Page MenuHomeFreeBSD

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/CHANGES b/CHANGES
index 67a6bd233816..c8662c392a7f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,13179 +1,13250 @@
OpenSSL CHANGES
_______________
This is a high-level summary of the most important changes.
For a full list of changes, see the git commit log; for example,
https://github.com/openssl/openssl/commits/ and pick the appropriate
release branch.
+ Changes between 1.1.1b and 1.1.1c [28 May 2019]
+
+ *) Add build tests for C++. These are generated files that only do one
+ thing, to include one public OpenSSL head file each. This tests that
+ the public header files can be usefully included in a C++ application.
+
+ This test isn't enabled by default. It can be enabled with the option
+ 'enable-buildtest-c++'.
+ [Richard Levitte]
+
+ *) Enable SHA3 pre-hashing for ECDSA and DSA.
+ [Patrick Steuer]
+
+ *) Change the default RSA, DSA and DH size to 2048 bit instead of 1024.
+ This changes the size when using the genpkey app when no size is given. It
+ fixes an omission in earlier changes that changed all RSA, DSA and DH
+ generation apps to use 2048 bits by default.
+ [Kurt Roeckx]
+
+ *) Reorganize the manual pages to consistently have RETURN VALUES,
+ EXAMPLES, SEE ALSO and HISTORY come in that order, and adjust
+ util/fix-doc-nits accordingly.
+ [Paul Yang, Joshua Lock]
+
+ *) Add the missing accessor EVP_PKEY_get0_engine()
+ [Matt Caswell]
+
+ *) Have apps like 's_client' and 's_server' output the signature scheme
+ along with other cipher suite parameters when debugging.
+ [Lorinczy Zsigmond]
+
+ *) Make OPENSSL_config() error agnostic again.
+ [Richard Levitte]
+
+ *) Do the error handling in RSA decryption constant time.
+ [Bernd Edlinger]
+
+ *) Prevent over long nonces in ChaCha20-Poly1305.
+
+ ChaCha20-Poly1305 is an AEAD cipher, and requires a unique nonce input
+ for every encryption operation. RFC 7539 specifies that the nonce value
+ (IV) should be 96 bits (12 bytes). OpenSSL allows a variable nonce length
+ and front pads the nonce with 0 bytes if it is less than 12
+ bytes. However it also incorrectly allows a nonce to be set of up to 16
+ bytes. In this case only the last 12 bytes are significant and any
+ additional leading bytes are ignored.
+
+ It is a requirement of using this cipher that nonce values are
+ unique. Messages encrypted using a reused nonce value are susceptible to
+ serious confidentiality and integrity attacks. If an application changes
+ the default nonce length to be longer than 12 bytes and then makes a
+ change to the leading bytes of the nonce expecting the new value to be a
+ new unique nonce then such an application could inadvertently encrypt
+ messages with a reused nonce.
+
+ Additionally the ignored bytes in a long nonce are not covered by the
+ integrity guarantee of this cipher. Any application that relies on the
+ integrity of these ignored leading bytes of a long nonce may be further
+ affected. Any OpenSSL internal use of this cipher, including in SSL/TLS,
+ is safe because no such use sets such a long nonce value. However user
+ applications that use this cipher directly and set a non-default nonce
+ length to be longer than 12 bytes may be vulnerable.
+
+ This issue was reported to OpenSSL on 16th of March 2019 by Joran Dirk
+ Greef of Ronomon.
+ (CVE-2019-1543)
+ [Matt Caswell]
+
+ *) Ensure that SM2 only uses SM3 as digest algorithm
+ [Paul Yang]
+
Changes between 1.1.1a and 1.1.1b [26 Feb 2019]
*) Added SCA hardening for modular field inversion in EC_GROUP through
a new dedicated field_inv() pointer in EC_METHOD.
This also addresses a leakage affecting conversions from projective
to affine coordinates.
[Billy Bob Brumley, Nicola Tuveri]
*) Change the info callback signals for the start and end of a post-handshake
message exchange in TLSv1.3. In 1.1.1/1.1.1a we used SSL_CB_HANDSHAKE_START
and SSL_CB_HANDSHAKE_DONE. Experience has shown that many applications get
confused by this and assume that a TLSv1.2 renegotiation has started. This
can break KeyUpdate handling. Instead we no longer signal the start and end
of a post handshake message exchange (although the messages themselves are
still signalled). This could break some applications that were expecting
the old signals. However without this KeyUpdate is not usable for many
applications.
[Matt Caswell]
*) Fix a bug in the computation of the endpoint-pair shared secret used
by DTLS over SCTP. This breaks interoperability with older versions
of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2. There is a runtime
switch SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG (off by default) enabling
interoperability with such broken implementations. However, enabling
this switch breaks interoperability with correct implementations.
*) Fix a use after free bug in d2i_X509_PUBKEY when overwriting a
re-used X509_PUBKEY object if the second PUBKEY is malformed.
[Bernd Edlinger]
*) Move strictness check from EVP_PKEY_asn1_new() to EVP_PKEY_asn1_add0().
[Richard Levitte]
*) Remove the 'dist' target and add a tarball building script. The
'dist' target has fallen out of use, and it shouldn't be
necessary to configure just to create a source distribution.
[Richard Levitte]
Changes between 1.1.1 and 1.1.1a [20 Nov 2018]
*) Timing vulnerability in DSA signature generation
The OpenSSL DSA signature algorithm has been shown to be vulnerable to a
timing side channel attack. An attacker could use variations in the signing
algorithm to recover the private key.
This issue was reported to OpenSSL on 16th October 2018 by Samuel Weiser.
(CVE-2018-0734)
[Paul Dale]
*) Timing vulnerability in ECDSA signature generation
The OpenSSL ECDSA signature algorithm has been shown to be vulnerable to a
timing side channel attack. An attacker could use variations in the signing
algorithm to recover the private key.
This issue was reported to OpenSSL on 25th October 2018 by Samuel Weiser.
(CVE-2018-0735)
[Paul Dale]
*) Added EVP_PKEY_ECDH_KDF_X9_63 and ecdh_KDF_X9_63() as replacements for
the EVP_PKEY_ECDH_KDF_X9_62 KDF type and ECDH_KDF_X9_62(). The old names
are retained for backwards compatibility.
[Antoine Salon]
*) Fixed the issue that RAND_add()/RAND_seed() silently discards random input
if its length exceeds 4096 bytes. The limit has been raised to a buffer size
of two gigabytes and the error handling improved.
This issue was reported to OpenSSL by Dr. Falko Strenzke. It has been
categorized as a normal bug, not a security issue, because the DRBG reseeds
automatically and is fully functional even without additional randomness
provided by the application.
Changes between 1.1.0i and 1.1.1 [11 Sep 2018]
*) Add a new ClientHello callback. Provides a callback interface that gives
the application the ability to adjust the nascent SSL object at the
earliest stage of ClientHello processing, immediately after extensions have
been collected but before they have been processed. In particular, this
callback can adjust the supported TLS versions in response to the contents
of the ClientHello
[Benjamin Kaduk]
*) Add SM2 base algorithm support.
[Jack Lloyd]
*) s390x assembly pack: add (improved) hardware-support for the following
cryptographic primitives: sha3, shake, aes-gcm, aes-ccm, aes-ctr, aes-ofb,
aes-cfb/cfb8, aes-ecb.
[Patrick Steuer]
*) Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str
parameter is no longer accepted, as it leads to a corrupt table. NULL
pem_str is reserved for alias entries only.
[Richard Levitte]
*) Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder
step for prime curves. The new implementation is based on formulae from
differential addition-and-doubling in homogeneous projective coordinates
from Izu-Takagi "A fast parallel elliptic curve multiplication resistant
against side channel attacks" and Brier-Joye "Weierstrass Elliptic Curves
and Side-Channel Attacks" Eq. (8) for y-coordinate recovery, modified
to work in projective coordinates.
[Billy Bob Brumley, Nicola Tuveri]
*) Change generating and checking of primes so that the error rate of not
being prime depends on the intended use based on the size of the input.
For larger primes this will result in more rounds of Miller-Rabin.
The maximal error rate for primes with more than 1080 bits is lowered
to 2^-128.
[Kurt Roeckx, Annie Yousar]
*) Increase the number of Miller-Rabin rounds for DSA key generating to 64.
[Kurt Roeckx]
*) The 'tsget' script is renamed to 'tsget.pl', to avoid confusion when
moving between systems, and to avoid confusion when a Windows build is
done with mingw vs with MSVC. For POSIX installs, there's still a
symlink or copy named 'tsget' to avoid that confusion as well.
[Richard Levitte]
*) Revert blinding in ECDSA sign and instead make problematic addition
length-invariant. Switch even to fixed-length Montgomery multiplication.
[Andy Polyakov]
*) Use the new ec_scalar_mul_ladder scaffold to implement a specialized ladder
step for binary curves. The new implementation is based on formulae from
differential addition-and-doubling in mixed Lopez-Dahab projective
coordinates, modified to independently blind the operands.
[Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri]
*) Add a scaffold to optionally enhance the Montgomery ladder implementation
for `ec_scalar_mul_ladder` (formerly `ec_mul_consttime`) allowing
EC_METHODs to implement their own specialized "ladder step", to take
advantage of more favorable coordinate systems or more efficient
differential addition-and-doubling algorithms.
[Billy Bob Brumley, Sohaib ul Hassan, Nicola Tuveri]
*) Modified the random device based seed sources to keep the relevant
file descriptors open rather than reopening them on each access.
This allows such sources to operate in a chroot() jail without
the associated device nodes being available. This behaviour can be
controlled using RAND_keep_random_devices_open().
[Paul Dale]
*) Numerous side-channel attack mitigations have been applied. This may have
performance impacts for some algorithms for the benefit of improved
security. Specific changes are noted in this change log by their respective
authors.
[Matt Caswell]
*) AIX shared library support overhaul. Switch to AIX "natural" way of
handling shared libraries, which means collecting shared objects of
different versions and bitnesses in one common archive. This allows to
mitigate conflict between 1.0 and 1.1 side-by-side installations. It
doesn't affect the way 3rd party applications are linked, only how
multi-version installation is managed.
[Andy Polyakov]
*) Make ec_group_do_inverse_ord() more robust and available to other
EC cryptosystems, so that irrespective of BN_FLG_CONSTTIME, SCA
mitigations are applied to the fallback BN_mod_inverse().
When using this function rather than BN_mod_inverse() directly, new
EC cryptosystem implementations are then safer-by-default.
[Billy Bob Brumley]
*) Add coordinate blinding for EC_POINT and implement projective
coordinate blinding for generic prime curves as a countermeasure to
chosen point SCA attacks.
[Sohaib ul Hassan, Nicola Tuveri, Billy Bob Brumley]
*) Add blinding to ECDSA and DSA signatures to protect against side channel
attacks discovered by Keegan Ryan (NCC Group).
[Matt Caswell]
*) Enforce checking in the pkeyutl command line app to ensure that the input
length does not exceed the maximum supported digest length when performing
a sign, verify or verifyrecover operation.
[Matt Caswell]
*) SSL_MODE_AUTO_RETRY is enabled by default. Applications that use blocking
I/O in combination with something like select() or poll() will hang. This
can be turned off again using SSL_CTX_clear_mode().
Many applications do not properly handle non-application data records, and
TLS 1.3 sends more of such records. Setting SSL_MODE_AUTO_RETRY works
around the problems in those applications, but can also break some.
It's recommended to read the manpages about SSL_read(), SSL_write(),
SSL_get_error(), SSL_shutdown(), SSL_CTX_set_mode() and
SSL_CTX_set_read_ahead() again.
[Kurt Roeckx]
*) When unlocking a pass phrase protected PEM file or PKCS#8 container, we
now allow empty (zero character) pass phrases.
[Richard Levitte]
*) Apply blinding to binary field modular inversion and remove patent
pending (OPENSSL_SUN_GF2M_DIV) BN_GF2m_mod_div implementation.
[Billy Bob Brumley]
*) Deprecate ec2_mult.c and unify scalar multiplication code paths for
binary and prime elliptic curves.
[Billy Bob Brumley]
*) Remove ECDSA nonce padding: EC_POINT_mul is now responsible for
constant time fixed point multiplication.
[Billy Bob Brumley]
*) Revise elliptic curve scalar multiplication with timing attack
defenses: ec_wNAF_mul redirects to a constant time implementation
when computing fixed point and variable point multiplication (which
in OpenSSL are mostly used with secret scalars in keygen, sign,
ECDH derive operations).
[Billy Bob Brumley, Nicola Tuveri, Cesar Pereida García,
Sohaib ul Hassan]
*) Updated CONTRIBUTING
[Rich Salz]
*) Updated DRBG / RAND to request nonce and additional low entropy
randomness from the system.
[Matthias St. Pierre]
*) Updated 'openssl rehash' to use OpenSSL consistent default.
[Richard Levitte]
*) Moved the load of the ssl_conf module to libcrypto, which helps
loading engines that libssl uses before libssl is initialised.
[Matt Caswell]
*) Added EVP_PKEY_sign() and EVP_PKEY_verify() for EdDSA
[Matt Caswell]
*) Fixed X509_NAME_ENTRY_set to get multi-valued RDNs right in all cases.
[Ingo Schwarze, Rich Salz]
*) Added output of accepting IP address and port for 'openssl s_server'
[Richard Levitte]
*) Added a new API for TLSv1.3 ciphersuites:
SSL_CTX_set_ciphersuites()
SSL_set_ciphersuites()
[Matt Caswell]
*) Memory allocation failures consistenly add an error to the error
stack.
[Rich Salz]
*) Don't use OPENSSL_ENGINES and OPENSSL_CONF environment values
in libcrypto when run as setuid/setgid.
[Bernd Edlinger]
*) Load any config file by default when libssl is used.
[Matt Caswell]
*) Added new public header file <openssl/rand_drbg.h> and documentation
for the RAND_DRBG API. See manual page RAND_DRBG(7) for an overview.
[Matthias St. Pierre]
*) QNX support removed (cannot find contributors to get their approval
for the license change).
[Rich Salz]
*) TLSv1.3 replay protection for early data has been implemented. See the
SSL_read_early_data() man page for further details.
[Matt Caswell]
*) Separated TLSv1.3 ciphersuite configuration out from TLSv1.2 ciphersuite
configuration. TLSv1.3 ciphersuites are not compatible with TLSv1.2 and
below. Similarly TLSv1.2 ciphersuites are not compatible with TLSv1.3.
In order to avoid issues where legacy TLSv1.2 ciphersuite configuration
would otherwise inadvertently disable all TLSv1.3 ciphersuites the
configuration has been separated out. See the ciphers man page or the
SSL_CTX_set_ciphersuites() man page for more information.
[Matt Caswell]
*) On POSIX (BSD, Linux, ...) systems the ocsp(1) command running
in responder mode now supports the new "-multi" option, which
spawns the specified number of child processes to handle OCSP
requests. The "-timeout" option now also limits the OCSP
responder's patience to wait to receive the full client request
on a newly accepted connection. Child processes are respawned
as needed, and the CA index file is automatically reloaded
when changed. This makes it possible to run the "ocsp" responder
as a long-running service, making the OpenSSL CA somewhat more
feature-complete. In this mode, most diagnostic messages logged
after entering the event loop are logged via syslog(3) rather than
written to stderr.
[Viktor Dukhovni]
*) Added support for X448 and Ed448. Heavily based on original work by
Mike Hamburg.
[Matt Caswell]
*) Extend OSSL_STORE with capabilities to search and to narrow the set of
objects loaded. This adds the functions OSSL_STORE_expect() and
OSSL_STORE_find() as well as needed tools to construct searches and
get the search data out of them.
[Richard Levitte]
*) Support for TLSv1.3 added. Note that users upgrading from an earlier
version of OpenSSL should review their configuration settings to ensure
that they are still appropriate for TLSv1.3. For further information see:
https://wiki.openssl.org/index.php/TLS1.3
[Matt Caswell]
*) Grand redesign of the OpenSSL random generator
The default RAND method now utilizes an AES-CTR DRBG according to
NIST standard SP 800-90Ar1. The new random generator is essentially
a port of the default random generator from the OpenSSL FIPS 2.0
object module. It is a hybrid deterministic random bit generator
using an AES-CTR bit stream and which seeds and reseeds itself
automatically using trusted system entropy sources.
Some of its new features are:
o Support for multiple DRBG instances with seed chaining.
o The default RAND method makes use of a DRBG.
o There is a public and private DRBG instance.
o The DRBG instances are fork-safe.
o Keep all global DRBG instances on the secure heap if it is enabled.
o The public and private DRBG instance are per thread for lock free
operation
[Paul Dale, Benjamin Kaduk, Kurt Roeckx, Rich Salz, Matthias St. Pierre]
*) Changed Configure so it only says what it does and doesn't dump
so much data. Instead, ./configdata.pm should be used as a script
to display all sorts of configuration data.
[Richard Levitte]
*) Added processing of "make variables" to Configure.
[Richard Levitte]
*) Added SHA512/224 and SHA512/256 algorithm support.
[Paul Dale]
*) The last traces of Netware support, first removed in 1.1.0, have
now been removed.
[Rich Salz]
*) Get rid of Makefile.shared, and in the process, make the processing
of certain files (rc.obj, or the .def/.map/.opt files produced from
the ordinal files) more visible and hopefully easier to trace and
debug (or make silent).
[Richard Levitte]
*) Make it possible to have environment variable assignments as
arguments to config / Configure.
[Richard Levitte]
*) Add multi-prime RSA (RFC 8017) support.
[Paul Yang]
*) Add SM3 implemented according to GB/T 32905-2016
[ Jack Lloyd <jack.lloyd@ribose.com>,
Ronald Tse <ronald.tse@ribose.com>,
Erick Borsboom <erick.borsboom@ribose.com> ]
*) Add 'Maximum Fragment Length' TLS extension negotiation and support
as documented in RFC6066.
Based on a patch from Tomasz Moń
[Filipe Raimundo da Silva]
*) Add SM4 implemented according to GB/T 32907-2016.
[ Jack Lloyd <jack.lloyd@ribose.com>,
Ronald Tse <ronald.tse@ribose.com>,
Erick Borsboom <erick.borsboom@ribose.com> ]
*) Reimplement -newreq-nodes and ERR_error_string_n; the
original author does not agree with the license change.
[Rich Salz]
*) Add ARIA AEAD TLS support.
[Jon Spillett]
*) Some macro definitions to support VS6 have been removed. Visual
Studio 6 has not worked since 1.1.0
[Rich Salz]
*) Add ERR_clear_last_mark(), to allow callers to clear the last mark
without clearing the errors.
[Richard Levitte]
*) Add "atfork" functions. If building on a system that without
pthreads, see doc/man3/OPENSSL_fork_prepare.pod for application
requirements. The RAND facility now uses/requires this.
[Rich Salz]
*) Add SHA3.
[Andy Polyakov]
*) The UI API becomes a permanent and integral part of libcrypto, i.e.
not possible to disable entirely. However, it's still possible to
disable the console reading UI method, UI_OpenSSL() (use UI_null()
as a fallback).
To disable, configure with 'no-ui-console'. 'no-ui' is still
possible to use as an alias. Check at compile time with the
macro OPENSSL_NO_UI_CONSOLE. The macro OPENSSL_NO_UI is still
possible to check and is an alias for OPENSSL_NO_UI_CONSOLE.
[Richard Levitte]
*) Add a STORE module, which implements a uniform and URI based reader of
stores that can contain keys, certificates, CRLs and numerous other
objects. The main API is loosely based on a few stdio functions,
and includes OSSL_STORE_open, OSSL_STORE_load, OSSL_STORE_eof,
OSSL_STORE_error and OSSL_STORE_close.
The implementation uses backends called "loaders" to implement arbitrary
URI schemes. There is one built in "loader" for the 'file' scheme.
[Richard Levitte]
*) Add devcrypto engine. This has been implemented against cryptodev-linux,
then adjusted to work on FreeBSD 8.4 as well.
Enable by configuring with 'enable-devcryptoeng'. This is done by default
on BSD implementations, as cryptodev.h is assumed to exist on all of them.
[Richard Levitte]
*) Module names can prefixed with OSSL_ or OPENSSL_. This affects
util/mkerr.pl, which is adapted to allow those prefixes, leading to
error code calls like this:
OSSL_FOOerr(OSSL_FOO_F_SOMETHING, OSSL_FOO_R_WHATEVER);
With this change, we claim the namespaces OSSL and OPENSSL in a manner
that can be encoded in C. For the foreseeable future, this will only
affect new modules.
[Richard Levitte and Tim Hudson]
*) Removed BSD cryptodev engine.
[Rich Salz]
*) Add a build target 'build_all_generated', to build all generated files
and only that. This can be used to prepare everything that requires
things like perl for a system that lacks perl and then move everything
to that system and do the rest of the build there.
[Richard Levitte]
*) In the UI interface, make it possible to duplicate the user data. This
can be used by engines that need to retain the data for a longer time
than just the call where this user data is passed.
[Richard Levitte]
*) Ignore the '-named_curve auto' value for compatibility of applications
with OpenSSL 1.0.2.
[Tomas Mraz <tmraz@fedoraproject.org>]
*) Fragmented SSL/TLS alerts are no longer accepted. An alert message is 2
bytes long. In theory it is permissible in SSLv3 - TLSv1.2 to fragment such
alerts across multiple records (some of which could be empty). In practice
it make no sense to send an empty alert record, or to fragment one. TLSv1.3
prohibts this altogether and other libraries (BoringSSL, NSS) do not
support this at all. Supporting it adds significant complexity to the
record layer, and its removal is unlikely to cause inter-operability
issues.
[Matt Caswell]
*) Add the ASN.1 types INT32, UINT32, INT64, UINT64 and variants prefixed
with Z. These are meant to replace LONG and ZLONG and to be size safe.
The use of LONG and ZLONG is discouraged and scheduled for deprecation
in OpenSSL 1.2.0.
[Richard Levitte]
*) Add the 'z' and 'j' modifiers to BIO_printf() et al formatting string,
'z' is to be used for [s]size_t, and 'j' - with [u]int64_t.
[Richard Levitte, Andy Polyakov]
*) Add EC_KEY_get0_engine(), which does for EC_KEY what RSA_get0_engine()
does for RSA, etc.
[Richard Levitte]
*) Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target
platform rather than 'mingw'.
[Richard Levitte]
*) The functions X509_STORE_add_cert and X509_STORE_add_crl return
success if they are asked to add an object which already exists
in the store. This change cascades to other functions which load
certificates and CRLs.
[Paul Dale]
*) x86_64 assembly pack: annotate code with DWARF CFI directives to
facilitate stack unwinding even from assembly subroutines.
[Andy Polyakov]
*) Remove VAX C specific definitions of OPENSSL_EXPORT, OPENSSL_EXTERN.
Also remove OPENSSL_GLOBAL entirely, as it became a no-op.
[Richard Levitte]
*) Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c.
VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1,
which is the minimum version we support.
[Richard Levitte]
*) Certificate time validation (X509_cmp_time) enforces stricter
compliance with RFC 5280. Fractional seconds and timezone offsets
are no longer allowed.
[Emilia Käsper]
*) Add support for ARIA
[Paul Dale]
*) s_client will now send the Server Name Indication (SNI) extension by
default unless the new "-noservername" option is used. The server name is
based on the host provided to the "-connect" option unless overridden by
using "-servername".
[Matt Caswell]
*) Add support for SipHash
[Todd Short]
*) OpenSSL now fails if it receives an unrecognised record type in TLS1.0
or TLS1.1. Previously this only happened in SSLv3 and TLS1.2. This is to
prevent issues where no progress is being made and the peer continually
sends unrecognised record types, using up resources processing them.
[Matt Caswell]
*) 'openssl passwd' can now produce SHA256 and SHA512 based output,
using the algorithm defined in
https://www.akkadia.org/drepper/SHA-crypt.txt
[Richard Levitte]
*) Heartbeat support has been removed; the ABI is changed for now.
[Richard Levitte, Rich Salz]
*) Support for SSL_OP_NO_ENCRYPT_THEN_MAC in SSL_CONF_cmd.
[Emilia Käsper]
*) The RSA "null" method, which was partially supported to avoid patent
issues, has been replaced to always returns NULL.
[Rich Salz]
Changes between 1.1.0h and 1.1.0i [xx XXX xxxx]
*) Client DoS due to large DH parameter
During key agreement in a TLS handshake using a DH(E) based ciphersuite a
malicious server can send a very large prime value to the client. This will
cause the client to spend an unreasonably long period of time generating a
key for this prime resulting in a hang until the client has finished. This
could be exploited in a Denial Of Service attack.
This issue was reported to OpenSSL on 5th June 2018 by Guido Vranken
(CVE-2018-0732)
[Guido Vranken]
*) Cache timing vulnerability in RSA Key Generation
The OpenSSL RSA Key generation algorithm has been shown to be vulnerable to
a cache timing side channel attack. An attacker with sufficient access to
mount cache timing attacks during the RSA key generation process could
recover the private key.
This issue was reported to OpenSSL on 4th April 2018 by Alejandro Cabrera
Aldaya, Billy Brumley, Cesar Pereida Garcia and Luis Manuel Alvarez Tapia.
(CVE-2018-0737)
[Billy Brumley]
*) Make EVP_PKEY_asn1_new() a bit stricter about its input. A NULL pem_str
parameter is no longer accepted, as it leads to a corrupt table. NULL
pem_str is reserved for alias entries only.
[Richard Levitte]
*) Revert blinding in ECDSA sign and instead make problematic addition
length-invariant. Switch even to fixed-length Montgomery multiplication.
[Andy Polyakov]
*) Change generating and checking of primes so that the error rate of not
being prime depends on the intended use based on the size of the input.
For larger primes this will result in more rounds of Miller-Rabin.
The maximal error rate for primes with more than 1080 bits is lowered
to 2^-128.
[Kurt Roeckx, Annie Yousar]
*) Increase the number of Miller-Rabin rounds for DSA key generating to 64.
[Kurt Roeckx]
*) Add blinding to ECDSA and DSA signatures to protect against side channel
attacks discovered by Keegan Ryan (NCC Group).
[Matt Caswell]
*) When unlocking a pass phrase protected PEM file or PKCS#8 container, we
now allow empty (zero character) pass phrases.
[Richard Levitte]
*) Certificate time validation (X509_cmp_time) enforces stricter
compliance with RFC 5280. Fractional seconds and timezone offsets
are no longer allowed.
[Emilia Käsper]
*) Fixed a text canonicalisation bug in CMS
Where a CMS detached signature is used with text content the text goes
through a canonicalisation process first prior to signing or verifying a
signature. This process strips trailing space at the end of lines, converts
line terminators to CRLF and removes additional trailing line terminators
at the end of a file. A bug in the canonicalisation process meant that
some characters, such as form-feed, were incorrectly treated as whitespace
and removed. This is contrary to the specification (RFC5485). This fix
could mean that detached text data signed with an earlier version of
OpenSSL 1.1.0 may fail to verify using the fixed version, or text data
signed with a fixed OpenSSL may fail to verify with an earlier version of
OpenSSL 1.1.0. A workaround is to only verify the canonicalised text data
and use the "-binary" flag (for the "cms" command line application) or set
the SMIME_BINARY/PKCS7_BINARY/CMS_BINARY flags (if using CMS_verify()).
[Matt Caswell]
Changes between 1.1.0g and 1.1.0h [27 Mar 2018]
*) Constructed ASN.1 types with a recursive definition could exceed the stack
Constructed ASN.1 types with a recursive definition (such as can be found
in PKCS7) could eventually exceed the stack given malicious input with
excessive recursion. This could result in a Denial Of Service attack. There
are no such structures used within SSL/TLS that come from untrusted sources
so this is considered safe.
This issue was reported to OpenSSL on 4th January 2018 by the OSS-fuzz
project.
(CVE-2018-0739)
[Matt Caswell]
*) Incorrect CRYPTO_memcmp on HP-UX PA-RISC
Because of an implementation bug the PA-RISC CRYPTO_memcmp function is
effectively reduced to only comparing the least significant bit of each
byte. This allows an attacker to forge messages that would be considered as
authenticated in an amount of tries lower than that guaranteed by the
security claims of the scheme. The module can only be compiled by the
HP-UX assembler, so that only HP-UX PA-RISC targets are affected.
This issue was reported to OpenSSL on 2nd March 2018 by Peter Waltenberg
(IBM).
(CVE-2018-0733)
[Andy Polyakov]
*) Add a build target 'build_all_generated', to build all generated files
and only that. This can be used to prepare everything that requires
things like perl for a system that lacks perl and then move everything
to that system and do the rest of the build there.
[Richard Levitte]
*) Backport SSL_OP_NO_RENGOTIATION
OpenSSL 1.0.2 and below had the ability to disable renegotiation using the
(undocumented) SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS flag. Due to the opacity
changes this is no longer possible in 1.1.0. Therefore the new
SSL_OP_NO_RENEGOTIATION option from 1.1.1-dev has been backported to
1.1.0 to provide equivalent functionality.
Note that if an application built against 1.1.0h headers (or above) is run
using an older version of 1.1.0 (prior to 1.1.0h) then the option will be
accepted but nothing will happen, i.e. renegotiation will not be prevented.
[Matt Caswell]
*) Removed the OS390-Unix config target. It relied on a script that doesn't
exist.
[Rich Salz]
*) rsaz_1024_mul_avx2 overflow bug on x86_64
There is an overflow bug in the AVX2 Montgomery multiplication procedure
used in exponentiation with 1024-bit moduli. No EC algorithms are affected.
Analysis suggests that attacks against RSA and DSA as a result of this
defect would be very difficult to perform and are not believed likely.
Attacks against DH1024 are considered just feasible, because most of the
work necessary to deduce information about a private key may be performed
offline. The amount of resources required for such an attack would be
significant. However, for an attack on TLS to be meaningful, the server
would have to share the DH1024 private key among multiple clients, which is
no longer an option since CVE-2016-0701.
This only affects processors that support the AVX2 but not ADX extensions
like Intel Haswell (4th generation).
This issue was reported to OpenSSL by David Benjamin (Google). The issue
was originally found via the OSS-Fuzz project.
(CVE-2017-3738)
[Andy Polyakov]
Changes between 1.1.0f and 1.1.0g [2 Nov 2017]
*) bn_sqrx8x_internal carry bug on x86_64
There is a carry propagating bug in the x86_64 Montgomery squaring
procedure. No EC algorithms are affected. Analysis suggests that attacks
against RSA and DSA as a result of this defect would be very difficult to
perform and are not believed likely. Attacks against DH are considered just
feasible (although very difficult) because most of the work necessary to
deduce information about a private key may be performed offline. The amount
of resources required for such an attack would be very significant and
likely only accessible to a limited number of attackers. An attacker would
additionally need online access to an unpatched system using the target
private key in a scenario with persistent DH parameters and a private
key that is shared between multiple clients.
This only affects processors that support the BMI1, BMI2 and ADX extensions
like Intel Broadwell (5th generation) and later or AMD Ryzen.
This issue was reported to OpenSSL by the OSS-Fuzz project.
(CVE-2017-3736)
[Andy Polyakov]
*) Malformed X.509 IPAddressFamily could cause OOB read
If an X.509 certificate has a malformed IPAddressFamily extension,
OpenSSL could do a one-byte buffer overread. The most likely result
would be an erroneous display of the certificate in text format.
This issue was reported to OpenSSL by the OSS-Fuzz project.
(CVE-2017-3735)
[Rich Salz]
Changes between 1.1.0e and 1.1.0f [25 May 2017]
*) Have 'config' recognise 64-bit mingw and choose 'mingw64' as the target
platform rather than 'mingw'.
[Richard Levitte]
*) Remove the VMS-specific reimplementation of gmtime from crypto/o_times.c.
VMS C's RTL has a fully up to date gmtime() and gmtime_r() since V7.1,
which is the minimum version we support.
[Richard Levitte]
Changes between 1.1.0d and 1.1.0e [16 Feb 2017]
*) Encrypt-Then-Mac renegotiation crash
During a renegotiation handshake if the Encrypt-Then-Mac extension is
negotiated where it was not in the original handshake (or vice-versa) then
this can cause OpenSSL to crash (dependant on ciphersuite). Both clients
and servers are affected.
This issue was reported to OpenSSL by Joe Orton (Red Hat).
(CVE-2017-3733)
[Matt Caswell]
Changes between 1.1.0c and 1.1.0d [26 Jan 2017]
*) Truncated packet could crash via OOB read
If one side of an SSL/TLS path is running on a 32-bit host and a specific
cipher is being used, then a truncated packet can cause that host to
perform an out-of-bounds read, usually resulting in a crash.
This issue was reported to OpenSSL by Robert Święcki of Google.
(CVE-2017-3731)
[Andy Polyakov]
*) Bad (EC)DHE parameters cause a client crash
If a malicious server supplies bad parameters for a DHE or ECDHE key
exchange then this can result in the client attempting to dereference a
NULL pointer leading to a client crash. This could be exploited in a Denial
of Service attack.
This issue was reported to OpenSSL by Guido Vranken.
(CVE-2017-3730)
[Matt Caswell]
*) BN_mod_exp may produce incorrect results on x86_64
There is a carry propagating bug in the x86_64 Montgomery squaring
procedure. No EC algorithms are affected. Analysis suggests that attacks
against RSA and DSA as a result of this defect would be very difficult to
perform and are not believed likely. Attacks against DH are considered just
feasible (although very difficult) because most of the work necessary to
deduce information about a private key may be performed offline. The amount
of resources required for such an attack would be very significant and
likely only accessible to a limited number of attackers. An attacker would
additionally need online access to an unpatched system using the target
private key in a scenario with persistent DH parameters and a private
key that is shared between multiple clients. For example this can occur by
default in OpenSSL DHE based SSL/TLS ciphersuites. Note: This issue is very
similar to CVE-2015-3193 but must be treated as a separate problem.
This issue was reported to OpenSSL by the OSS-Fuzz project.
(CVE-2017-3732)
[Andy Polyakov]
Changes between 1.1.0b and 1.1.0c [10 Nov 2016]
*) ChaCha20/Poly1305 heap-buffer-overflow
TLS connections using *-CHACHA20-POLY1305 ciphersuites are susceptible to
a DoS attack by corrupting larger payloads. This can result in an OpenSSL
crash. This issue is not considered to be exploitable beyond a DoS.
This issue was reported to OpenSSL by Robert Święcki (Google Security Team)
(CVE-2016-7054)
[Richard Levitte]
*) CMS Null dereference
Applications parsing invalid CMS structures can crash with a NULL pointer
dereference. This is caused by a bug in the handling of the ASN.1 CHOICE
type in OpenSSL 1.1.0 which can result in a NULL value being passed to the
structure callback if an attempt is made to free certain invalid encodings.
Only CHOICE structures using a callback which do not handle NULL value are
affected.
This issue was reported to OpenSSL by Tyler Nighswander of ForAllSecure.
(CVE-2016-7053)
[Stephen Henson]
*) Montgomery multiplication may produce incorrect results
There is a carry propagating bug in the Broadwell-specific Montgomery
multiplication procedure that handles input lengths divisible by, but
longer than 256 bits. Analysis suggests that attacks against RSA, DSA
and DH private keys are impossible. This is because the subroutine in
question is not used in operations with the private key itself and an input
of the attacker's direct choice. Otherwise the bug can manifest itself as
transient authentication and key negotiation failures or reproducible
erroneous outcome of public-key operations with specially crafted input.
Among EC algorithms only Brainpool P-512 curves are affected and one
presumably can attack ECDH key negotiation. Impact was not analyzed in
detail, because pre-requisites for attack are considered unlikely. Namely
multiple clients have to choose the curve in question and the server has to
share the private key among them, neither of which is default behaviour.
Even then only clients that chose the curve will be affected.
This issue was publicly reported as transient failures and was not
initially recognized as a security issue. Thanks to Richard Morgan for
providing reproducible case.
(CVE-2016-7055)
[Andy Polyakov]
*) Removed automatic addition of RPATH in shared libraries and executables,
as this was a remainder from OpenSSL 1.0.x and isn't needed any more.
[Richard Levitte]
Changes between 1.1.0a and 1.1.0b [26 Sep 2016]
*) Fix Use After Free for large message sizes
The patch applied to address CVE-2016-6307 resulted in an issue where if a
message larger than approx 16k is received then the underlying buffer to
store the incoming message is reallocated and moved. Unfortunately a
dangling pointer to the old location is left which results in an attempt to
write to the previously freed location. This is likely to result in a
crash, however it could potentially lead to execution of arbitrary code.
This issue only affects OpenSSL 1.1.0a.
This issue was reported to OpenSSL by Robert Święcki.
(CVE-2016-6309)
[Matt Caswell]
Changes between 1.1.0 and 1.1.0a [22 Sep 2016]
*) OCSP Status Request extension unbounded memory growth
A malicious client can send an excessively large OCSP Status Request
extension. If that client continually requests renegotiation, sending a
large OCSP Status Request extension each time, then there will be unbounded
memory growth on the server. This will eventually lead to a Denial Of
Service attack through memory exhaustion. Servers with a default
configuration are vulnerable even if they do not support OCSP. Builds using
the "no-ocsp" build time option are not affected.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
(CVE-2016-6304)
[Matt Caswell]
*) SSL_peek() hang on empty record
OpenSSL 1.1.0 SSL/TLS will hang during a call to SSL_peek() if the peer
sends an empty record. This could be exploited by a malicious peer in a
Denial Of Service attack.
This issue was reported to OpenSSL by Alex Gaynor.
(CVE-2016-6305)
[Matt Caswell]
*) Excessive allocation of memory in tls_get_message_header() and
dtls1_preprocess_fragment()
A (D)TLS message includes 3 bytes for its length in the header for the
message. This would allow for messages up to 16Mb in length. Messages of
this length are excessive and OpenSSL includes a check to ensure that a
peer is sending reasonably sized messages in order to avoid too much memory
being consumed to service a connection. A flaw in the logic of version
1.1.0 means that memory for the message is allocated too early, prior to
the excessive message length check. Due to way memory is allocated in
OpenSSL this could mean an attacker could force up to 21Mb to be allocated
to service a connection. This could lead to a Denial of Service through
memory exhaustion. However, the excessive message length check still takes
place, and this would cause the connection to immediately fail. Assuming
that the application calls SSL_free() on the failed connection in a timely
manner then the 21Mb of allocated memory will then be immediately freed
again. Therefore the excessive memory allocation will be transitory in
nature. This then means that there is only a security impact if:
1) The application does not call SSL_free() in a timely manner in the event
that the connection fails
or
2) The application is working in a constrained environment where there is
very little free memory
or
3) The attacker initiates multiple connection attempts such that there are
multiple connections in a state where memory has been allocated for the
connection; SSL_free() has not yet been called; and there is insufficient
memory to service the multiple requests.
Except in the instance of (1) above any Denial Of Service is likely to be
transitory because as soon as the connection fails the memory is
subsequently freed again in the SSL_free() call. However there is an
increased risk during this period of application crashes due to the lack of
memory - which would then mean a more serious Denial of Service.
This issue was reported to OpenSSL by Shi Lei (Gear Team, Qihoo 360 Inc.)
(CVE-2016-6307 and CVE-2016-6308)
[Matt Caswell]
*) solaris-x86-cc, i.e. 32-bit configuration with vendor compiler,
had to be removed. Primary reason is that vendor assembler can't
assemble our modules with -KPIC flag. As result it, assembly
support, was not even available as option. But its lack means
lack of side-channel resistant code, which is incompatible with
security by todays standards. Fortunately gcc is readily available
prepackaged option, which we firmly point at...
[Andy Polyakov]
Changes between 1.0.2h and 1.1.0 [25 Aug 2016]
*) Windows command-line tool supports UTF-8 opt-in option for arguments
and console input. Setting OPENSSL_WIN32_UTF8 environment variable
(to any value) allows Windows user to access PKCS#12 file generated
with Windows CryptoAPI and protected with non-ASCII password, as well
as files generated under UTF-8 locale on Linux also protected with
non-ASCII password.
[Andy Polyakov]
*) To mitigate the SWEET32 attack (CVE-2016-2183), 3DES cipher suites
have been disabled by default and removed from DEFAULT, just like RC4.
See the RC4 item below to re-enable both.
[Rich Salz]
*) The method for finding the storage location for the Windows RAND seed file
has changed. First we check %RANDFILE%. If that is not set then we check
the directories %HOME%, %USERPROFILE% and %SYSTEMROOT% in that order. If
all else fails we fall back to C:\.
[Matt Caswell]
*) The EVP_EncryptUpdate() function has had its return type changed from void
to int. A return of 0 indicates and error while a return of 1 indicates
success.
[Matt Caswell]
*) The flags RSA_FLAG_NO_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME and
DH_FLAG_NO_EXP_CONSTTIME which previously provided the ability to switch
off the constant time implementation for RSA, DSA and DH have been made
no-ops and deprecated.
[Matt Caswell]
*) Windows RAND implementation was simplified to only get entropy by
calling CryptGenRandom(). Various other RAND-related tickets
were also closed.
[Joseph Wylie Yandle, Rich Salz]
*) The stack and lhash API's were renamed to start with OPENSSL_SK_
and OPENSSL_LH_, respectively. The old names are available
with API compatibility. They new names are now completely documented.
[Rich Salz]
*) Unify TYPE_up_ref(obj) methods signature.
SSL_CTX_up_ref(), SSL_up_ref(), X509_up_ref(), EVP_PKEY_up_ref(),
X509_CRL_up_ref(), X509_OBJECT_up_ref_count() methods are now returning an
int (instead of void) like all others TYPE_up_ref() methods.
So now these methods also check the return value of CRYPTO_atomic_add(),
and the validity of object reference counter.
[fdasilvayy@gmail.com]
*) With Windows Visual Studio builds, the .pdb files are installed
alongside the installed libraries and executables. For a static
library installation, ossl_static.pdb is the associate compiler
generated .pdb file to be used when linking programs.
[Richard Levitte]
*) Remove openssl.spec. Packaging files belong with the packagers.
[Richard Levitte]
*) Automatic Darwin/OSX configuration has had a refresh, it will now
recognise x86_64 architectures automatically. You can still decide
to build for a different bitness with the environment variable
KERNEL_BITS (can be 32 or 64), for example:
KERNEL_BITS=32 ./config
[Richard Levitte]
*) Change default algorithms in pkcs8 utility to use PKCS#5 v2.0,
256 bit AES and HMAC with SHA256.
[Steve Henson]
*) Remove support for MIPS o32 ABI on IRIX (and IRIX only).
[Andy Polyakov]
*) Triple-DES ciphers have been moved from HIGH to MEDIUM.
[Rich Salz]
*) To enable users to have their own config files and build file templates,
Configure looks in the directory indicated by the environment variable
OPENSSL_LOCAL_CONFIG_DIR as well as the in-source Configurations/
directory. On VMS, OPENSSL_LOCAL_CONFIG_DIR is expected to be a logical
name and is used as is.
[Richard Levitte]
*) The following datatypes were made opaque: X509_OBJECT, X509_STORE_CTX,
X509_STORE, X509_LOOKUP, and X509_LOOKUP_METHOD. The unused type
X509_CERT_FILE_CTX was removed.
[Rich Salz]
*) "shared" builds are now the default. To create only static libraries use
the "no-shared" Configure option.
[Matt Caswell]
*) Remove the no-aes, no-hmac, no-rsa, no-sha and no-md5 Configure options.
All of these option have not worked for some while and are fundamental
algorithms.
[Matt Caswell]
*) Make various cleanup routines no-ops and mark them as deprecated. Most
global cleanup functions are no longer required because they are handled
via auto-deinit (see OPENSSL_init_crypto and OPENSSL_init_ssl man pages).
Explicitly de-initing can cause problems (e.g. where a library that uses
OpenSSL de-inits, but an application is still using it). The affected
functions are CONF_modules_free(), ENGINE_cleanup(), OBJ_cleanup(),
EVP_cleanup(), BIO_sock_cleanup(), CRYPTO_cleanup_all_ex_data(),
RAND_cleanup(), SSL_COMP_free_compression_methods(), ERR_free_strings() and
COMP_zlib_cleanup().
[Matt Caswell]
*) --strict-warnings no longer enables runtime debugging options
such as REF_DEBUG. Instead, debug options are automatically
enabled with '--debug' builds.
[Andy Polyakov, Emilia Käsper]
*) Made DH and DH_METHOD opaque. The structures for managing DH objects
have been moved out of the public header files. New functions for managing
these have been added.
[Matt Caswell]
*) Made RSA and RSA_METHOD opaque. The structures for managing RSA
objects have been moved out of the public header files. New
functions for managing these have been added.
[Richard Levitte]
*) Made DSA and DSA_METHOD opaque. The structures for managing DSA objects
have been moved out of the public header files. New functions for managing
these have been added.
[Matt Caswell]
*) Made BIO and BIO_METHOD opaque. The structures for managing BIOs have been
moved out of the public header files. New functions for managing these
have been added.
[Matt Caswell]
*) Removed no-rijndael as a config option. Rijndael is an old name for AES.
[Matt Caswell]
*) Removed the mk1mf build scripts.
[Richard Levitte]
*) Headers are now wrapped, if necessary, with OPENSSL_NO_xxx, so
it is always safe to #include a header now.
[Rich Salz]
*) Removed the aged BC-32 config and all its supporting scripts
[Richard Levitte]
*) Removed support for Ultrix, Netware, and OS/2.
[Rich Salz]
*) Add support for HKDF.
[Alessandro Ghedini]
*) Add support for blake2b and blake2s
[Bill Cox]
*) Added support for "pipelining". Ciphers that have the
EVP_CIPH_FLAG_PIPELINE flag set have a capability to process multiple
encryptions/decryptions simultaneously. There are currently no built-in
ciphers with this property but the expectation is that engines will be able
to offer it to significantly improve throughput. Support has been extended
into libssl so that multiple records for a single connection can be
processed in one go (for >=TLS 1.1).
[Matt Caswell]
*) Added the AFALG engine. This is an async capable engine which is able to
offload work to the Linux kernel. In this initial version it only supports
AES128-CBC. The kernel must be version 4.1.0 or greater.
[Catriona Lucey]
*) OpenSSL now uses a new threading API. It is no longer necessary to
set locking callbacks to use OpenSSL in a multi-threaded environment. There
are two supported threading models: pthreads and windows threads. It is
also possible to configure OpenSSL at compile time for "no-threads". The
old threading API should no longer be used. The functions have been
replaced with "no-op" compatibility macros.
[Alessandro Ghedini, Matt Caswell]
*) Modify behavior of ALPN to invoke callback after SNI/servername
callback, such that updates to the SSL_CTX affect ALPN.
[Todd Short]
*) Add SSL_CIPHER queries for authentication and key-exchange.
[Todd Short]
*) Changes to the DEFAULT cipherlist:
- Prefer (EC)DHE handshakes over plain RSA.
- Prefer AEAD ciphers over legacy ciphers.
- Prefer ECDSA over RSA when both certificates are available.
- Prefer TLSv1.2 ciphers/PRF.
- Remove DSS, SEED, IDEA, CAMELLIA, and AES-CCM from the
default cipherlist.
[Emilia Käsper]
*) Change the ECC default curve list to be this, in order: x25519,
secp256r1, secp521r1, secp384r1.
[Rich Salz]
*) RC4 based libssl ciphersuites are now classed as "weak" ciphers and are
disabled by default. They can be re-enabled using the
enable-weak-ssl-ciphers option to Configure.
[Matt Caswell]
*) If the server has ALPN configured, but supports no protocols that the
client advertises, send a fatal "no_application_protocol" alert.
This behaviour is SHALL in RFC 7301, though it isn't universally
implemented by other servers.
[Emilia Käsper]
*) Add X25519 support.
Add ASN.1 and EVP_PKEY methods for X25519. This includes support
for public and private key encoding using the format documented in
draft-ietf-curdle-pkix-02. The corresponding EVP_PKEY method supports
key generation and key derivation.
TLS support complies with draft-ietf-tls-rfc4492bis-08 and uses
X25519(29).
[Steve Henson]
*) Deprecate SRP_VBASE_get_by_user.
SRP_VBASE_get_by_user had inconsistent memory management behaviour.
In order to fix an unavoidable memory leak (CVE-2016-0798),
SRP_VBASE_get_by_user was changed to ignore the "fake user" SRP
seed, even if the seed is configured.
Users should use SRP_VBASE_get1_by_user instead. Note that in
SRP_VBASE_get1_by_user, caller must free the returned value. Note
also that even though configuring the SRP seed attempts to hide
invalid usernames by continuing the handshake with fake
credentials, this behaviour is not constant time and no strong
guarantees are made that the handshake is indistinguishable from
that of a valid user.
[Emilia Käsper]
*) Configuration change; it's now possible to build dynamic engines
without having to build shared libraries and vice versa. This
only applies to the engines in engines/, those in crypto/engine/
will always be built into libcrypto (i.e. "static").
Building dynamic engines is enabled by default; to disable, use
the configuration option "disable-dynamic-engine".
The only requirements for building dynamic engines are the
presence of the DSO module and building with position independent
code, so they will also automatically be disabled if configuring
with "disable-dso" or "disable-pic".
The macros OPENSSL_NO_STATIC_ENGINE and OPENSSL_NO_DYNAMIC_ENGINE
are also taken away from openssl/opensslconf.h, as they are
irrelevant.
[Richard Levitte]
*) Configuration change; if there is a known flag to compile
position independent code, it will always be applied on the
libcrypto and libssl object files, and never on the application
object files. This means other libraries that use routines from
libcrypto / libssl can be made into shared libraries regardless
of how OpenSSL was configured.
If this isn't desirable, the configuration options "disable-pic"
or "no-pic" can be used to disable the use of PIC. This will
also disable building shared libraries and dynamic engines.
[Richard Levitte]
*) Removed JPAKE code. It was experimental and has no wide use.
[Rich Salz]
*) The INSTALL_PREFIX Makefile variable has been renamed to
DESTDIR. That makes for less confusion on what this variable
is for. Also, the configuration option --install_prefix is
removed.
[Richard Levitte]
*) Heartbeat for TLS has been removed and is disabled by default
for DTLS; configure with enable-heartbeats. Code that uses the
old #define's might need to be updated.
[Emilia Käsper, Rich Salz]
*) Rename REF_CHECK to REF_DEBUG.
[Rich Salz]
*) New "unified" build system
The "unified" build system is aimed to be a common system for all
platforms we support. With it comes new support for VMS.
This system builds supports building in a different directory tree
than the source tree. It produces one Makefile (for unix family
or lookalikes), or one descrip.mms (for VMS).
The source of information to make the Makefile / descrip.mms is
small files called 'build.info', holding the necessary
information for each directory with source to compile, and a
template in Configurations, like unix-Makefile.tmpl or
descrip.mms.tmpl.
With this change, the library names were also renamed on Windows
and on VMS. They now have names that are closer to the standard
on Unix, and include the major version number, and in certain
cases, the architecture they are built for. See "Notes on shared
libraries" in INSTALL.
We rely heavily on the perl module Text::Template.
[Richard Levitte]
*) Added support for auto-initialisation and de-initialisation of the library.
OpenSSL no longer requires explicit init or deinit routines to be called,
except in certain circumstances. See the OPENSSL_init_crypto() and
OPENSSL_init_ssl() man pages for further information.
[Matt Caswell]
*) The arguments to the DTLSv1_listen function have changed. Specifically the
"peer" argument is now expected to be a BIO_ADDR object.
*) Rewrite of BIO networking library. The BIO library lacked consistent
support of IPv6, and adding it required some more extensive
modifications. This introduces the BIO_ADDR and BIO_ADDRINFO types,
which hold all types of addresses and chains of address information.
It also introduces a new API, with functions like BIO_socket,
BIO_connect, BIO_listen, BIO_lookup and a rewrite of BIO_accept.
The source/sink BIOs BIO_s_connect, BIO_s_accept and BIO_s_datagram
have been adapted accordingly.
[Richard Levitte]
*) RSA_padding_check_PKCS1_type_1 now accepts inputs with and without
the leading 0-byte.
[Emilia Käsper]
*) CRIME protection: disable compression by default, even if OpenSSL is
compiled with zlib enabled. Applications can still enable compression
by calling SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION), or by
using the SSL_CONF library to configure compression.
[Emilia Käsper]
*) The signature of the session callback configured with
SSL_CTX_sess_set_get_cb was changed. The read-only input buffer
was explicitly marked as 'const unsigned char*' instead of
'unsigned char*'.
[Emilia Käsper]
*) Always DPURIFY. Remove the use of uninitialized memory in the
RNG, and other conditional uses of DPURIFY. This makes -DPURIFY a no-op.
[Emilia Käsper]
*) Removed many obsolete configuration items, including
DES_PTR, DES_RISC1, DES_RISC2, DES_INT
MD2_CHAR, MD2_INT, MD2_LONG
BF_PTR, BF_PTR2
IDEA_SHORT, IDEA_LONG
RC2_SHORT, RC2_LONG, RC4_LONG, RC4_CHUNK, RC4_INDEX
[Rich Salz, with advice from Andy Polyakov]
*) Many BN internals have been moved to an internal header file.
[Rich Salz with help from Andy Polyakov]
*) Configuration and writing out the results from it has changed.
Files such as Makefile include/openssl/opensslconf.h and are now
produced through general templates, such as Makefile.in and
crypto/opensslconf.h.in and some help from the perl module
Text::Template.
Also, the center of configuration information is no longer
Makefile. Instead, Configure produces a perl module in
configdata.pm which holds most of the config data (in the hash
table %config), the target data that comes from the target
configuration in one of the Configurations/*.conf files (in
%target).
[Richard Levitte]
*) To clarify their intended purposes, the Configure options
--prefix and --openssldir change their semantics, and become more
straightforward and less interdependent.
--prefix shall be used exclusively to give the location INSTALLTOP
where programs, scripts, libraries, include files and manuals are
going to be installed. The default is now /usr/local.
--openssldir shall be used exclusively to give the default
location OPENSSLDIR where certificates, private keys, CRLs are
managed. This is also where the default openssl.cnf gets
installed.
If the directory given with this option is a relative path, the
values of both the --prefix value and the --openssldir value will
be combined to become OPENSSLDIR.
The default for --openssldir is INSTALLTOP/ssl.
Anyone who uses --openssldir to specify where OpenSSL is to be
installed MUST change to use --prefix instead.
[Richard Levitte]
*) The GOST engine was out of date and therefore it has been removed. An up
to date GOST engine is now being maintained in an external repository.
See: https://wiki.openssl.org/index.php/Binaries. Libssl still retains
support for GOST ciphersuites (these are only activated if a GOST engine
is present).
[Matt Caswell]
*) EGD is no longer supported by default; use enable-egd when
configuring.
[Ben Kaduk and Rich Salz]
*) The distribution now has Makefile.in files, which are used to
create Makefile's when Configure is run. *Configure must be run
before trying to build now.*
[Rich Salz]
*) The return value for SSL_CIPHER_description() for error conditions
has changed.
[Rich Salz]
*) Support for RFC6698/RFC7671 DANE TLSA peer authentication.
Obtaining and performing DNSSEC validation of TLSA records is
the application's responsibility. The application provides
the TLSA records of its choice to OpenSSL, and these are then
used to authenticate the peer.
The TLSA records need not even come from DNS. They can, for
example, be used to implement local end-entity certificate or
trust-anchor "pinning", where the "pin" data takes the form
of TLSA records, which can augment or replace verification
based on the usual WebPKI public certification authorities.
[Viktor Dukhovni]
*) Revert default OPENSSL_NO_DEPRECATED setting. Instead OpenSSL
continues to support deprecated interfaces in default builds.
However, applications are strongly advised to compile their
source files with -DOPENSSL_API_COMPAT=0x10100000L, which hides
the declarations of all interfaces deprecated in 0.9.8, 1.0.0
or the 1.1.0 releases.
In environments in which all applications have been ported to
not use any deprecated interfaces OpenSSL's Configure script
should be used with the --api=1.1.0 option to entirely remove
support for the deprecated features from the library and
unconditionally disable them in the installed headers.
Essentially the same effect can be achieved with the "no-deprecated"
argument to Configure, except that this will always restrict
the build to just the latest API, rather than a fixed API
version.
As applications are ported to future revisions of the API,
they should update their compile-time OPENSSL_API_COMPAT define
accordingly, but in most cases should be able to continue to
compile with later releases.
The OPENSSL_API_COMPAT versions for 1.0.0, and 0.9.8 are
0x10000000L and 0x00908000L, respectively. However those
versions did not support the OPENSSL_API_COMPAT feature, and
so applications are not typically tested for explicit support
of just the undeprecated features of either release.
[Viktor Dukhovni]
*) Add support for setting the minimum and maximum supported protocol.
It can bet set via the SSL_set_min_proto_version() and
SSL_set_max_proto_version(), or via the SSL_CONF's MinProtocol and
MaxProtocol. It's recommended to use the new APIs to disable
protocols instead of disabling individual protocols using
SSL_set_options() or SSL_CONF's Protocol. This change also
removes support for disabling TLS 1.2 in the OpenSSL TLS
client at compile time by defining OPENSSL_NO_TLS1_2_CLIENT.
[Kurt Roeckx]
*) Support for ChaCha20 and Poly1305 added to libcrypto and libssl.
[Andy Polyakov]
*) New EC_KEY_METHOD, this replaces the older ECDSA_METHOD and ECDH_METHOD
and integrates ECDSA and ECDH functionality into EC. Implementations can
now redirect key generation and no longer need to convert to or from
ECDSA_SIG format.
Note: the ecdsa.h and ecdh.h headers are now no longer needed and just
include the ec.h header file instead.
[Steve Henson]
*) Remove support for all 40 and 56 bit ciphers. This includes all the export
ciphers who are no longer supported and drops support the ephemeral RSA key
exchange. The LOW ciphers currently doesn't have any ciphers in it.
[Kurt Roeckx]
*) Made EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX, EVP_CIPHER and HMAC_CTX
opaque. For HMAC_CTX, the following constructors and destructors
were added:
HMAC_CTX *HMAC_CTX_new(void);
void HMAC_CTX_free(HMAC_CTX *ctx);
For EVP_MD and EVP_CIPHER, complete APIs to create, fill and
destroy such methods has been added. See EVP_MD_meth_new(3) and
EVP_CIPHER_meth_new(3) for documentation.
Additional changes:
1) EVP_MD_CTX_cleanup(), EVP_CIPHER_CTX_cleanup() and
HMAC_CTX_cleanup() were removed. HMAC_CTX_reset() and
EVP_MD_CTX_reset() should be called instead to reinitialise
an already created structure.
2) For consistency with the majority of our object creators and
destructors, EVP_MD_CTX_(create|destroy) were renamed to
EVP_MD_CTX_(new|free). The old names are retained as macros
for deprecated builds.
[Richard Levitte]
*) Added ASYNC support. Libcrypto now includes the async sub-library to enable
cryptographic operations to be performed asynchronously as long as an
asynchronous capable engine is used. See the ASYNC_start_job() man page for
further details. Libssl has also had this capability integrated with the
introduction of the new mode SSL_MODE_ASYNC and associated error
SSL_ERROR_WANT_ASYNC. See the SSL_CTX_set_mode() and SSL_get_error() man
pages. This work was developed in partnership with Intel Corp.
[Matt Caswell]
*) SSL_{CTX_}set_ecdh_auto() has been removed and ECDH is support is
always enabled now. If you want to disable the support you should
exclude it using the list of supported ciphers. This also means that the
"-no_ecdhe" option has been removed from s_server.
[Kurt Roeckx]
*) SSL_{CTX}_set_tmp_ecdh() which can set 1 EC curve now internally calls
SSL_{CTX_}set1_curves() which can set a list.
[Kurt Roeckx]
*) Remove support for SSL_{CTX_}set_tmp_ecdh_callback(). You should set the
curve you want to support using SSL_{CTX_}set1_curves().
[Kurt Roeckx]
*) State machine rewrite. The state machine code has been significantly
refactored in order to remove much duplication of code and solve issues
with the old code (see ssl/statem/README for further details). This change
does have some associated API changes. Notably the SSL_state() function
has been removed and replaced by SSL_get_state which now returns an
"OSSL_HANDSHAKE_STATE" instead of an int. SSL_set_state() has been removed
altogether. The previous handshake states defined in ssl.h and ssl3.h have
also been removed.
[Matt Caswell]
*) All instances of the string "ssleay" in the public API were replaced
with OpenSSL (case-matching; e.g., OPENSSL_VERSION for #define's)
Some error codes related to internal RSA_eay API's were renamed.
[Rich Salz]
*) The demo files in crypto/threads were moved to demo/threads.
[Rich Salz]
*) Removed obsolete engines: 4758cca, aep, atalla, cswift, nuron, gmp,
sureware and ubsec.
[Matt Caswell, Rich Salz]
*) New ASN.1 embed macro.
New ASN.1 macro ASN1_EMBED. This is the same as ASN1_SIMPLE except the
structure is not allocated: it is part of the parent. That is instead of
FOO *x;
it must be:
FOO x;
This reduces memory fragmentation and make it impossible to accidentally
set a mandatory field to NULL.
This currently only works for some fields specifically a SEQUENCE, CHOICE,
or ASN1_STRING type which is part of a parent SEQUENCE. Since it is
equivalent to ASN1_SIMPLE it cannot be tagged, OPTIONAL, SET OF or
SEQUENCE OF.
[Steve Henson]
*) Remove EVP_CHECK_DES_KEY, a compile-time option that never compiled.
[Emilia Käsper]
*) Removed DES and RC4 ciphersuites from DEFAULT. Also removed RC2 although
in 1.0.2 EXPORT was already removed and the only RC2 ciphersuite is also
an EXPORT one. COMPLEMENTOFDEFAULT has been updated accordingly to add
DES and RC4 ciphersuites.
[Matt Caswell]
*) Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs.
This changes the decoding behaviour for some invalid messages,
though the change is mostly in the more lenient direction, and
legacy behaviour is preserved as much as possible.
[Emilia Käsper]
*) Fix no-stdio build.
[ David Woodhouse <David.Woodhouse@intel.com> and also
Ivan Nestlerode <ivan.nestlerode@sonos.com> ]
*) New testing framework
The testing framework has been largely rewritten and is now using
perl and the perl modules Test::Harness and an extended variant of
Test::More called OpenSSL::Test to do its work. All test scripts in
test/ have been rewritten into test recipes, and all direct calls to
executables in test/Makefile have become individual recipes using the
simplified testing OpenSSL::Test::Simple.
For documentation on our testing modules, do:
perldoc test/testlib/OpenSSL/Test/Simple.pm
perldoc test/testlib/OpenSSL/Test.pm
[Richard Levitte]
*) Revamped memory debug; only -DCRYPTO_MDEBUG and -DCRYPTO_MDEBUG_ABORT
are used; the latter aborts on memory leaks (usually checked on exit).
Some undocumented "set malloc, etc., hooks" functions were removed
and others were changed. All are now documented.
[Rich Salz]
*) In DSA_generate_parameters_ex, if the provided seed is too short,
return an error
[Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>]
*) Rewrite PSK to support ECDHE_PSK, DHE_PSK and RSA_PSK. Add ciphersuites
from RFC4279, RFC4785, RFC5487, RFC5489.
Thanks to Christian J. Dietrich and Giuseppe D'Angelo for the
original RSA_PSK patch.
[Steve Henson]
*) Dropped support for the SSL3_FLAGS_DELAY_CLIENT_FINISHED flag. This SSLeay
era flag was never set throughout the codebase (only read). Also removed
SSL3_FLAGS_POP_BUFFER which was only used if
SSL3_FLAGS_DELAY_CLIENT_FINISHED was also set.
[Matt Caswell]
*) Changed the default name options in the "ca", "crl", "req" and "x509"
to be "oneline" instead of "compat".
[Richard Levitte]
*) Remove SSL_OP_TLS_BLOCK_PADDING_BUG. This is SSLeay legacy, we're
not aware of clients that still exhibit this bug, and the workaround
hasn't been working properly for a while.
[Emilia Käsper]
*) The return type of BIO_number_read() and BIO_number_written() as well as
the corresponding num_read and num_write members in the BIO structure has
changed from unsigned long to uint64_t. On platforms where an unsigned
long is 32 bits (e.g. Windows) these counters could overflow if >4Gb is
transferred.
[Matt Caswell]
*) Given the pervasive nature of TLS extensions it is inadvisable to run
OpenSSL without support for them. It also means that maintaining
the OPENSSL_NO_TLSEXT option within the code is very invasive (and probably
not well tested). Therefore the OPENSSL_NO_TLSEXT option has been removed.
[Matt Caswell]
*) Removed support for the two export grade static DH ciphersuites
EXP-DH-RSA-DES-CBC-SHA and EXP-DH-DSS-DES-CBC-SHA. These two ciphersuites
were newly added (along with a number of other static DH ciphersuites) to
1.0.2. However the two export ones have *never* worked since they were
introduced. It seems strange in any case to be adding new export
ciphersuites, and given "logjam" it also does not seem correct to fix them.
[Matt Caswell]
*) Version negotiation has been rewritten. In particular SSLv23_method(),
SSLv23_client_method() and SSLv23_server_method() have been deprecated,
and turned into macros which simply call the new preferred function names
TLS_method(), TLS_client_method() and TLS_server_method(). All new code
should use the new names instead. Also as part of this change the ssl23.h
header file has been removed.
[Matt Caswell]
*) Support for Kerberos ciphersuites in TLS (RFC2712) has been removed. This
code and the associated standard is no longer considered fit-for-purpose.
[Matt Caswell]
*) RT2547 was closed. When generating a private key, try to make the
output file readable only by the owner. This behavior change might
be noticeable when interacting with other software.
*) Documented all exdata functions. Added CRYPTO_free_ex_index.
Added a test.
[Rich Salz]
*) Added HTTP GET support to the ocsp command.
[Rich Salz]
*) Changed default digest for the dgst and enc commands from MD5 to
sha256
[Rich Salz]
*) RAND_pseudo_bytes has been deprecated. Users should use RAND_bytes instead.
[Matt Caswell]
*) Added support for TLS extended master secret from
draft-ietf-tls-session-hash-03.txt. Thanks for Alfredo Pironti for an
initial patch which was a great help during development.
[Steve Henson]
*) All libssl internal structures have been removed from the public header
files, and the OPENSSL_NO_SSL_INTERN option has been removed (since it is
now redundant). Users should not attempt to access internal structures
directly. Instead they should use the provided API functions.
[Matt Caswell]
*) config has been changed so that by default OPENSSL_NO_DEPRECATED is used.
Access to deprecated functions can be re-enabled by running config with
"enable-deprecated". In addition applications wishing to use deprecated
functions must define OPENSSL_USE_DEPRECATED. Note that this new behaviour
will, by default, disable some transitive includes that previously existed
in the header files (e.g. ec.h will no longer, by default, include bn.h)
[Matt Caswell]
*) Added support for OCB mode. OpenSSL has been granted a patent license
compatible with the OpenSSL license for use of OCB. Details are available
at https://www.openssl.org/source/OCB-patent-grant-OpenSSL.pdf. Support
for OCB can be removed by calling config with no-ocb.
[Matt Caswell]
*) SSLv2 support has been removed. It still supports receiving a SSLv2
compatible client hello.
[Kurt Roeckx]
*) Increased the minimal RSA keysize from 256 to 512 bits [Rich Salz],
done while fixing the error code for the key-too-small case.
[Annie Yousar <a.yousar@informatik.hu-berlin.de>]
*) CA.sh has been removed; use CA.pl instead.
[Rich Salz]
*) Removed old DES API.
[Rich Salz]
*) Remove various unsupported platforms:
Sony NEWS4
BEOS and BEOS_R5
NeXT
SUNOS
MPE/iX
Sinix/ReliantUNIX RM400
DGUX
NCR
Tandem
Cray
16-bit platforms such as WIN16
[Rich Salz]
*) Clean up OPENSSL_NO_xxx #define's
Use setbuf() and remove OPENSSL_NO_SETVBUF_IONBF
Rename OPENSSL_SYSNAME_xxx to OPENSSL_SYS_xxx
OPENSSL_NO_EC{DH,DSA} merged into OPENSSL_NO_EC
OPENSSL_NO_RIPEMD160, OPENSSL_NO_RIPEMD merged into OPENSSL_NO_RMD160
OPENSSL_NO_FP_API merged into OPENSSL_NO_STDIO
Remove OPENSSL_NO_BIO OPENSSL_NO_BUFFER OPENSSL_NO_CHAIN_VERIFY
OPENSSL_NO_EVP OPENSSL_NO_FIPS_ERR OPENSSL_NO_HASH_COMP
OPENSSL_NO_LHASH OPENSSL_NO_OBJECT OPENSSL_NO_SPEED OPENSSL_NO_STACK
OPENSSL_NO_X509 OPENSSL_NO_X509_VERIFY
Remove MS_STATIC; it's a relic from platforms <32 bits.
[Rich Salz]
*) Cleaned up dead code
Remove all but one '#ifdef undef' which is to be looked at.
[Rich Salz]
*) Clean up calling of xxx_free routines.
Just like free(), fix most of the xxx_free routines to accept
NULL. Remove the non-null checks from callers. Save much code.
[Rich Salz]
*) Add secure heap for storage of private keys (when possible).
Add BIO_s_secmem(), CBIGNUM, etc.
Contributed by Akamai Technologies under our Corporate CLA.
[Rich Salz]
*) Experimental support for a new, fast, unbiased prime candidate generator,
bn_probable_prime_dh_coprime(). Not currently used by any prime generator.
[Felix Laurie von Massenbach <felix@erbridge.co.uk>]
*) New output format NSS in the sess_id command line tool. This allows
exporting the session id and the master key in NSS keylog format.
[Martin Kaiser <martin@kaiser.cx>]
*) Harmonize version and its documentation. -f flag is used to display
compilation flags.
[mancha <mancha1@zoho.com>]
*) Fix eckey_priv_encode so it immediately returns an error upon a failure
in i2d_ECPrivateKey. Thanks to Ted Unangst for feedback on this issue.
[mancha <mancha1@zoho.com>]
*) Fix some double frees. These are not thought to be exploitable.
[mancha <mancha1@zoho.com>]
*) A missing bounds check in the handling of the TLS heartbeat extension
can be used to reveal up to 64k of memory to a connected client or
server.
Thanks for Neel Mehta of Google Security for discovering this bug and to
Adam Langley <agl@chromium.org> and Bodo Moeller <bmoeller@acm.org> for
preparing the fix (CVE-2014-0160)
[Adam Langley, Bodo Moeller]
*) Fix for the attack described in the paper "Recovering OpenSSL
ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack"
by Yuval Yarom and Naomi Benger. Details can be obtained from:
http://eprint.iacr.org/2014/140
Thanks to Yuval Yarom and Naomi Benger for discovering this
flaw and to Yuval Yarom for supplying a fix (CVE-2014-0076)
[Yuval Yarom and Naomi Benger]
*) Use algorithm specific chains in SSL_CTX_use_certificate_chain_file():
this fixes a limitation in previous versions of OpenSSL.
[Steve Henson]
*) Experimental encrypt-then-mac support.
Experimental support for encrypt then mac from
draft-gutmann-tls-encrypt-then-mac-02.txt
To enable it set the appropriate extension number (0x42 for the test
server) using e.g. -DTLSEXT_TYPE_encrypt_then_mac=0x42
For non-compliant peers (i.e. just about everything) this should have no
effect.
WARNING: EXPERIMENTAL, SUBJECT TO CHANGE.
[Steve Henson]
*) Add EVP support for key wrapping algorithms, to avoid problems with
existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in
the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap
algorithms and include tests cases.
[Steve Henson]
*) Extend CMS code to support RSA-PSS signatures and RSA-OAEP for
enveloped data.
[Steve Henson]
*) Extended RSA OAEP support via EVP_PKEY API. Options to specify digest,
MGF1 digest and OAEP label.
[Steve Henson]
*) Make openssl verify return errors.
[Chris Palmer <palmer@google.com> and Ben Laurie]
*) New function ASN1_TIME_diff to calculate the difference between two
ASN1_TIME structures or one structure and the current time.
[Steve Henson]
*) Update fips_test_suite to support multiple command line options. New
test to induce all self test errors in sequence and check expected
failures.
[Steve Henson]
*) Add FIPS_{rsa,dsa,ecdsa}_{sign,verify} functions which digest and
sign or verify all in one operation.
[Steve Henson]
*) Add fips_algvs: a multicall fips utility incorporating all the algorithm
test programs and fips_test_suite. Includes functionality to parse
the minimal script output of fipsalgest.pl directly.
[Steve Henson]
*) Add authorisation parameter to FIPS_module_mode_set().
[Steve Henson]
*) Add FIPS selftest for ECDH algorithm using P-224 and B-233 curves.
[Steve Henson]
*) Use separate DRBG fields for internal and external flags. New function
FIPS_drbg_health_check() to perform on demand health checking. Add
generation tests to fips_test_suite with reduced health check interval to
demonstrate periodic health checking. Add "nodh" option to
fips_test_suite to skip very slow DH test.
[Steve Henson]
*) New function FIPS_get_cipherbynid() to lookup FIPS supported ciphers
based on NID.
[Steve Henson]
*) More extensive health check for DRBG checking many more failure modes.
New function FIPS_selftest_drbg_all() to handle every possible DRBG
combination: call this in fips_test_suite.
[Steve Henson]
*) Add support for canonical generation of DSA parameter 'g'. See
FIPS 186-3 A.2.3.
*) Add support for HMAC DRBG from SP800-90. Update DRBG algorithm test and
POST to handle HMAC cases.
[Steve Henson]
*) Add functions FIPS_module_version() and FIPS_module_version_text()
to return numerical and string versions of the FIPS module number.
[Steve Henson]
*) Rename FIPS_mode_set and FIPS_mode to FIPS_module_mode_set and
FIPS_module_mode. FIPS_mode and FIPS_mode_set will be implemented
outside the validated module in the FIPS capable OpenSSL.
[Steve Henson]
*) Minor change to DRBG entropy callback semantics. In some cases
there is no multiple of the block length between min_len and
max_len. Allow the callback to return more than max_len bytes
of entropy but discard any extra: it is the callback's responsibility
to ensure that the extra data discarded does not impact the
requested amount of entropy.
[Steve Henson]
*) Add PRNG security strength checks to RSA, DSA and ECDSA using
information in FIPS186-3, SP800-57 and SP800-131A.
[Steve Henson]
*) CCM support via EVP. Interface is very similar to GCM case except we
must supply all data in one chunk (i.e. no update, final) and the
message length must be supplied if AAD is used. Add algorithm test
support.
[Steve Henson]
*) Initial version of POST overhaul. Add POST callback to allow the status
of POST to be monitored and/or failures induced. Modify fips_test_suite
to use callback. Always run all selftests even if one fails.
[Steve Henson]
*) XTS support including algorithm test driver in the fips_gcmtest program.
Note: this does increase the maximum key length from 32 to 64 bytes but
there should be no binary compatibility issues as existing applications
will never use XTS mode.
[Steve Henson]
*) Extensive reorganisation of FIPS PRNG behaviour. Remove all dependencies
to OpenSSL RAND code and replace with a tiny FIPS RAND API which also
performs algorithm blocking for unapproved PRNG types. Also do not
set PRNG type in FIPS_mode_set(): leave this to the application.
Add default OpenSSL DRBG handling: sets up FIPS PRNG and seeds with
the standard OpenSSL PRNG: set additional data to a date time vector.
[Steve Henson]
*) Rename old X9.31 PRNG functions of the form FIPS_rand* to FIPS_x931*.
This shouldn't present any incompatibility problems because applications
shouldn't be using these directly and any that are will need to rethink
anyway as the X9.31 PRNG is now deprecated by FIPS 140-2
[Steve Henson]
*) Extensive self tests and health checking required by SP800-90 DRBG.
Remove strength parameter from FIPS_drbg_instantiate and always
instantiate at maximum supported strength.
[Steve Henson]
*) Add ECDH code to fips module and fips_ecdhvs for primitives only testing.
[Steve Henson]
*) New algorithm test program fips_dhvs to handle DH primitives only testing.
[Steve Henson]
*) New function DH_compute_key_padded() to compute a DH key and pad with
leading zeroes if needed: this complies with SP800-56A et al.
[Steve Henson]
*) Initial implementation of SP800-90 DRBGs for Hash and CTR. Not used by
anything, incomplete, subject to change and largely untested at present.
[Steve Henson]
*) Modify fipscanisteronly build option to only build the necessary object
files by filtering FIPS_EX_OBJ through a perl script in crypto/Makefile.
[Steve Henson]
*) Add experimental option FIPSSYMS to give all symbols in
fipscanister.o and FIPS or fips prefix. This will avoid
conflicts with future versions of OpenSSL. Add perl script
util/fipsas.pl to preprocess assembly language source files
and rename any affected symbols.
[Steve Henson]
*) Add selftest checks and algorithm block of non-fips algorithms in
FIPS mode. Remove DES2 from selftests.
[Steve Henson]
*) Add ECDSA code to fips module. Add tiny fips_ecdsa_check to just
return internal method without any ENGINE dependencies. Add new
tiny fips sign and verify functions.
[Steve Henson]
*) New build option no-ec2m to disable characteristic 2 code.
[Steve Henson]
*) New build option "fipscanisteronly". This only builds fipscanister.o
and (currently) associated fips utilities. Uses the file Makefile.fips
instead of Makefile.org as the prototype.
[Steve Henson]
*) Add some FIPS mode restrictions to GCM. Add internal IV generator.
Update fips_gcmtest to use IV generator.
[Steve Henson]
*) Initial, experimental EVP support for AES-GCM. AAD can be input by
setting output buffer to NULL. The *Final function must be
called although it will not retrieve any additional data. The tag
can be set or retrieved with a ctrl. The IV length is by default 12
bytes (96 bits) but can be set to an alternative value. If the IV
length exceeds the maximum IV length (currently 16 bytes) it cannot be
set before the key.
[Steve Henson]
*) New flag in ciphers: EVP_CIPH_FLAG_CUSTOM_CIPHER. This means the
underlying do_cipher function handles all cipher semantics itself
including padding and finalisation. This is useful if (for example)
an ENGINE cipher handles block padding itself. The behaviour of
do_cipher is subtly changed if this flag is set: the return value
is the number of characters written to the output buffer (zero is
no longer an error code) or a negative error code. Also if the
input buffer is NULL and length 0 finalisation should be performed.
[Steve Henson]
*) If a candidate issuer certificate is already part of the constructed
path ignore it: new debug notification X509_V_ERR_PATH_LOOP for this case.
[Steve Henson]
*) Improve forward-security support: add functions
void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx, int (*cb)(SSL *ssl, int is_forward_secure))
void SSL_set_not_resumable_session_callback(SSL *ssl, int (*cb)(SSL *ssl, int is_forward_secure))
for use by SSL/TLS servers; the callback function will be called whenever a
new session is created, and gets to decide whether the session may be
cached to make it resumable (return 0) or not (return 1). (As by the
SSL/TLS protocol specifications, the session_id sent by the server will be
empty to indicate that the session is not resumable; also, the server will
not generate RFC 4507 (RFC 5077) session tickets.)
A simple reasonable callback implementation is to return is_forward_secure.
This parameter will be set to 1 or 0 depending on the ciphersuite selected
by the SSL/TLS server library, indicating whether it can provide forward
security.
[Emilia Käsper <emilia.kasper@esat.kuleuven.be> (Google)]
*) New -verify_name option in command line utilities to set verification
parameters by name.
[Steve Henson]
*) Initial CMAC implementation. WARNING: EXPERIMENTAL, API MAY CHANGE.
Add CMAC pkey methods.
[Steve Henson]
*) Experimental renegotiation in s_server -www mode. If the client
browses /reneg connection is renegotiated. If /renegcert it is
renegotiated requesting a certificate.
[Steve Henson]
*) Add an "external" session cache for debugging purposes to s_server. This
should help trace issues which normally are only apparent in deployed
multi-process servers.
[Steve Henson]
*) Extensive audit of libcrypto with DEBUG_UNUSED. Fix many cases where
return value is ignored. NB. The functions RAND_add(), RAND_seed(),
BIO_set_cipher() and some obscure PEM functions were changed so they
can now return an error. The RAND changes required a change to the
RAND_METHOD structure.
[Steve Henson]
*) New macro __owur for "OpenSSL Warn Unused Result". This makes use of
a gcc attribute to warn if the result of a function is ignored. This
is enable if DEBUG_UNUSED is set. Add to several functions in evp.h
whose return value is often ignored.
[Steve Henson]
*) New -noct, -requestct, -requirect and -ctlogfile options for s_client.
These allow SCTs (signed certificate timestamps) to be requested and
validated when establishing a connection.
[Rob Percival <robpercival@google.com>]
Changes between 1.0.2g and 1.0.2h [3 May 2016]
*) Prevent padding oracle in AES-NI CBC MAC check
A MITM attacker can use a padding oracle attack to decrypt traffic
when the connection uses an AES CBC cipher and the server support
AES-NI.
This issue was introduced as part of the fix for Lucky 13 padding
attack (CVE-2013-0169). The padding check was rewritten to be in
constant time by making sure that always the same bytes are read and
compared against either the MAC or padding bytes. But it no longer
checked that there was enough data to have both the MAC and padding
bytes.
This issue was reported by Juraj Somorovsky using TLS-Attacker.
(CVE-2016-2107)
[Kurt Roeckx]
*) Fix EVP_EncodeUpdate overflow
An overflow can occur in the EVP_EncodeUpdate() function which is used for
Base64 encoding of binary data. If an attacker is able to supply very large
amounts of input data then a length check can overflow resulting in a heap
corruption.
Internally to OpenSSL the EVP_EncodeUpdate() function is primarily used by
the PEM_write_bio* family of functions. These are mainly used within the
OpenSSL command line applications, so any application which processes data
from an untrusted source and outputs it as a PEM file should be considered
vulnerable to this issue. User applications that call these APIs directly
with large amounts of untrusted data may also be vulnerable.
This issue was reported by Guido Vranken.
(CVE-2016-2105)
[Matt Caswell]
*) Fix EVP_EncryptUpdate overflow
An overflow can occur in the EVP_EncryptUpdate() function. If an attacker
is able to supply very large amounts of input data after a previous call to
EVP_EncryptUpdate() with a partial block then a length check can overflow
resulting in a heap corruption. Following an analysis of all OpenSSL
internal usage of the EVP_EncryptUpdate() function all usage is one of two
forms. The first form is where the EVP_EncryptUpdate() call is known to be
the first called function after an EVP_EncryptInit(), and therefore that
specific call must be safe. The second form is where the length passed to
EVP_EncryptUpdate() can be seen from the code to be some small value and
therefore there is no possibility of an overflow. Since all instances are
one of these two forms, it is believed that there can be no overflows in
internal code due to this problem. It should be noted that
EVP_DecryptUpdate() can call EVP_EncryptUpdate() in certain code paths.
Also EVP_CipherUpdate() is a synonym for EVP_EncryptUpdate(). All instances
of these calls have also been analysed too and it is believed there are no
instances in internal usage where an overflow could occur.
This issue was reported by Guido Vranken.
(CVE-2016-2106)
[Matt Caswell]
*) Prevent ASN.1 BIO excessive memory allocation
When ASN.1 data is read from a BIO using functions such as d2i_CMS_bio()
a short invalid encoding can cause allocation of large amounts of memory
potentially consuming excessive resources or exhausting memory.
Any application parsing untrusted data through d2i BIO functions is
affected. The memory based functions such as d2i_X509() are *not* affected.
Since the memory based functions are used by the TLS library, TLS
applications are not affected.
This issue was reported by Brian Carpenter.
(CVE-2016-2109)
[Stephen Henson]
*) EBCDIC overread
ASN1 Strings that are over 1024 bytes can cause an overread in applications
using the X509_NAME_oneline() function on EBCDIC systems. This could result
in arbitrary stack data being returned in the buffer.
This issue was reported by Guido Vranken.
(CVE-2016-2176)
[Matt Caswell]
*) Modify behavior of ALPN to invoke callback after SNI/servername
callback, such that updates to the SSL_CTX affect ALPN.
[Todd Short]
*) Remove LOW from the DEFAULT cipher list. This removes singles DES from the
default.
[Kurt Roeckx]
*) Only remove the SSLv2 methods with the no-ssl2-method option. When the
methods are enabled and ssl2 is disabled the methods return NULL.
[Kurt Roeckx]
Changes between 1.0.2f and 1.0.2g [1 Mar 2016]
* Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
Builds that are not configured with "enable-weak-ssl-ciphers" will not
provide any "EXPORT" or "LOW" strength ciphers.
[Viktor Dukhovni]
* Disable SSLv2 default build, default negotiation and weak ciphers. SSLv2
is by default disabled at build-time. Builds that are not configured with
"enable-ssl2" will not support SSLv2. Even if "enable-ssl2" is used,
users who want to negotiate SSLv2 via the version-flexible SSLv23_method()
will need to explicitly call either of:
SSL_CTX_clear_options(ctx, SSL_OP_NO_SSLv2);
or
SSL_clear_options(ssl, SSL_OP_NO_SSLv2);
as appropriate. Even if either of those is used, or the application
explicitly uses the version-specific SSLv2_method() or its client and
server variants, SSLv2 ciphers vulnerable to exhaustive search key
recovery have been removed. Specifically, the SSLv2 40-bit EXPORT
ciphers, and SSLv2 56-bit DES are no longer available.
(CVE-2016-0800)
[Viktor Dukhovni]
*) Fix a double-free in DSA code
A double free bug was discovered when OpenSSL parses malformed DSA private
keys and could lead to a DoS attack or memory corruption for applications
that receive DSA private keys from untrusted sources. This scenario is
considered rare.
This issue was reported to OpenSSL by Adam Langley(Google/BoringSSL) using
libFuzzer.
(CVE-2016-0705)
[Stephen Henson]
*) Disable SRP fake user seed to address a server memory leak.
Add a new method SRP_VBASE_get1_by_user that handles the seed properly.
SRP_VBASE_get_by_user had inconsistent memory management behaviour.
In order to fix an unavoidable memory leak, SRP_VBASE_get_by_user
was changed to ignore the "fake user" SRP seed, even if the seed
is configured.
Users should use SRP_VBASE_get1_by_user instead. Note that in
SRP_VBASE_get1_by_user, caller must free the returned value. Note
also that even though configuring the SRP seed attempts to hide
invalid usernames by continuing the handshake with fake
credentials, this behaviour is not constant time and no strong
guarantees are made that the handshake is indistinguishable from
that of a valid user.
(CVE-2016-0798)
[Emilia Käsper]
*) Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
In the BN_hex2bn function the number of hex digits is calculated using an
int value |i|. Later |bn_expand| is called with a value of |i * 4|. For
large values of |i| this can result in |bn_expand| not allocating any
memory because |i * 4| is negative. This can leave the internal BIGNUM data
field as NULL leading to a subsequent NULL ptr deref. For very large values
of |i|, the calculation |i * 4| could be a positive value smaller than |i|.
In this case memory is allocated to the internal BIGNUM data field, but it
is insufficiently sized leading to heap corruption. A similar issue exists
in BN_dec2bn. This could have security consequences if BN_hex2bn/BN_dec2bn
is ever called by user applications with very large untrusted hex/dec data.
This is anticipated to be a rare occurrence.
All OpenSSL internal usage of these functions use data that is not expected
to be untrusted, e.g. config file data or application command line
arguments. If user developed applications generate config file data based
on untrusted data then it is possible that this could also lead to security
consequences. This is also anticipated to be rare.
This issue was reported to OpenSSL by Guido Vranken.
(CVE-2016-0797)
[Matt Caswell]
*) Fix memory issues in BIO_*printf functions
The internal |fmtstr| function used in processing a "%s" format string in
the BIO_*printf functions could overflow while calculating the length of a
string and cause an OOB read when printing very long strings.
Additionally the internal |doapr_outch| function can attempt to write to an
OOB memory location (at an offset from the NULL pointer) in the event of a
memory allocation failure. In 1.0.2 and below this could be caused where
the size of a buffer to be allocated is greater than INT_MAX. E.g. this
could be in processing a very long "%s" format string. Memory leaks can
also occur.
The first issue may mask the second issue dependent on compiler behaviour.
These problems could enable attacks where large amounts of untrusted data
is passed to the BIO_*printf functions. If applications use these functions
in this way then they could be vulnerable. OpenSSL itself uses these
functions when printing out human-readable dumps of ASN.1 data. Therefore
applications that print this data could be vulnerable if the data is from
untrusted sources. OpenSSL command line applications could also be
vulnerable where they print out ASN.1 data, or if untrusted data is passed
as command line arguments.
Libssl is not considered directly vulnerable. Additionally certificates etc
received via remote connections via libssl are also unlikely to be able to
trigger these issues because of message size limits enforced within libssl.
This issue was reported to OpenSSL Guido Vranken.
(CVE-2016-0799)
[Matt Caswell]
*) Side channel attack on modular exponentiation
A side-channel attack was found which makes use of cache-bank conflicts on
the Intel Sandy-Bridge microarchitecture which could lead to the recovery
of RSA keys. The ability to exploit this issue is limited as it relies on
an attacker who has control of code in a thread running on the same
hyper-threaded core as the victim thread which is performing decryptions.
This issue was reported to OpenSSL by Yuval Yarom, The University of
Adelaide and NICTA, Daniel Genkin, Technion and Tel Aviv University, and
Nadia Heninger, University of Pennsylvania with more information at
http://cachebleed.info.
(CVE-2016-0702)
[Andy Polyakov]
*) Change the req app to generate a 2048-bit RSA/DSA key by default,
if no keysize is specified with default_bits. This fixes an
omission in an earlier change that changed all RSA/DSA key generation
apps to use 2048 bits by default.
[Emilia Käsper]
Changes between 1.0.2e and 1.0.2f [28 Jan 2016]
*) DH small subgroups
Historically OpenSSL only ever generated DH parameters based on "safe"
primes. More recently (in version 1.0.2) support was provided for
generating X9.42 style parameter files such as those required for RFC 5114
support. The primes used in such files may not be "safe". Where an
application is using DH configured with parameters based on primes that are
not "safe" then an attacker could use this fact to find a peer's private
DH exponent. This attack requires that the attacker complete multiple
handshakes in which the peer uses the same private DH exponent. For example
this could be used to discover a TLS server's private DH exponent if it's
reusing the private DH exponent or it's using a static DH ciphersuite.
OpenSSL provides the option SSL_OP_SINGLE_DH_USE for ephemeral DH (DHE) in
TLS. It is not on by default. If the option is not set then the server
reuses the same private DH exponent for the life of the server process and
would be vulnerable to this attack. It is believed that many popular
applications do set this option and would therefore not be at risk.
The fix for this issue adds an additional check where a "q" parameter is
available (as is the case in X9.42 based parameters). This detects the
only known attack, and is the only possible defense for static DH
ciphersuites. This could have some performance impact.
Additionally the SSL_OP_SINGLE_DH_USE option has been switched on by
default and cannot be disabled. This could have some performance impact.
This issue was reported to OpenSSL by Antonio Sanso (Adobe).
(CVE-2016-0701)
[Matt Caswell]
*) SSLv2 doesn't block disabled ciphers
A malicious client can negotiate SSLv2 ciphers that have been disabled on
the server and complete SSLv2 handshakes even if all SSLv2 ciphers have
been disabled, provided that the SSLv2 protocol was not also disabled via
SSL_OP_NO_SSLv2.
This issue was reported to OpenSSL on 26th December 2015 by Nimrod Aviram
and Sebastian Schinzel.
(CVE-2015-3197)
[Viktor Dukhovni]
Changes between 1.0.2d and 1.0.2e [3 Dec 2015]
*) BN_mod_exp may produce incorrect results on x86_64
There is a carry propagating bug in the x86_64 Montgomery squaring
procedure. No EC algorithms are affected. Analysis suggests that attacks
against RSA and DSA as a result of this defect would be very difficult to
perform and are not believed likely. Attacks against DH are considered just
feasible (although very difficult) because most of the work necessary to
deduce information about a private key may be performed offline. The amount
of resources required for such an attack would be very significant and
likely only accessible to a limited number of attackers. An attacker would
additionally need online access to an unpatched system using the target
private key in a scenario with persistent DH parameters and a private
key that is shared between multiple clients. For example this can occur by
default in OpenSSL DHE based SSL/TLS ciphersuites.
This issue was reported to OpenSSL by Hanno Böck.
(CVE-2015-3193)
[Andy Polyakov]
*) Certificate verify crash with missing PSS parameter
The signature verification routines will crash with a NULL pointer
dereference if presented with an ASN.1 signature using the RSA PSS
algorithm and absent mask generation function parameter. Since these
routines are used to verify certificate signature algorithms this can be
used to crash any certificate verification operation and exploited in a
DoS attack. Any application which performs certificate verification is
vulnerable including OpenSSL clients and servers which enable client
authentication.
This issue was reported to OpenSSL by Loïc Jonas Etienne (Qnective AG).
(CVE-2015-3194)
[Stephen Henson]
*) X509_ATTRIBUTE memory leak
When presented with a malformed X509_ATTRIBUTE structure OpenSSL will leak
memory. This structure is used by the PKCS#7 and CMS routines so any
application which reads PKCS#7 or CMS data from untrusted sources is
affected. SSL/TLS is not affected.
This issue was reported to OpenSSL by Adam Langley (Google/BoringSSL) using
libFuzzer.
(CVE-2015-3195)
[Stephen Henson]
*) Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs.
This changes the decoding behaviour for some invalid messages,
though the change is mostly in the more lenient direction, and
legacy behaviour is preserved as much as possible.
[Emilia Käsper]
*) In DSA_generate_parameters_ex, if the provided seed is too short,
return an error
[Rich Salz and Ismo Puustinen <ismo.puustinen@intel.com>]
Changes between 1.0.2c and 1.0.2d [9 Jul 2015]
*) Alternate chains certificate forgery
During certificate verification, OpenSSL will attempt to find an
alternative certificate chain if the first attempt to build such a chain
fails. An error in the implementation of this logic can mean that an
attacker could cause certain checks on untrusted certificates to be
bypassed, such as the CA flag, enabling them to use a valid leaf
certificate to act as a CA and "issue" an invalid certificate.
This issue was reported to OpenSSL by Adam Langley/David Benjamin
(Google/BoringSSL).
[Matt Caswell]
Changes between 1.0.2b and 1.0.2c [12 Jun 2015]
*) Fix HMAC ABI incompatibility. The previous version introduced an ABI
incompatibility in the handling of HMAC. The previous ABI has now been
restored.
[Matt Caswell]
Changes between 1.0.2a and 1.0.2b [11 Jun 2015]
*) Malformed ECParameters causes infinite loop
When processing an ECParameters structure OpenSSL enters an infinite loop
if the curve specified is over a specially malformed binary polynomial
field.
This can be used to perform denial of service against any
system which processes public keys, certificate requests or
certificates. This includes TLS clients and TLS servers with
client authentication enabled.
This issue was reported to OpenSSL by Joseph Barr-Pixton.
(CVE-2015-1788)
[Andy Polyakov]
*) Exploitable out-of-bounds read in X509_cmp_time
X509_cmp_time does not properly check the length of the ASN1_TIME
string and can read a few bytes out of bounds. In addition,
X509_cmp_time accepts an arbitrary number of fractional seconds in the
time string.
An attacker can use this to craft malformed certificates and CRLs of
various sizes and potentially cause a segmentation fault, resulting in
a DoS on applications that verify certificates or CRLs. TLS clients
that verify CRLs are affected. TLS clients and servers with client
authentication enabled may be affected if they use custom verification
callbacks.
This issue was reported to OpenSSL by Robert Swiecki (Google), and
independently by Hanno Böck.
(CVE-2015-1789)
[Emilia Käsper]
*) PKCS7 crash with missing EnvelopedContent
The PKCS#7 parsing code does not handle missing inner EncryptedContent
correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs
with missing content and trigger a NULL pointer dereference on parsing.
Applications that decrypt PKCS#7 data or otherwise parse PKCS#7
structures from untrusted sources are affected. OpenSSL clients and
servers are not affected.
This issue was reported to OpenSSL by Michal Zalewski (Google).
(CVE-2015-1790)
[Emilia Käsper]
*) CMS verify infinite loop with unknown hash function
When verifying a signedData message the CMS code can enter an infinite loop
if presented with an unknown hash function OID. This can be used to perform
denial of service against any system which verifies signedData messages using
the CMS code.
This issue was reported to OpenSSL by Johannes Bauer.
(CVE-2015-1792)
[Stephen Henson]
*) Race condition handling NewSessionTicket
If a NewSessionTicket is received by a multi-threaded client when attempting to
reuse a previous ticket then a race condition can occur potentially leading to
a double free of the ticket data.
(CVE-2015-1791)
[Matt Caswell]
*) Only support 256-bit or stronger elliptic curves with the
'ecdh_auto' setting (server) or by default (client). Of supported
curves, prefer P-256 (both).
[Emilia Kasper]
Changes between 1.0.2 and 1.0.2a [19 Mar 2015]
*) ClientHello sigalgs DoS fix
If a client connects to an OpenSSL 1.0.2 server and renegotiates with an
invalid signature algorithms extension a NULL pointer dereference will
occur. This can be exploited in a DoS attack against the server.
This issue was was reported to OpenSSL by David Ramos of Stanford
University.
(CVE-2015-0291)
[Stephen Henson and Matt Caswell]
*) Multiblock corrupted pointer fix
OpenSSL 1.0.2 introduced the "multiblock" performance improvement. This
feature only applies on 64 bit x86 architecture platforms that support AES
NI instructions. A defect in the implementation of "multiblock" can cause
OpenSSL's internal write buffer to become incorrectly set to NULL when
using non-blocking IO. Typically, when the user application is using a
socket BIO for writing, this will only result in a failed connection.
However if some other BIO is used then it is likely that a segmentation
fault will be triggered, thus enabling a potential DoS attack.
This issue was reported to OpenSSL by Daniel Danner and Rainer Mueller.
(CVE-2015-0290)
[Matt Caswell]
*) Segmentation fault in DTLSv1_listen fix
The DTLSv1_listen function is intended to be stateless and processes the
initial ClientHello from many peers. It is common for user code to loop
over the call to DTLSv1_listen until a valid ClientHello is received with
an associated cookie. A defect in the implementation of DTLSv1_listen means
that state is preserved in the SSL object from one invocation to the next
that can lead to a segmentation fault. Errors processing the initial
ClientHello can trigger this scenario. An example of such an error could be
that a DTLS1.0 only client is attempting to connect to a DTLS1.2 only
server.
This issue was reported to OpenSSL by Per Allansson.
(CVE-2015-0207)
[Matt Caswell]
*) Segmentation fault in ASN1_TYPE_cmp fix
The function ASN1_TYPE_cmp will crash with an invalid read if an attempt is
made to compare ASN.1 boolean types. Since ASN1_TYPE_cmp is used to check
certificate signature algorithm consistency this can be used to crash any
certificate verification operation and exploited in a DoS attack. Any
application which performs certificate verification is vulnerable including
OpenSSL clients and servers which enable client authentication.
(CVE-2015-0286)
[Stephen Henson]
*) Segmentation fault for invalid PSS parameters fix
The signature verification routines will crash with a NULL pointer
dereference if presented with an ASN.1 signature using the RSA PSS
algorithm and invalid parameters. Since these routines are used to verify
certificate signature algorithms this can be used to crash any
certificate verification operation and exploited in a DoS attack. Any
application which performs certificate verification is vulnerable including
OpenSSL clients and servers which enable client authentication.
This issue was was reported to OpenSSL by Brian Carpenter.
(CVE-2015-0208)
[Stephen Henson]
*) ASN.1 structure reuse memory corruption fix
Reusing a structure in ASN.1 parsing may allow an attacker to cause
memory corruption via an invalid write. Such reuse is and has been
strongly discouraged and is believed to be rare.
Applications that parse structures containing CHOICE or ANY DEFINED BY
components may be affected. Certificate parsing (d2i_X509 and related
functions) are however not affected. OpenSSL clients and servers are
not affected.
(CVE-2015-0287)
[Stephen Henson]
*) PKCS7 NULL pointer dereferences fix
The PKCS#7 parsing code does not handle missing outer ContentInfo
correctly. An attacker can craft malformed ASN.1-encoded PKCS#7 blobs with
missing content and trigger a NULL pointer dereference on parsing.
Applications that verify PKCS#7 signatures, decrypt PKCS#7 data or
otherwise parse PKCS#7 structures from untrusted sources are
affected. OpenSSL clients and servers are not affected.
This issue was reported to OpenSSL by Michal Zalewski (Google).
(CVE-2015-0289)
[Emilia Käsper]
*) DoS via reachable assert in SSLv2 servers fix
A malicious client can trigger an OPENSSL_assert (i.e., an abort) in
servers that both support SSLv2 and enable export cipher suites by sending
a specially crafted SSLv2 CLIENT-MASTER-KEY message.
This issue was discovered by Sean Burford (Google) and Emilia Käsper
(OpenSSL development team).
(CVE-2015-0293)
[Emilia Käsper]
*) Empty CKE with client auth and DHE fix
If client auth is used then a server can seg fault in the event of a DHE
ciphersuite being selected and a zero length ClientKeyExchange message
being sent by the client. This could be exploited in a DoS attack.
(CVE-2015-1787)
[Matt Caswell]
*) Handshake with unseeded PRNG fix
Under certain conditions an OpenSSL 1.0.2 client can complete a handshake
with an unseeded PRNG. The conditions are:
- The client is on a platform where the PRNG has not been seeded
automatically, and the user has not seeded manually
- A protocol specific client method version has been used (i.e. not
SSL_client_methodv23)
- A ciphersuite is used that does not require additional random data from
the PRNG beyond the initial ClientHello client random (e.g. PSK-RC4-SHA).
If the handshake succeeds then the client random that has been used will
have been generated from a PRNG with insufficient entropy and therefore the
output may be predictable.
For example using the following command with an unseeded openssl will
succeed on an unpatched platform:
openssl s_client -psk 1a2b3c4d -tls1_2 -cipher PSK-RC4-SHA
(CVE-2015-0285)
[Matt Caswell]
*) Use After Free following d2i_ECPrivatekey error fix
A malformed EC private key file consumed via the d2i_ECPrivateKey function
could cause a use after free condition. This, in turn, could cause a double
free in several private key parsing functions (such as d2i_PrivateKey
or EVP_PKCS82PKEY) and could lead to a DoS attack or memory corruption
for applications that receive EC private keys from untrusted
sources. This scenario is considered rare.
This issue was discovered by the BoringSSL project and fixed in their
commit 517073cd4b.
(CVE-2015-0209)
[Matt Caswell]
*) X509_to_X509_REQ NULL pointer deref fix
The function X509_to_X509_REQ will crash with a NULL pointer dereference if
the certificate key is invalid. This function is rarely used in practice.
This issue was discovered by Brian Carpenter.
(CVE-2015-0288)
[Stephen Henson]
*) Removed the export ciphers from the DEFAULT ciphers
[Kurt Roeckx]
Changes between 1.0.1l and 1.0.2 [22 Jan 2015]
*) Facilitate "universal" ARM builds targeting range of ARM ISAs, e.g.
ARMv5 through ARMv8, as opposite to "locking" it to single one.
So far those who have to target multiple platforms would compromise
and argue that binary targeting say ARMv5 would still execute on
ARMv8. "Universal" build resolves this compromise by providing
near-optimal performance even on newer platforms.
[Andy Polyakov]
*) Accelerated NIST P-256 elliptic curve implementation for x86_64
(other platforms pending).
[Shay Gueron & Vlad Krasnov (Intel Corp), Andy Polyakov]
*) Add support for the SignedCertificateTimestampList certificate and
OCSP response extensions from RFC6962.
[Rob Stradling]
*) Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
for corner cases. (Certain input points at infinity could lead to
bogus results, with non-infinity inputs mapped to infinity too.)
[Bodo Moeller]
*) Initial support for PowerISA 2.0.7, first implemented in POWER8.
This covers AES, SHA256/512 and GHASH. "Initial" means that most
common cases are optimized and there still is room for further
improvements. Vector Permutation AES for Altivec is also added.
[Andy Polyakov]
*) Add support for little-endian ppc64 Linux target.
[Marcelo Cerri (IBM)]
*) Initial support for AMRv8 ISA crypto extensions. This covers AES,
SHA1, SHA256 and GHASH. "Initial" means that most common cases
are optimized and there still is room for further improvements.
Both 32- and 64-bit modes are supported.
[Andy Polyakov, Ard Biesheuvel (Linaro)]
*) Improved ARMv7 NEON support.
[Andy Polyakov]
*) Support for SPARC Architecture 2011 crypto extensions, first
implemented in SPARC T4. This covers AES, DES, Camellia, SHA1,
SHA256/512, MD5, GHASH and modular exponentiation.
[Andy Polyakov, David Miller]
*) Accelerated modular exponentiation for Intel processors, a.k.a.
RSAZ.
[Shay Gueron & Vlad Krasnov (Intel Corp)]
*) Support for new and upcoming Intel processors, including AVX2,
BMI and SHA ISA extensions. This includes additional "stitched"
implementations, AESNI-SHA256 and GCM, and multi-buffer support
for TLS encrypt.
This work was sponsored by Intel Corp.
[Andy Polyakov]
*) Support for DTLS 1.2. This adds two sets of DTLS methods: DTLS_*_method()
supports both DTLS 1.2 and 1.0 and should use whatever version the peer
supports and DTLSv1_2_*_method() which supports DTLS 1.2 only.
[Steve Henson]
*) Use algorithm specific chains in SSL_CTX_use_certificate_chain_file():
this fixes a limitation in previous versions of OpenSSL.
[Steve Henson]
*) Extended RSA OAEP support via EVP_PKEY API. Options to specify digest,
MGF1 digest and OAEP label.
[Steve Henson]
*) Add EVP support for key wrapping algorithms, to avoid problems with
existing code the flag EVP_CIPHER_CTX_WRAP_ALLOW has to be set in
the EVP_CIPHER_CTX or an error is returned. Add AES and DES3 wrap
algorithms and include tests cases.
[Steve Henson]
*) Add functions to allocate and set the fields of an ECDSA_METHOD
structure.
[Douglas E. Engert, Steve Henson]
*) New functions OPENSSL_gmtime_diff and ASN1_TIME_diff to find the
difference in days and seconds between two tm or ASN1_TIME structures.
[Steve Henson]
*) Add -rev test option to s_server to just reverse order of characters
received by client and send back to server. Also prints an abbreviated
summary of the connection parameters.
[Steve Henson]
*) New option -brief for s_client and s_server to print out a brief summary
of connection parameters.
[Steve Henson]
*) Add callbacks for arbitrary TLS extensions.
[Trevor Perrin <trevp@trevp.net> and Ben Laurie]
*) New option -crl_download in several openssl utilities to download CRLs
from CRLDP extension in certificates.
[Steve Henson]
*) New options -CRL and -CRLform for s_client and s_server for CRLs.
[Steve Henson]
*) New function X509_CRL_diff to generate a delta CRL from the difference
of two full CRLs. Add support to "crl" utility.
[Steve Henson]
*) New functions to set lookup_crls function and to retrieve
X509_STORE from X509_STORE_CTX.
[Steve Henson]
*) Print out deprecated issuer and subject unique ID fields in
certificates.
[Steve Henson]
*) Extend OCSP I/O functions so they can be used for simple general purpose
HTTP as well as OCSP. New wrapper function which can be used to download
CRLs using the OCSP API.
[Steve Henson]
*) Delegate command line handling in s_client/s_server to SSL_CONF APIs.
[Steve Henson]
*) SSL_CONF* functions. These provide a common framework for application
configuration using configuration files or command lines.
[Steve Henson]
*) SSL/TLS tracing code. This parses out SSL/TLS records using the
message callback and prints the results. Needs compile time option
"enable-ssl-trace". New options to s_client and s_server to enable
tracing.
[Steve Henson]
*) New ctrl and macro to retrieve supported points extensions.
Print out extension in s_server and s_client.
[Steve Henson]
*) New functions to retrieve certificate signature and signature
OID NID.
[Steve Henson]
*) Add functions to retrieve and manipulate the raw cipherlist sent by a
client to OpenSSL.
[Steve Henson]
*) New Suite B modes for TLS code. These use and enforce the requirements
of RFC6460: restrict ciphersuites, only permit Suite B algorithms and
only use Suite B curves. The Suite B modes can be set by using the
strings "SUITEB128", "SUITEB192" or "SUITEB128ONLY" for the cipherstring.
[Steve Henson]
*) New chain verification flags for Suite B levels of security. Check
algorithms are acceptable when flags are set in X509_verify_cert.
[Steve Henson]
*) Make tls1_check_chain return a set of flags indicating checks passed
by a certificate chain. Add additional tests to handle client
certificates: checks for matching certificate type and issuer name
comparison.
[Steve Henson]
*) If an attempt is made to use a signature algorithm not in the peer
preference list abort the handshake. If client has no suitable
signature algorithms in response to a certificate request do not
use the certificate.
[Steve Henson]
*) If server EC tmp key is not in client preference list abort handshake.
[Steve Henson]
*) Add support for certificate stores in CERT structure. This makes it
possible to have different stores per SSL structure or one store in
the parent SSL_CTX. Include distinct stores for certificate chain
verification and chain building. New ctrl SSL_CTRL_BUILD_CERT_CHAIN
to build and store a certificate chain in CERT structure: returning
an error if the chain cannot be built: this will allow applications
to test if a chain is correctly configured.
Note: if the CERT based stores are not set then the parent SSL_CTX
store is used to retain compatibility with existing behaviour.
[Steve Henson]
*) New function ssl_set_client_disabled to set a ciphersuite disabled
mask based on the current session, check mask when sending client
hello and checking the requested ciphersuite.
[Steve Henson]
*) New ctrls to retrieve and set certificate types in a certificate
request message. Print out received values in s_client. If certificate
types is not set with custom values set sensible values based on
supported signature algorithms.
[Steve Henson]
*) Support for distinct client and server supported signature algorithms.
[Steve Henson]
*) Add certificate callback. If set this is called whenever a certificate
is required by client or server. An application can decide which
certificate chain to present based on arbitrary criteria: for example
supported signature algorithms. Add very simple example to s_server.
This fixes many of the problems and restrictions of the existing client
certificate callback: for example you can now clear an existing
certificate and specify the whole chain.
[Steve Henson]
*) Add new "valid_flags" field to CERT_PKEY structure which determines what
the certificate can be used for (if anything). Set valid_flags field
in new tls1_check_chain function. Simplify ssl_set_cert_masks which used
to have similar checks in it.
Add new "cert_flags" field to CERT structure and include a "strict mode".
This enforces some TLS certificate requirements (such as only permitting
certificate signature algorithms contained in the supported algorithms
extension) which some implementations ignore: this option should be used
with caution as it could cause interoperability issues.
[Steve Henson]
*) Update and tidy signature algorithm extension processing. Work out
shared signature algorithms based on preferences and peer algorithms
and print them out in s_client and s_server. Abort handshake if no
shared signature algorithms.
[Steve Henson]
*) Add new functions to allow customised supported signature algorithms
for SSL and SSL_CTX structures. Add options to s_client and s_server
to support them.
[Steve Henson]
*) New function SSL_certs_clear() to delete all references to certificates
from an SSL structure. Before this once a certificate had been added
it couldn't be removed.
[Steve Henson]
*) Integrate hostname, email address and IP address checking with certificate
verification. New verify options supporting checking in openssl utility.
[Steve Henson]
*) Fixes and wildcard matching support to hostname and email checking
functions. Add manual page.
[Florian Weimer (Red Hat Product Security Team)]
*) New functions to check a hostname email or IP address against a
certificate. Add options x509 utility to print results of checks against
a certificate.
[Steve Henson]
*) Fix OCSP checking.
[Rob Stradling <rob.stradling@comodo.com> and Ben Laurie]
*) Initial experimental support for explicitly trusted non-root CAs.
OpenSSL still tries to build a complete chain to a root but if an
intermediate CA has a trust setting included that is used. The first
setting is used: whether to trust (e.g., -addtrust option to the x509
utility) or reject.
[Steve Henson]
*) Add -trusted_first option which attempts to find certificates in the
trusted store even if an untrusted chain is also supplied.
[Steve Henson]
*) MIPS assembly pack updates: support for MIPS32r2 and SmartMIPS ASE,
platform support for Linux and Android.
[Andy Polyakov]
*) Support for linux-x32, ILP32 environment in x86_64 framework.
[Andy Polyakov]
*) Experimental multi-implementation support for FIPS capable OpenSSL.
When in FIPS mode the approved implementations are used as normal,
when not in FIPS mode the internal unapproved versions are used instead.
This means that the FIPS capable OpenSSL isn't forced to use the
(often lower performance) FIPS implementations outside FIPS mode.
[Steve Henson]
*) Transparently support X9.42 DH parameters when calling
PEM_read_bio_DHparameters. This means existing applications can handle
the new parameter format automatically.
[Steve Henson]
*) Initial experimental support for X9.42 DH parameter format: mainly
to support use of 'q' parameter for RFC5114 parameters.
[Steve Henson]
*) Add DH parameters from RFC5114 including test data to dhtest.
[Steve Henson]
*) Support for automatic EC temporary key parameter selection. If enabled
the most preferred EC parameters are automatically used instead of
hardcoded fixed parameters. Now a server just has to call:
SSL_CTX_set_ecdh_auto(ctx, 1) and the server will automatically
support ECDH and use the most appropriate parameters.
[Steve Henson]
*) Enhance and tidy EC curve and point format TLS extension code. Use
static structures instead of allocation if default values are used.
New ctrls to set curves we wish to support and to retrieve shared curves.
Print out shared curves in s_server. New options to s_server and s_client
to set list of supported curves.
[Steve Henson]
*) New ctrls to retrieve supported signature algorithms and
supported curve values as an array of NIDs. Extend openssl utility
to print out received values.
[Steve Henson]
*) Add new APIs EC_curve_nist2nid and EC_curve_nid2nist which convert
between NIDs and the more common NIST names such as "P-256". Enhance
ecparam utility and ECC method to recognise the NIST names for curves.
[Steve Henson]
*) Enhance SSL/TLS certificate chain handling to support different
chains for each certificate instead of one chain in the parent SSL_CTX.
[Steve Henson]
*) Support for fixed DH ciphersuite client authentication: where both
server and client use DH certificates with common parameters.
[Steve Henson]
*) Support for fixed DH ciphersuites: those requiring DH server
certificates.
[Steve Henson]
*) New function i2d_re_X509_tbs for re-encoding the TBS portion of
the certificate.
Note: Related 1.0.2-beta specific macros X509_get_cert_info,
X509_CINF_set_modified, X509_CINF_get_issuer, X509_CINF_get_extensions and
X509_CINF_get_signature were reverted post internal team review.
Changes between 1.0.1k and 1.0.1l [15 Jan 2015]
*) Build fixes for the Windows and OpenVMS platforms
[Matt Caswell and Richard Levitte]
Changes between 1.0.1j and 1.0.1k [8 Jan 2015]
*) Fix DTLS segmentation fault in dtls1_get_record. A carefully crafted DTLS
message can cause a segmentation fault in OpenSSL due to a NULL pointer
dereference. This could lead to a Denial Of Service attack. Thanks to
Markus Stenberg of Cisco Systems, Inc. for reporting this issue.
(CVE-2014-3571)
[Steve Henson]
*) Fix DTLS memory leak in dtls1_buffer_record. A memory leak can occur in the
dtls1_buffer_record function under certain conditions. In particular this
could occur if an attacker sent repeated DTLS records with the same
sequence number but for the next epoch. The memory leak could be exploited
by an attacker in a Denial of Service attack through memory exhaustion.
Thanks to Chris Mueller for reporting this issue.
(CVE-2015-0206)
[Matt Caswell]
*) Fix issue where no-ssl3 configuration sets method to NULL. When openssl is
built with the no-ssl3 option and a SSL v3 ClientHello is received the ssl
method would be set to NULL which could later result in a NULL pointer
dereference. Thanks to Frank Schmirler for reporting this issue.
(CVE-2014-3569)
[Kurt Roeckx]
*) Abort handshake if server key exchange message is omitted for ephemeral
ECDH ciphersuites.
Thanks to Karthikeyan Bhargavan of the PROSECCO team at INRIA for
reporting this issue.
(CVE-2014-3572)
[Steve Henson]
*) Remove non-export ephemeral RSA code on client and server. This code
violated the TLS standard by allowing the use of temporary RSA keys in
non-export ciphersuites and could be used by a server to effectively
downgrade the RSA key length used to a value smaller than the server
certificate. Thanks for Karthikeyan Bhargavan of the PROSECCO team at
INRIA or reporting this issue.
(CVE-2015-0204)
[Steve Henson]
*) Fixed issue where DH client certificates are accepted without verification.
An OpenSSL server will accept a DH certificate for client authentication
without the certificate verify message. This effectively allows a client to
authenticate without the use of a private key. This only affects servers
which trust a client certificate authority which issues certificates
containing DH keys: these are extremely rare and hardly ever encountered.
Thanks for Karthikeyan Bhargavan of the PROSECCO team at INRIA or reporting
this issue.
(CVE-2015-0205)
[Steve Henson]
*) Ensure that the session ID context of an SSL is updated when its
SSL_CTX is updated via SSL_set_SSL_CTX.
The session ID context is typically set from the parent SSL_CTX,
and can vary with the CTX.
[Adam Langley]
*) Fix various certificate fingerprint issues.
By using non-DER or invalid encodings outside the signed portion of a
certificate the fingerprint can be changed without breaking the signature.
Although no details of the signed portion of the certificate can be changed
this can cause problems with some applications: e.g. those using the
certificate fingerprint for blacklists.
1. Reject signatures with non zero unused bits.
If the BIT STRING containing the signature has non zero unused bits reject
the signature. All current signature algorithms require zero unused bits.
2. Check certificate algorithm consistency.
Check the AlgorithmIdentifier inside TBS matches the one in the
certificate signature. NB: this will result in signature failure
errors for some broken certificates.
Thanks to Konrad Kraszewski from Google for reporting this issue.
3. Check DSA/ECDSA signatures use DER.
Re-encode DSA/ECDSA signatures and compare with the original received
signature. Return an error if there is a mismatch.
This will reject various cases including garbage after signature
(thanks to Antti Karjalainen and Tuomo Untinen from the Codenomicon CROSS
program for discovering this case) and use of BER or invalid ASN.1 INTEGERs
(negative or with leading zeroes).
Further analysis was conducted and fixes were developed by Stephen Henson
of the OpenSSL core team.
(CVE-2014-8275)
[Steve Henson]
*) Correct Bignum squaring. Bignum squaring (BN_sqr) may produce incorrect
results on some platforms, including x86_64. This bug occurs at random
with a very low probability, and is not known to be exploitable in any
way, though its exact impact is difficult to determine. Thanks to Pieter
Wuille (Blockstream) who reported this issue and also suggested an initial
fix. Further analysis was conducted by the OpenSSL development team and
Adam Langley of Google. The final fix was developed by Andy Polyakov of
the OpenSSL core team.
(CVE-2014-3570)
[Andy Polyakov]
*) Do not resume sessions on the server if the negotiated protocol
version does not match the session's version. Resuming with a different
version, while not strictly forbidden by the RFC, is of questionable
sanity and breaks all known clients.
[David Benjamin, Emilia Käsper]
*) Tighten handling of the ChangeCipherSpec (CCS) message: reject
early CCS messages during renegotiation. (Note that because
renegotiation is encrypted, this early CCS was not exploitable.)
[Emilia Käsper]
*) Tighten client-side session ticket handling during renegotiation:
ensure that the client only accepts a session ticket if the server sends
the extension anew in the ServerHello. Previously, a TLS client would
reuse the old extension state and thus accept a session ticket if one was
announced in the initial ServerHello.
Similarly, ensure that the client requires a session ticket if one
was advertised in the ServerHello. Previously, a TLS client would
ignore a missing NewSessionTicket message.
[Emilia Käsper]
Changes between 1.0.1i and 1.0.1j [15 Oct 2014]
*) SRTP Memory Leak.
A flaw in the DTLS SRTP extension parsing code allows an attacker, who
sends a carefully crafted handshake message, to cause OpenSSL to fail
to free up to 64k of memory causing a memory leak. This could be
exploited in a Denial Of Service attack. This issue affects OpenSSL
1.0.1 server implementations for both SSL/TLS and DTLS regardless of
whether SRTP is used or configured. Implementations of OpenSSL that
have been compiled with OPENSSL_NO_SRTP defined are not affected.
The fix was developed by the OpenSSL team.
(CVE-2014-3513)
[OpenSSL team]
*) Session Ticket Memory Leak.
When an OpenSSL SSL/TLS/DTLS server receives a session ticket the
integrity of that ticket is first verified. In the event of a session
ticket integrity check failing, OpenSSL will fail to free memory
causing a memory leak. By sending a large number of invalid session
tickets an attacker could exploit this issue in a Denial Of Service
attack.
(CVE-2014-3567)
[Steve Henson]
*) Build option no-ssl3 is incomplete.
When OpenSSL is configured with "no-ssl3" as a build option, servers
could accept and complete a SSL 3.0 handshake, and clients could be
configured to send them.
(CVE-2014-3568)
[Akamai and the OpenSSL team]
*) Add support for TLS_FALLBACK_SCSV.
Client applications doing fallback retries should call
SSL_set_mode(s, SSL_MODE_SEND_FALLBACK_SCSV).
(CVE-2014-3566)
[Adam Langley, Bodo Moeller]
*) Add additional DigestInfo checks.
Re-encode DigestInto in DER and check against the original when
verifying RSA signature: this will reject any improperly encoded
DigestInfo structures.
Note: this is a precautionary measure and no attacks are currently known.
[Steve Henson]
Changes between 1.0.1h and 1.0.1i [6 Aug 2014]
*) Fix SRP buffer overrun vulnerability. Invalid parameters passed to the
SRP code can be overrun an internal buffer. Add sanity check that
g, A, B < N to SRP code.
Thanks to Sean Devlin and Watson Ladd of Cryptography Services, NCC
Group for discovering this issue.
(CVE-2014-3512)
[Steve Henson]
*) A flaw in the OpenSSL SSL/TLS server code causes the server to negotiate
TLS 1.0 instead of higher protocol versions when the ClientHello message
is badly fragmented. This allows a man-in-the-middle attacker to force a
downgrade to TLS 1.0 even if both the server and the client support a
higher protocol version, by modifying the client's TLS records.
Thanks to David Benjamin and Adam Langley (Google) for discovering and
researching this issue.
(CVE-2014-3511)
[David Benjamin]
*) OpenSSL DTLS clients enabling anonymous (EC)DH ciphersuites are subject
to a denial of service attack. A malicious server can crash the client
with a null pointer dereference (read) by specifying an anonymous (EC)DH
ciphersuite and sending carefully crafted handshake messages.
Thanks to Felix Gröbert (Google) for discovering and researching this
issue.
(CVE-2014-3510)
[Emilia Käsper]
*) By sending carefully crafted DTLS packets an attacker could cause openssl
to leak memory. This can be exploited through a Denial of Service attack.
Thanks to Adam Langley for discovering and researching this issue.
(CVE-2014-3507)
[Adam Langley]
*) An attacker can force openssl to consume large amounts of memory whilst
processing DTLS handshake messages. This can be exploited through a
Denial of Service attack.
Thanks to Adam Langley for discovering and researching this issue.
(CVE-2014-3506)
[Adam Langley]
*) An attacker can force an error condition which causes openssl to crash
whilst processing DTLS packets due to memory being freed twice. This
can be exploited through a Denial of Service attack.
Thanks to Adam Langley and Wan-Teh Chang for discovering and researching
this issue.
(CVE-2014-3505)
[Adam Langley]
*) If a multithreaded client connects to a malicious server using a resumed
session and the server sends an ec point format extension it could write
up to 255 bytes to freed memory.
Thanks to Gabor Tyukasz (LogMeIn Inc) for discovering and researching this
issue.
(CVE-2014-3509)
[Gabor Tyukasz]
*) A malicious server can crash an OpenSSL client with a null pointer
dereference (read) by specifying an SRP ciphersuite even though it was not
properly negotiated with the client. This can be exploited through a
Denial of Service attack.
Thanks to Joonas Kuorilehto and Riku Hietamäki (Codenomicon) for
discovering and researching this issue.
(CVE-2014-5139)
[Steve Henson]
*) A flaw in OBJ_obj2txt may cause pretty printing functions such as
X509_name_oneline, X509_name_print_ex et al. to leak some information
from the stack. Applications may be affected if they echo pretty printing
output to the attacker.
Thanks to Ivan Fratric (Google) for discovering this issue.
(CVE-2014-3508)
[Emilia Käsper, and Steve Henson]
*) Fix ec_GFp_simple_points_make_affine (thus, EC_POINTs_mul etc.)
for corner cases. (Certain input points at infinity could lead to
bogus results, with non-infinity inputs mapped to infinity too.)
[Bodo Moeller]
Changes between 1.0.1g and 1.0.1h [5 Jun 2014]
*) Fix for SSL/TLS MITM flaw. An attacker using a carefully crafted
handshake can force the use of weak keying material in OpenSSL
SSL/TLS clients and servers.
Thanks to KIKUCHI Masashi (Lepidum Co. Ltd.) for discovering and
researching this issue. (CVE-2014-0224)
[KIKUCHI Masashi, Steve Henson]
*) Fix DTLS recursion flaw. By sending an invalid DTLS handshake to an
OpenSSL DTLS client the code can be made to recurse eventually crashing
in a DoS attack.
Thanks to Imre Rad (Search-Lab Ltd.) for discovering this issue.
(CVE-2014-0221)
[Imre Rad, Steve Henson]
*) Fix DTLS invalid fragment vulnerability. A buffer overrun attack can
be triggered by sending invalid DTLS fragments to an OpenSSL DTLS
client or server. This is potentially exploitable to run arbitrary
code on a vulnerable client or server.
Thanks to Jüri Aedla for reporting this issue. (CVE-2014-0195)
[Jüri Aedla, Steve Henson]
*) Fix bug in TLS code where clients enable anonymous ECDH ciphersuites
are subject to a denial of service attack.
Thanks to Felix Gröbert and Ivan Fratric at Google for discovering
this issue. (CVE-2014-3470)
[Felix Gröbert, Ivan Fratric, Steve Henson]
*) Harmonize version and its documentation. -f flag is used to display
compilation flags.
[mancha <mancha1@zoho.com>]
*) Fix eckey_priv_encode so it immediately returns an error upon a failure
in i2d_ECPrivateKey.
[mancha <mancha1@zoho.com>]
*) Fix some double frees. These are not thought to be exploitable.
[mancha <mancha1@zoho.com>]
Changes between 1.0.1f and 1.0.1g [7 Apr 2014]
*) A missing bounds check in the handling of the TLS heartbeat extension
can be used to reveal up to 64k of memory to a connected client or
server.
Thanks for Neel Mehta of Google Security for discovering this bug and to
Adam Langley <agl@chromium.org> and Bodo Moeller <bmoeller@acm.org> for
preparing the fix (CVE-2014-0160)
[Adam Langley, Bodo Moeller]
*) Fix for the attack described in the paper "Recovering OpenSSL
ECDSA Nonces Using the FLUSH+RELOAD Cache Side-channel Attack"
by Yuval Yarom and Naomi Benger. Details can be obtained from:
http://eprint.iacr.org/2014/140
Thanks to Yuval Yarom and Naomi Benger for discovering this
flaw and to Yuval Yarom for supplying a fix (CVE-2014-0076)
[Yuval Yarom and Naomi Benger]
*) TLS pad extension: draft-agl-tls-padding-03
Workaround for the "TLS hang bug" (see FAQ and PR#2771): if the
TLS client Hello record length value would otherwise be > 255 and
less that 512 pad with a dummy extension containing zeroes so it
is at least 512 bytes long.
[Adam Langley, Steve Henson]
Changes between 1.0.1e and 1.0.1f [6 Jan 2014]
*) Fix for TLS record tampering bug. A carefully crafted invalid
handshake could crash OpenSSL with a NULL pointer exception.
Thanks to Anton Johansson for reporting this issues.
(CVE-2013-4353)
*) Keep original DTLS digest and encryption contexts in retransmission
structures so we can use the previous session parameters if they need
to be resent. (CVE-2013-6450)
[Steve Henson]
*) Add option SSL_OP_SAFARI_ECDHE_ECDSA_BUG (part of SSL_OP_ALL) which
avoids preferring ECDHE-ECDSA ciphers when the client appears to be
Safari on OS X. Safari on OS X 10.8..10.8.3 advertises support for
several ECDHE-ECDSA ciphers, but fails to negotiate them. The bug
is fixed in OS X 10.8.4, but Apple have ruled out both hot fixing
10.8..10.8.3 and forcing users to upgrade to 10.8.4 or newer.
[Rob Stradling, Adam Langley]
Changes between 1.0.1d and 1.0.1e [11 Feb 2013]
*) Correct fix for CVE-2013-0169. The original didn't work on AES-NI
supporting platforms or when small records were transferred.
[Andy Polyakov, Steve Henson]
Changes between 1.0.1c and 1.0.1d [5 Feb 2013]
*) Make the decoding of SSLv3, TLS and DTLS CBC records constant time.
This addresses the flaw in CBC record processing discovered by
Nadhem Alfardan and Kenny Paterson. Details of this attack can be found
at: http://www.isg.rhul.ac.uk/tls/
Thanks go to Nadhem Alfardan and Kenny Paterson of the Information
Security Group at Royal Holloway, University of London
(www.isg.rhul.ac.uk) for discovering this flaw and Adam Langley and
Emilia Käsper for the initial patch.
(CVE-2013-0169)
[Emilia Käsper, Adam Langley, Ben Laurie, Andy Polyakov, Steve Henson]
*) Fix flaw in AESNI handling of TLS 1.2 and 1.1 records for CBC mode
ciphersuites which can be exploited in a denial of service attack.
Thanks go to and to Adam Langley <agl@chromium.org> for discovering
and detecting this bug and to Wolfgang Ettlinger
<wolfgang.ettlinger@gmail.com> for independently discovering this issue.
(CVE-2012-2686)
[Adam Langley]
*) Return an error when checking OCSP signatures when key is NULL.
This fixes a DoS attack. (CVE-2013-0166)
[Steve Henson]
*) Make openssl verify return errors.
[Chris Palmer <palmer@google.com> and Ben Laurie]
*) Call OCSP Stapling callback after ciphersuite has been chosen, so
the right response is stapled. Also change SSL_get_certificate()
so it returns the certificate actually sent.
See http://rt.openssl.org/Ticket/Display.html?id=2836.
[Rob Stradling <rob.stradling@comodo.com>]
*) Fix possible deadlock when decoding public keys.
[Steve Henson]
*) Don't use TLS 1.0 record version number in initial client hello
if renegotiating.
[Steve Henson]
Changes between 1.0.1b and 1.0.1c [10 May 2012]
*) Sanity check record length before skipping explicit IV in TLS
1.2, 1.1 and DTLS to fix DoS attack.
Thanks to Codenomicon for discovering this issue using Fuzz-o-Matic
fuzzing as a service testing platform.
(CVE-2012-2333)
[Steve Henson]
*) Initialise tkeylen properly when encrypting CMS messages.
Thanks to Solar Designer of Openwall for reporting this issue.
[Steve Henson]
*) In FIPS mode don't try to use composite ciphers as they are not
approved.
[Steve Henson]
Changes between 1.0.1a and 1.0.1b [26 Apr 2012]
*) OpenSSL 1.0.0 sets SSL_OP_ALL to 0x80000FFFL and OpenSSL 1.0.1 and
1.0.1a set SSL_OP_NO_TLSv1_1 to 0x00000400L which would unfortunately
mean any application compiled against OpenSSL 1.0.0 headers setting
SSL_OP_ALL would also set SSL_OP_NO_TLSv1_1, unintentionally disabling
TLS 1.1 also. Fix this by changing the value of SSL_OP_NO_TLSv1_1 to
0x10000000L Any application which was previously compiled against
OpenSSL 1.0.1 or 1.0.1a headers and which cares about SSL_OP_NO_TLSv1_1
will need to be recompiled as a result. Letting be results in
inability to disable specifically TLS 1.1 and in client context,
in unlike event, limit maximum offered version to TLS 1.0 [see below].
[Steve Henson]
*) In order to ensure interoperability SSL_OP_NO_protocolX does not
disable just protocol X, but all protocols above X *if* there are
protocols *below* X still enabled. In more practical terms it means
that if application wants to disable TLS1.0 in favor of TLS1.1 and
above, it's not sufficient to pass SSL_OP_NO_TLSv1, one has to pass
SSL_OP_NO_TLSv1|SSL_OP_NO_SSLv3|SSL_OP_NO_SSLv2. This applies to
client side.
[Andy Polyakov]
Changes between 1.0.1 and 1.0.1a [19 Apr 2012]
*) Check for potentially exploitable overflows in asn1_d2i_read_bio
BUF_mem_grow and BUF_mem_grow_clean. Refuse attempts to shrink buffer
in CRYPTO_realloc_clean.
Thanks to Tavis Ormandy, Google Security Team, for discovering this
issue and to Adam Langley <agl@chromium.org> for fixing it.
(CVE-2012-2110)
[Adam Langley (Google), Tavis Ormandy, Google Security Team]
*) Don't allow TLS 1.2 SHA-256 ciphersuites in TLS 1.0, 1.1 connections.
[Adam Langley]
*) Workarounds for some broken servers that "hang" if a client hello
record length exceeds 255 bytes.
1. Do not use record version number > TLS 1.0 in initial client
hello: some (but not all) hanging servers will now work.
2. If we set OPENSSL_MAX_TLS1_2_CIPHER_LENGTH this will truncate
the number of ciphers sent in the client hello. This should be
set to an even number, such as 50, for example by passing:
-DOPENSSL_MAX_TLS1_2_CIPHER_LENGTH=50 to config or Configure.
Most broken servers should now work.
3. If all else fails setting OPENSSL_NO_TLS1_2_CLIENT will disable
TLS 1.2 client support entirely.
[Steve Henson]
*) Fix SEGV in Vector Permutation AES module observed in OpenSSH.
[Andy Polyakov]
Changes between 1.0.0h and 1.0.1 [14 Mar 2012]
*) Add compatibility with old MDC2 signatures which use an ASN1 OCTET
STRING form instead of a DigestInfo.
[Steve Henson]
*) The format used for MDC2 RSA signatures is inconsistent between EVP
and the RSA_sign/RSA_verify functions. This was made more apparent when
OpenSSL used RSA_sign/RSA_verify for some RSA signatures in particular
those which went through EVP_PKEY_METHOD in 1.0.0 and later. Detect
the correct format in RSA_verify so both forms transparently work.
[Steve Henson]
*) Some servers which support TLS 1.0 can choke if we initially indicate
support for TLS 1.2 and later renegotiate using TLS 1.0 in the RSA
encrypted premaster secret. As a workaround use the maximum permitted
client version in client hello, this should keep such servers happy
and still work with previous versions of OpenSSL.
[Steve Henson]
*) Add support for TLS/DTLS heartbeats.
[Robin Seggelmann <seggelmann@fh-muenster.de>]
*) Add support for SCTP.
[Robin Seggelmann <seggelmann@fh-muenster.de>]
*) Improved PRNG seeding for VOS.
[Paul Green <Paul.Green@stratus.com>]
*) Extensive assembler packs updates, most notably:
- x86[_64]: AES-NI, PCLMULQDQ, RDRAND support;
- x86[_64]: SSSE3 support (SHA1, vector-permutation AES);
- x86_64: bit-sliced AES implementation;
- ARM: NEON support, contemporary platforms optimizations;
- s390x: z196 support;
- *: GHASH and GF(2^m) multiplication implementations;
[Andy Polyakov]
*) Make TLS-SRP code conformant with RFC 5054 API cleanup
(removal of unnecessary code)
[Peter Sylvester <peter.sylvester@edelweb.fr>]
*) Add TLS key material exporter from RFC 5705.
[Eric Rescorla]
*) Add DTLS-SRTP negotiation from RFC 5764.
[Eric Rescorla]
*) Add Next Protocol Negotiation,
http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-00. Can be
disabled with a no-npn flag to config or Configure. Code donated
by Google.
[Adam Langley <agl@google.com> and Ben Laurie]
*) Add optional 64-bit optimized implementations of elliptic curves NIST-P224,
NIST-P256, NIST-P521, with constant-time single point multiplication on
typical inputs. Compiler support for the nonstandard type __uint128_t is
required to use this (present in gcc 4.4 and later, for 64-bit builds).
Code made available under Apache License version 2.0.
Specify "enable-ec_nistp_64_gcc_128" on the Configure (or config) command
line to include this in your build of OpenSSL, and run "make depend" (or
"make update"). This enables the following EC_METHODs:
EC_GFp_nistp224_method()
EC_GFp_nistp256_method()
EC_GFp_nistp521_method()
EC_GROUP_new_by_curve_name() will automatically use these (while
EC_GROUP_new_curve_GFp() currently prefers the more flexible
implementations).
[Emilia Käsper, Adam Langley, Bodo Moeller (Google)]
*) Use type ossl_ssize_t instad of ssize_t which isn't available on
all platforms. Move ssize_t definition from e_os.h to the public
header file e_os2.h as it now appears in public header file cms.h
[Steve Henson]
*) New -sigopt option to the ca, req and x509 utilities. Additional
signature parameters can be passed using this option and in
particular PSS.
[Steve Henson]
*) Add RSA PSS signing function. This will generate and set the
appropriate AlgorithmIdentifiers for PSS based on those in the
corresponding EVP_MD_CTX structure. No application support yet.
[Steve Henson]
*) Support for companion algorithm specific ASN1 signing routines.
New function ASN1_item_sign_ctx() signs a pre-initialised
EVP_MD_CTX structure and sets AlgorithmIdentifiers based on
the appropriate parameters.
[Steve Henson]
*) Add new algorithm specific ASN1 verification initialisation function
to EVP_PKEY_ASN1_METHOD: this is not in EVP_PKEY_METHOD since the ASN1
handling will be the same no matter what EVP_PKEY_METHOD is used.
Add a PSS handler to support verification of PSS signatures: checked
against a number of sample certificates.
[Steve Henson]
*) Add signature printing for PSS. Add PSS OIDs.
[Steve Henson, Martin Kaiser <lists@kaiser.cx>]
*) Add algorithm specific signature printing. An individual ASN1 method
can now print out signatures instead of the standard hex dump.
More complex signatures (e.g. PSS) can print out more meaningful
information. Include DSA version that prints out the signature
parameters r, s.
[Steve Henson]
*) Password based recipient info support for CMS library: implementing
RFC3211.
[Steve Henson]
*) Split password based encryption into PBES2 and PBKDF2 functions. This
neatly separates the code into cipher and PBE sections and is required
for some algorithms that split PBES2 into separate pieces (such as
password based CMS).
[Steve Henson]
*) Session-handling fixes:
- Fix handling of connections that are resuming with a session ID,
but also support Session Tickets.
- Fix a bug that suppressed issuing of a new ticket if the client
presented a ticket with an expired session.
- Try to set the ticket lifetime hint to something reasonable.
- Make tickets shorter by excluding irrelevant information.
- On the client side, don't ignore renewed tickets.
[Adam Langley, Bodo Moeller (Google)]
*) Fix PSK session representation.
[Bodo Moeller]
*) Add RC4-MD5 and AESNI-SHA1 "stitched" implementations.
This work was sponsored by Intel.
[Andy Polyakov]
*) Add GCM support to TLS library. Some custom code is needed to split
the IV between the fixed (from PRF) and explicit (from TLS record)
portions. This adds all GCM ciphersuites supported by RFC5288 and
RFC5289. Generalise some AES* cipherstrings to include GCM and
add a special AESGCM string for GCM only.
[Steve Henson]
*) Expand range of ctrls for AES GCM. Permit setting invocation
field on decrypt and retrieval of invocation field only on encrypt.
[Steve Henson]
*) Add HMAC ECC ciphersuites from RFC5289. Include SHA384 PRF support.
As required by RFC5289 these ciphersuites cannot be used if for
versions of TLS earlier than 1.2.
[Steve Henson]
*) For FIPS capable OpenSSL interpret a NULL default public key method
as unset and return the appropriate default but do *not* set the default.
This means we can return the appropriate method in applications that
switch between FIPS and non-FIPS modes.
[Steve Henson]
*) Redirect HMAC and CMAC operations to FIPS module in FIPS mode. If an
ENGINE is used then we cannot handle that in the FIPS module so we
keep original code iff non-FIPS operations are allowed.
[Steve Henson]
*) Add -attime option to openssl utilities.
[Peter Eckersley <pde@eff.org>, Ben Laurie and Steve Henson]
*) Redirect DSA and DH operations to FIPS module in FIPS mode.
[Steve Henson]
*) Redirect ECDSA and ECDH operations to FIPS module in FIPS mode. Also use
FIPS EC methods unconditionally for now.
[Steve Henson]
*) New build option no-ec2m to disable characteristic 2 code.
[Steve Henson]
*) Backport libcrypto audit of return value checking from 1.1.0-dev; not
all cases can be covered as some introduce binary incompatibilities.
[Steve Henson]
*) Redirect RSA operations to FIPS module including keygen,
encrypt, decrypt, sign and verify. Block use of non FIPS RSA methods.
[Steve Henson]
*) Add similar low level API blocking to ciphers.
[Steve Henson]
*) Low level digest APIs are not approved in FIPS mode: any attempt
to use these will cause a fatal error. Applications that *really* want
to use them can use the private_* version instead.
[Steve Henson]
*) Redirect cipher operations to FIPS module for FIPS builds.
[Steve Henson]
*) Redirect digest operations to FIPS module for FIPS builds.
[Steve Henson]
*) Update build system to add "fips" flag which will link in fipscanister.o
for static and shared library builds embedding a signature if needed.
[Steve Henson]
*) Output TLS supported curves in preference order instead of numerical
order. This is currently hardcoded for the highest order curves first.
This should be configurable so applications can judge speed vs strength.
[Steve Henson]
*) Add TLS v1.2 server support for client authentication.
[Steve Henson]
*) Add support for FIPS mode in ssl library: disable SSLv3, non-FIPS ciphers
and enable MD5.
[Steve Henson]
*) Functions FIPS_mode_set() and FIPS_mode() which call the underlying
FIPS modules versions.
[Steve Henson]
*) Add TLS v1.2 client side support for client authentication. Keep cache
of handshake records longer as we don't know the hash algorithm to use
until after the certificate request message is received.
[Steve Henson]
*) Initial TLS v1.2 client support. Add a default signature algorithms
extension including all the algorithms we support. Parse new signature
format in client key exchange. Relax some ECC signing restrictions for
TLS v1.2 as indicated in RFC5246.
[Steve Henson]
*) Add server support for TLS v1.2 signature algorithms extension. Switch
to new signature format when needed using client digest preference.
All server ciphersuites should now work correctly in TLS v1.2. No client
support yet and no support for client certificates.
[Steve Henson]
*) Initial TLS v1.2 support. Add new SHA256 digest to ssl code, switch
to SHA256 for PRF when using TLS v1.2 and later. Add new SHA256 based
ciphersuites. At present only RSA key exchange ciphersuites work with
TLS v1.2. Add new option for TLS v1.2 replacing the old and obsolete
SSL_OP_PKCS1_CHECK flags with SSL_OP_NO_TLSv1_2. New TLSv1.2 methods
and version checking.
[Steve Henson]
*) New option OPENSSL_NO_SSL_INTERN. If an application can be compiled
with this defined it will not be affected by any changes to ssl internal
structures. Add several utility functions to allow openssl application
to work with OPENSSL_NO_SSL_INTERN defined.
[Steve Henson]
*) A long standing patch to add support for SRP from EdelWeb (Peter
Sylvester and Christophe Renou) was integrated.
[Christophe Renou <christophe.renou@edelweb.fr>, Peter Sylvester
<peter.sylvester@edelweb.fr>, Tom Wu <tjw@cs.stanford.edu>, and
Ben Laurie]
*) Add functions to copy EVP_PKEY_METHOD and retrieve flags and id.
[Steve Henson]
*) Permit abbreviated handshakes when renegotiating using the function
SSL_renegotiate_abbreviated().
[Robin Seggelmann <seggelmann@fh-muenster.de>]
*) Add call to ENGINE_register_all_complete() to
ENGINE_load_builtin_engines(), so some implementations get used
automatically instead of needing explicit application support.
[Steve Henson]
*) Add support for TLS key exporter as described in RFC5705.
[Robin Seggelmann <seggelmann@fh-muenster.de>, Steve Henson]
*) Initial TLSv1.1 support. Since TLSv1.1 is very similar to TLS v1.0 only
a few changes are required:
Add SSL_OP_NO_TLSv1_1 flag.
Add TLSv1_1 methods.
Update version checking logic to handle version 1.1.
Add explicit IV handling (ported from DTLS code).
Add command line options to s_client/s_server.
[Steve Henson]
Changes between 1.0.0g and 1.0.0h [12 Mar 2012]
*) Fix MMA (Bleichenbacher's attack on PKCS #1 v1.5 RSA padding) weakness
in CMS and PKCS7 code. When RSA decryption fails use a random key for
content decryption and always return the same error. Note: this attack
needs on average 2^20 messages so it only affects automated senders. The
old behaviour can be re-enabled in the CMS code by setting the
CMS_DEBUG_DECRYPT flag: this is useful for debugging and testing where
an MMA defence is not necessary.
Thanks to Ivan Nestlerode <inestlerode@us.ibm.com> for discovering
this issue. (CVE-2012-0884)
[Steve Henson]
*) Fix CVE-2011-4619: make sure we really are receiving a
client hello before rejecting multiple SGC restarts. Thanks to
Ivan Nestlerode <inestlerode@us.ibm.com> for discovering this bug.
[Steve Henson]
Changes between 1.0.0f and 1.0.0g [18 Jan 2012]
*) Fix for DTLS DoS issue introduced by fix for CVE-2011-4109.
Thanks to Antonio Martin, Enterprise Secure Access Research and
Development, Cisco Systems, Inc. for discovering this bug and
preparing a fix. (CVE-2012-0050)
[Antonio Martin]
Changes between 1.0.0e and 1.0.0f [4 Jan 2012]
*) Nadhem Alfardan and Kenny Paterson have discovered an extension
of the Vaudenay padding oracle attack on CBC mode encryption
which enables an efficient plaintext recovery attack against
the OpenSSL implementation of DTLS. Their attack exploits timing
differences arising during decryption processing. A research
paper describing this attack can be found at:
http://www.isg.rhul.ac.uk/~kp/dtls.pdf
Thanks go to Nadhem Alfardan and Kenny Paterson of the Information
Security Group at Royal Holloway, University of London
(www.isg.rhul.ac.uk) for discovering this flaw and to Robin Seggelmann
<seggelmann@fh-muenster.de> and Michael Tuexen <tuexen@fh-muenster.de>
for preparing the fix. (CVE-2011-4108)
[Robin Seggelmann, Michael Tuexen]
*) Clear bytes used for block padding of SSL 3.0 records.
(CVE-2011-4576)
[Adam Langley (Google)]
*) Only allow one SGC handshake restart for SSL/TLS. Thanks to George
Kadianakis <desnacked@gmail.com> for discovering this issue and
Adam Langley for preparing the fix. (CVE-2011-4619)
[Adam Langley (Google)]
*) Check parameters are not NULL in GOST ENGINE. (CVE-2012-0027)
[Andrey Kulikov <amdeich@gmail.com>]
*) Prevent malformed RFC3779 data triggering an assertion failure.
Thanks to Andrew Chi, BBN Technologies, for discovering the flaw
and Rob Austein <sra@hactrn.net> for fixing it. (CVE-2011-4577)
[Rob Austein <sra@hactrn.net>]
*) Improved PRNG seeding for VOS.
[Paul Green <Paul.Green@stratus.com>]
*) Fix ssl_ciph.c set-up race.
[Adam Langley (Google)]
*) Fix spurious failures in ecdsatest.c.
[Emilia Käsper (Google)]
*) Fix the BIO_f_buffer() implementation (which was mixing different
interpretations of the '..._len' fields).
[Adam Langley (Google)]
*) Fix handling of BN_BLINDING: now BN_BLINDING_invert_ex (rather than
BN_BLINDING_invert_ex) calls BN_BLINDING_update, ensuring that concurrent
threads won't reuse the same blinding coefficients.
This also avoids the need to obtain the CRYPTO_LOCK_RSA_BLINDING
lock to call BN_BLINDING_invert_ex, and avoids one use of
BN_BLINDING_update for each BN_BLINDING structure (previously,
the last update always remained unused).
[Emilia Käsper (Google)]
*) In ssl3_clear, preserve s3->init_extra along with s3->rbuf.
[Bob Buckholz (Google)]
Changes between 1.0.0d and 1.0.0e [6 Sep 2011]
*) Fix bug where CRLs with nextUpdate in the past are sometimes accepted
by initialising X509_STORE_CTX properly. (CVE-2011-3207)
[Kaspar Brand <ossl@velox.ch>]
*) Fix SSL memory handling for (EC)DH ciphersuites, in particular
for multi-threaded use of ECDH. (CVE-2011-3210)
[Adam Langley (Google)]
*) Fix x509_name_ex_d2i memory leak on bad inputs.
[Bodo Moeller]
*) Remove hard coded ecdsaWithSHA1 signature tests in ssl code and check
signature public key algorithm by using OID xref utilities instead.
Before this you could only use some ECC ciphersuites with SHA1 only.
[Steve Henson]
*) Add protection against ECDSA timing attacks as mentioned in the paper
by Billy Bob Brumley and Nicola Tuveri, see:
http://eprint.iacr.org/2011/232.pdf
[Billy Bob Brumley and Nicola Tuveri]
Changes between 1.0.0c and 1.0.0d [8 Feb 2011]
*) Fix parsing of OCSP stapling ClientHello extension. CVE-2011-0014
[Neel Mehta, Adam Langley, Bodo Moeller (Google)]
*) Fix bug in string printing code: if *any* escaping is enabled we must
escape the escape character (backslash) or the resulting string is
ambiguous.
[Steve Henson]
Changes between 1.0.0b and 1.0.0c [2 Dec 2010]
*) Disable code workaround for ancient and obsolete Netscape browsers
and servers: an attacker can use it in a ciphersuite downgrade attack.
Thanks to Martin Rex for discovering this bug. CVE-2010-4180
[Steve Henson]
*) Fixed J-PAKE implementation error, originally discovered by
Sebastien Martini, further info and confirmation from Stefan
Arentz and Feng Hao. Note that this fix is a security fix. CVE-2010-4252
[Ben Laurie]
Changes between 1.0.0a and 1.0.0b [16 Nov 2010]
*) Fix extension code to avoid race conditions which can result in a buffer
overrun vulnerability: resumed sessions must not be modified as they can
be shared by multiple threads. CVE-2010-3864
[Steve Henson]
*) Fix WIN32 build system to correctly link an ENGINE directory into
a DLL.
[Steve Henson]
Changes between 1.0.0 and 1.0.0a [01 Jun 2010]
*) Check return value of int_rsa_verify in pkey_rsa_verifyrecover
(CVE-2010-1633)
[Steve Henson, Peter-Michael Hager <hager@dortmund.net>]
Changes between 0.9.8n and 1.0.0 [29 Mar 2010]
*) Add "missing" function EVP_CIPHER_CTX_copy(). This copies a cipher
context. The operation can be customised via the ctrl mechanism in
case ENGINEs want to include additional functionality.
[Steve Henson]
*) Tolerate yet another broken PKCS#8 key format: private key value negative.
[Steve Henson]
*) Add new -subject_hash_old and -issuer_hash_old options to x509 utility to
output hashes compatible with older versions of OpenSSL.
[Willy Weisz <weisz@vcpc.univie.ac.at>]
*) Fix compression algorithm handling: if resuming a session use the
compression algorithm of the resumed session instead of determining
it from client hello again. Don't allow server to change algorithm.
[Steve Henson]
*) Add load_crls() function to apps tidying load_certs() too. Add option
to verify utility to allow additional CRLs to be included.
[Steve Henson]
*) Update OCSP request code to permit adding custom headers to the request:
some responders need this.
[Steve Henson]
*) The function EVP_PKEY_sign() returns <=0 on error: check return code
correctly.
[Julia Lawall <julia@diku.dk>]
*) Update verify callback code in apps/s_cb.c and apps/verify.c, it
needlessly dereferenced structures, used obsolete functions and
didn't handle all updated verify codes correctly.
[Steve Henson]
*) Disable MD2 in the default configuration.
[Steve Henson]
*) In BIO_pop() and BIO_push() use the ctrl argument (which was NULL) to
indicate the initial BIO being pushed or popped. This makes it possible
to determine whether the BIO is the one explicitly called or as a result
of the ctrl being passed down the chain. Fix BIO_pop() and SSL BIOs so
it handles reference counts correctly and doesn't zero out the I/O bio
when it is not being explicitly popped. WARNING: applications which
included workarounds for the old buggy behaviour will need to be modified
or they could free up already freed BIOs.
[Steve Henson]
*) Extend the uni2asc/asc2uni => OPENSSL_uni2asc/OPENSSL_asc2uni
renaming to all platforms (within the 0.9.8 branch, this was
done conditionally on Netware platforms to avoid a name clash).
[Guenter <lists@gknw.net>]
*) Add ECDHE and PSK support to DTLS.
[Michael Tuexen <tuexen@fh-muenster.de>]
*) Add CHECKED_STACK_OF macro to safestack.h, otherwise safestack can't
be used on C++.
[Steve Henson]
*) Add "missing" function EVP_MD_flags() (without this the only way to
retrieve a digest flags is by accessing the structure directly. Update
EVP_MD_do_all*() and EVP_CIPHER_do_all*() to include the name a digest
or cipher is registered as in the "from" argument. Print out all
registered digests in the dgst usage message instead of manually
attempting to work them out.
[Steve Henson]
*) If no SSLv2 ciphers are used don't use an SSLv2 compatible client hello:
this allows the use of compression and extensions. Change default cipher
string to remove SSLv2 ciphersuites. This effectively avoids ancient SSLv2
by default unless an application cipher string requests it.
[Steve Henson]
*) Alter match criteria in PKCS12_parse(). It used to try to use local
key ids to find matching certificates and keys but some PKCS#12 files
don't follow the (somewhat unwritten) rules and this strategy fails.
Now just gather all certificates together and the first private key
then look for the first certificate that matches the key.
[Steve Henson]
*) Support use of registered digest and cipher names for dgst and cipher
commands instead of having to add each one as a special case. So now
you can do:
openssl sha256 foo
as well as:
openssl dgst -sha256 foo
and this works for ENGINE based algorithms too.
[Steve Henson]
*) Update Gost ENGINE to support parameter files.
[Victor B. Wagner <vitus@cryptocom.ru>]
*) Support GeneralizedTime in ca utility.
[Oliver Martin <oliver@volatilevoid.net>, Steve Henson]
*) Enhance the hash format used for certificate directory links. The new
form uses the canonical encoding (meaning equivalent names will work
even if they aren't identical) and uses SHA1 instead of MD5. This form
is incompatible with the older format and as a result c_rehash should
be used to rebuild symbolic links.
[Steve Henson]
*) Make PKCS#8 the default write format for private keys, replacing the
traditional format. This form is standardised, more secure and doesn't
include an implicit MD5 dependency.
[Steve Henson]
*) Add a $gcc_devteam_warn option to Configure. The idea is that any code
committed to OpenSSL should pass this lot as a minimum.
[Steve Henson]
*) Add session ticket override functionality for use by EAP-FAST.
[Jouni Malinen <j@w1.fi>]
*) Modify HMAC functions to return a value. Since these can be implemented
in an ENGINE errors can occur.
[Steve Henson]
*) Type-checked OBJ_bsearch_ex.
[Ben Laurie]
*) Type-checked OBJ_bsearch. Also some constification necessitated
by type-checking. Still to come: TXT_DB, bsearch(?),
OBJ_bsearch_ex, qsort, CRYPTO_EX_DATA, ASN1_VALUE, ASN1_STRING,
CONF_VALUE.
[Ben Laurie]
*) New function OPENSSL_gmtime_adj() to add a specific number of days and
seconds to a tm structure directly, instead of going through OS
specific date routines. This avoids any issues with OS routines such
as the year 2038 bug. New *_adj() functions for ASN1 time structures
and X509_time_adj_ex() to cover the extended range. The existing
X509_time_adj() is still usable and will no longer have any date issues.
[Steve Henson]
*) Delta CRL support. New use deltas option which will attempt to locate
and search any appropriate delta CRLs available.
This work was sponsored by Google.
[Steve Henson]
*) Support for CRLs partitioned by reason code. Reorganise CRL processing
code and add additional score elements. Validate alternate CRL paths
as part of the CRL checking and indicate a new error "CRL path validation
error" in this case. Applications wanting additional details can use
the verify callback and check the new "parent" field. If this is not
NULL CRL path validation is taking place. Existing applications won't
see this because it requires extended CRL support which is off by
default.
This work was sponsored by Google.
[Steve Henson]
*) Support for freshest CRL extension.
This work was sponsored by Google.
[Steve Henson]
*) Initial indirect CRL support. Currently only supported in the CRLs
passed directly and not via lookup. Process certificate issuer
CRL entry extension and lookup CRL entries by bother issuer name
and serial number. Check and process CRL issuer entry in IDP extension.
This work was sponsored by Google.
[Steve Henson]
*) Add support for distinct certificate and CRL paths. The CRL issuer
certificate is validated separately in this case. Only enabled if
an extended CRL support flag is set: this flag will enable additional
CRL functionality in future.
This work was sponsored by Google.
[Steve Henson]
*) Add support for policy mappings extension.
This work was sponsored by Google.
[Steve Henson]
*) Fixes to pathlength constraint, self issued certificate handling,
policy processing to align with RFC3280 and PKITS tests.
This work was sponsored by Google.
[Steve Henson]
*) Support for name constraints certificate extension. DN, email, DNS
and URI types are currently supported.
This work was sponsored by Google.
[Steve Henson]
*) To cater for systems that provide a pointer-based thread ID rather
than numeric, deprecate the current numeric thread ID mechanism and
replace it with a structure and associated callback type. This
mechanism allows a numeric "hash" to be extracted from a thread ID in
either case, and on platforms where pointers are larger than 'long',
mixing is done to help ensure the numeric 'hash' is usable even if it
can't be guaranteed unique. The default mechanism is to use "&errno"
as a pointer-based thread ID to distinguish between threads.
Applications that want to provide their own thread IDs should now use
CRYPTO_THREADID_set_callback() to register a callback that will call
either CRYPTO_THREADID_set_numeric() or CRYPTO_THREADID_set_pointer().
Note that ERR_remove_state() is now deprecated, because it is tied
to the assumption that thread IDs are numeric. ERR_remove_state(0)
to free the current thread's error state should be replaced by
ERR_remove_thread_state(NULL).
(This new approach replaces the functions CRYPTO_set_idptr_callback(),
CRYPTO_get_idptr_callback(), and CRYPTO_thread_idptr() that existed in
OpenSSL 0.9.9-dev between June 2006 and August 2008. Also, if an
application was previously providing a numeric thread callback that
was inappropriate for distinguishing threads, then uniqueness might
have been obtained with &errno that happened immediately in the
intermediate development versions of OpenSSL; this is no longer the
case, the numeric thread callback will now override the automatic use
of &errno.)
[Geoff Thorpe, with help from Bodo Moeller]
*) Initial support for different CRL issuing certificates. This covers a
simple case where the self issued certificates in the chain exist and
the real CRL issuer is higher in the existing chain.
This work was sponsored by Google.
[Steve Henson]
*) Removed effectively defunct crypto/store from the build.
[Ben Laurie]
*) Revamp of STACK to provide stronger type-checking. Still to come:
TXT_DB, bsearch(?), OBJ_bsearch, qsort, CRYPTO_EX_DATA, ASN1_VALUE,
ASN1_STRING, CONF_VALUE.
[Ben Laurie]
*) Add a new SSL_MODE_RELEASE_BUFFERS mode flag to release unused buffer
RAM on SSL connections. This option can save about 34k per idle SSL.
[Nick Mathewson]
*) Revamp of LHASH to provide stronger type-checking. Still to come:
STACK, TXT_DB, bsearch, qsort.
[Ben Laurie]
*) Initial support for Cryptographic Message Syntax (aka CMS) based
on RFC3850, RFC3851 and RFC3852. New cms directory and cms utility,
support for data, signedData, compressedData, digestedData and
encryptedData, envelopedData types included. Scripts to check against
RFC4134 examples draft and interop and consistency checks of many
content types and variants.
[Steve Henson]
*) Add options to enc utility to support use of zlib compression BIO.
[Steve Henson]
*) Extend mk1mf to support importing of options and assembly language
files from Configure script, currently only included in VC-WIN32.
The assembly language rules can now optionally generate the source
files from the associated perl scripts.
[Steve Henson]
*) Implement remaining functionality needed to support GOST ciphersuites.
Interop testing has been performed using CryptoPro implementations.
[Victor B. Wagner <vitus@cryptocom.ru>]
*) s390x assembler pack.
[Andy Polyakov]
*) ARMv4 assembler pack. ARMv4 refers to v4 and later ISA, not CPU
"family."
[Andy Polyakov]
*) Implement Opaque PRF Input TLS extension as specified in
draft-rescorla-tls-opaque-prf-input-00.txt. Since this is not an
official specification yet and no extension type assignment by
IANA exists, this extension (for now) will have to be explicitly
enabled when building OpenSSL by providing the extension number
to use. For example, specify an option
-DTLSEXT_TYPE_opaque_prf_input=0x9527
to the "config" or "Configure" script to enable the extension,
assuming extension number 0x9527 (which is a completely arbitrary
and unofficial assignment based on the MD5 hash of the Internet
Draft). Note that by doing so, you potentially lose
interoperability with other TLS implementations since these might
be using the same extension number for other purposes.
SSL_set_tlsext_opaque_prf_input(ssl, src, len) is used to set the
opaque PRF input value to use in the handshake. This will create
an internal copy of the length-'len' string at 'src', and will
return non-zero for success.
To get more control and flexibility, provide a callback function
by using
SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb)
SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg)
where
int (*cb)(SSL *, void *peerinput, size_t len, void *arg);
void *arg;
Callback function 'cb' will be called in handshakes, and is
expected to use SSL_set_tlsext_opaque_prf_input() as appropriate.
Argument 'arg' is for application purposes (the value as given to
SSL_CTX_set_tlsext_opaque_prf_input_callback_arg() will directly
be provided to the callback function). The callback function
has to return non-zero to report success: usually 1 to use opaque
PRF input just if possible, or 2 to enforce use of the opaque PRF
input. In the latter case, the library will abort the handshake
if opaque PRF input is not successfully negotiated.
Arguments 'peerinput' and 'len' given to the callback function
will always be NULL and 0 in the case of a client. A server will
see the client's opaque PRF input through these variables if
available (NULL and 0 otherwise). Note that if the server
provides an opaque PRF input, the length must be the same as the
length of the client's opaque PRF input.
Note that the callback function will only be called when creating
a new session (session resumption can resume whatever was
previously negotiated), and will not be called in SSL 2.0
handshakes; thus, SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) or
SSL_set_options(ssl, SSL_OP_NO_SSLv2) is especially recommended
for applications that need to enforce opaque PRF input.
[Bodo Moeller]
*) Update ssl code to support digests other than SHA1+MD5 for handshake
MAC.
[Victor B. Wagner <vitus@cryptocom.ru>]
*) Add RFC4507 support to OpenSSL. This includes the corrections in
RFC4507bis. The encrypted ticket format is an encrypted encoded
SSL_SESSION structure, that way new session features are automatically
supported.
If a client application caches session in an SSL_SESSION structure
support is transparent because tickets are now stored in the encoded
SSL_SESSION.
The SSL_CTX structure automatically generates keys for ticket
protection in servers so again support should be possible
with no application modification.
If a client or server wishes to disable RFC4507 support then the option
SSL_OP_NO_TICKET can be set.
Add a TLS extension debugging callback to allow the contents of any client
or server extensions to be examined.
This work was sponsored by Google.
[Steve Henson]
*) Final changes to avoid use of pointer pointer casts in OpenSSL.
OpenSSL should now compile cleanly on gcc 4.2
[Peter Hartley <pdh@utter.chaos.org.uk>, Steve Henson]
*) Update SSL library to use new EVP_PKEY MAC API. Include generic MAC
support including streaming MAC support: this is required for GOST
ciphersuite support.
[Victor B. Wagner <vitus@cryptocom.ru>, Steve Henson]
*) Add option -stream to use PKCS#7 streaming in smime utility. New
function i2d_PKCS7_bio_stream() and PEM_write_PKCS7_bio_stream()
to output in BER and PEM format.
[Steve Henson]
*) Experimental support for use of HMAC via EVP_PKEY interface. This
allows HMAC to be handled via the EVP_DigestSign*() interface. The
EVP_PKEY "key" in this case is the HMAC key, potentially allowing
ENGINE support for HMAC keys which are unextractable. New -mac and
-macopt options to dgst utility.
[Steve Henson]
*) New option -sigopt to dgst utility. Update dgst to use
EVP_Digest{Sign,Verify}*. These two changes make it possible to use
alternative signing parameters such as X9.31 or PSS in the dgst
utility.
[Steve Henson]
*) Change ssl_cipher_apply_rule(), the internal function that does
the work each time a ciphersuite string requests enabling
("foo+bar"), moving ("+foo+bar"), disabling ("-foo+bar", or
removing ("!foo+bar") a class of ciphersuites: Now it maintains
the order of disabled ciphersuites such that those ciphersuites
that most recently went from enabled to disabled not only stay
in order with respect to each other, but also have higher priority
than other disabled ciphersuites the next time ciphersuites are
enabled again.
This means that you can now say, e.g., "PSK:-PSK:HIGH" to enable
the same ciphersuites as with "HIGH" alone, but in a specific
order where the PSK ciphersuites come first (since they are the
most recently disabled ciphersuites when "HIGH" is parsed).
Also, change ssl_create_cipher_list() (using this new
functionality) such that between otherwise identical
ciphersuites, ephemeral ECDH is preferred over ephemeral DH in
the default order.
[Bodo Moeller]
*) Change ssl_create_cipher_list() so that it automatically
arranges the ciphersuites in reasonable order before starting
to process the rule string. Thus, the definition for "DEFAULT"
(SSL_DEFAULT_CIPHER_LIST) now is just "ALL:!aNULL:!eNULL", but
remains equivalent to "AES:ALL:!aNULL:!eNULL:+aECDH:+kRSA:+RC4:@STRENGTH".
This makes it much easier to arrive at a reasonable default order
in applications for which anonymous ciphers are OK (meaning
that you can't actually use DEFAULT).
[Bodo Moeller; suggested by Victor Duchovni]
*) Split the SSL/TLS algorithm mask (as used for ciphersuite string
processing) into multiple integers instead of setting
"SSL_MKEY_MASK" bits, "SSL_AUTH_MASK" bits, "SSL_ENC_MASK",
"SSL_MAC_MASK", and "SSL_SSL_MASK" bits all in a single integer.
(These masks as well as the individual bit definitions are hidden
away into the non-exported interface ssl/ssl_locl.h, so this
change to the definition of the SSL_CIPHER structure shouldn't
affect applications.) This give us more bits for each of these
categories, so there is no longer a need to coagulate AES128 and
AES256 into a single algorithm bit, and to coagulate Camellia128
and Camellia256 into a single algorithm bit, which has led to all
kinds of kludges.
Thus, among other things, the kludge introduced in 0.9.7m and
0.9.8e for masking out AES256 independently of AES128 or masking
out Camellia256 independently of AES256 is not needed here in 0.9.9.
With the change, we also introduce new ciphersuite aliases that
so far were missing: "AES128", "AES256", "CAMELLIA128", and
"CAMELLIA256".
[Bodo Moeller]
*) Add support for dsa-with-SHA224 and dsa-with-SHA256.
Use the leftmost N bytes of the signature input if the input is
larger than the prime q (with N being the size in bytes of q).
[Nils Larsch]
*) Very *very* experimental PKCS#7 streaming encoder support. Nothing uses
it yet and it is largely untested.
[Steve Henson]
*) Add support for the ecdsa-with-SHA224/256/384/512 signature types.
[Nils Larsch]
*) Initial incomplete changes to avoid need for function casts in OpenSSL
some compilers (gcc 4.2 and later) reject their use. Safestack is
reimplemented. Update ASN1 to avoid use of legacy functions.
[Steve Henson]
*) Win32/64 targets are linked with Winsock2.
[Andy Polyakov]
*) Add an X509_CRL_METHOD structure to allow CRL processing to be redirected
to external functions. This can be used to increase CRL handling
efficiency especially when CRLs are very large by (for example) storing
the CRL revoked certificates in a database.
[Steve Henson]
*) Overhaul of by_dir code. Add support for dynamic loading of CRLs so
new CRLs added to a directory can be used. New command line option
-verify_return_error to s_client and s_server. This causes real errors
to be returned by the verify callback instead of carrying on no matter
what. This reflects the way a "real world" verify callback would behave.
[Steve Henson]
*) GOST engine, supporting several GOST algorithms and public key formats.
Kindly donated by Cryptocom.
[Cryptocom]
*) Partial support for Issuing Distribution Point CRL extension. CRLs
partitioned by DP are handled but no indirect CRL or reason partitioning
(yet). Complete overhaul of CRL handling: now the most suitable CRL is
selected via a scoring technique which handles IDP and AKID in CRLs.
[Steve Henson]
*) New X509_STORE_CTX callbacks lookup_crls() and lookup_certs() which
will ultimately be used for all verify operations: this will remove the
X509_STORE dependency on certificate verification and allow alternative
lookup methods. X509_STORE based implementations of these two callbacks.
[Steve Henson]
*) Allow multiple CRLs to exist in an X509_STORE with matching issuer names.
Modify get_crl() to find a valid (unexpired) CRL if possible.
[Steve Henson]
*) New function X509_CRL_match() to check if two CRLs are identical. Normally
this would be called X509_CRL_cmp() but that name is already used by
a function that just compares CRL issuer names. Cache several CRL
extensions in X509_CRL structure and cache CRLDP in X509.
[Steve Henson]
*) Store a "canonical" representation of X509_NAME structure (ASN1 Name)
this maps equivalent X509_NAME structures into a consistent structure.
Name comparison can then be performed rapidly using memcmp().
[Steve Henson]
*) Non-blocking OCSP request processing. Add -timeout option to ocsp
utility.
[Steve Henson]
*) Allow digests to supply their own micalg string for S/MIME type using
the ctrl EVP_MD_CTRL_MICALG.
[Steve Henson]
*) During PKCS7 signing pass the PKCS7 SignerInfo structure to the
EVP_PKEY_METHOD before and after signing via the EVP_PKEY_CTRL_PKCS7_SIGN
ctrl. It can then customise the structure before and/or after signing
if necessary.
[Steve Henson]
*) New function OBJ_add_sigid() to allow application defined signature OIDs
to be added to OpenSSLs internal tables. New function OBJ_sigid_free()
to free up any added signature OIDs.
[Steve Henson]
*) New functions EVP_CIPHER_do_all(), EVP_CIPHER_do_all_sorted(),
EVP_MD_do_all() and EVP_MD_do_all_sorted() to enumerate internal
digest and cipher tables. New options added to openssl utility:
list-message-digest-algorithms and list-cipher-algorithms.
[Steve Henson]
*) Change the array representation of binary polynomials: the list
of degrees of non-zero coefficients is now terminated with -1.
Previously it was terminated with 0, which was also part of the
value; thus, the array representation was not applicable to
polynomials where t^0 has coefficient zero. This change makes
the array representation useful in a more general context.
[Douglas Stebila]
*) Various modifications and fixes to SSL/TLS cipher string
handling. For ECC, the code now distinguishes between fixed ECDH
with RSA certificates on the one hand and with ECDSA certificates
on the other hand, since these are separate ciphersuites. The
unused code for Fortezza ciphersuites has been removed.
For consistency with EDH, ephemeral ECDH is now called "EECDH"
(not "ECDHE"). For consistency with the code for DH
certificates, use of ECDH certificates is now considered ECDH
authentication, not RSA or ECDSA authentication (the latter is
merely the CA's signing algorithm and not actively used in the
protocol).
The temporary ciphersuite alias "ECCdraft" is no longer
available, and ECC ciphersuites are no longer excluded from "ALL"
and "DEFAULT". The following aliases now exist for RFC 4492
ciphersuites, most of these by analogy with the DH case:
kECDHr - ECDH cert, signed with RSA
kECDHe - ECDH cert, signed with ECDSA
kECDH - ECDH cert (signed with either RSA or ECDSA)
kEECDH - ephemeral ECDH
ECDH - ECDH cert or ephemeral ECDH
aECDH - ECDH cert
aECDSA - ECDSA cert
ECDSA - ECDSA cert
AECDH - anonymous ECDH
EECDH - non-anonymous ephemeral ECDH (equivalent to "kEECDH:-AECDH")
[Bodo Moeller]
*) Add additional S/MIME capabilities for AES and GOST ciphers if supported.
Use correct micalg parameters depending on digest(s) in signed message.
[Steve Henson]
*) Add engine support for EVP_PKEY_ASN1_METHOD. Add functions to process
an ENGINE asn1 method. Support ENGINE lookups in the ASN1 code.
[Steve Henson]
*) Initial engine support for EVP_PKEY_METHOD. New functions to permit
an engine to register a method. Add ENGINE lookups for methods and
functional reference processing.
[Steve Henson]
*) New functions EVP_Digest{Sign,Verify)*. These are enhanced versions of
EVP_{Sign,Verify}* which allow an application to customise the signature
process.
[Steve Henson]
*) New -resign option to smime utility. This adds one or more signers
to an existing PKCS#7 signedData structure. Also -md option to use an
alternative message digest algorithm for signing.
[Steve Henson]
*) Tidy up PKCS#7 routines and add new functions to make it easier to
create PKCS7 structures containing multiple signers. Update smime
application to support multiple signers.
[Steve Henson]
*) New -macalg option to pkcs12 utility to allow setting of an alternative
digest MAC.
[Steve Henson]
*) Initial support for PKCS#5 v2.0 PRFs other than default SHA1 HMAC.
Reorganize PBE internals to lookup from a static table using NIDs,
add support for HMAC PBE OID translation. Add a EVP_CIPHER ctrl:
EVP_CTRL_PBE_PRF_NID this allows a cipher to specify an alternative
PRF which will be automatically used with PBES2.
[Steve Henson]
*) Replace the algorithm specific calls to generate keys in "req" with the
new API.
[Steve Henson]
*) Update PKCS#7 enveloped data routines to use new API. This is now
supported by any public key method supporting the encrypt operation. A
ctrl is added to allow the public key algorithm to examine or modify
the PKCS#7 RecipientInfo structure if it needs to: for RSA this is
a no op.
[Steve Henson]
*) Add a ctrl to asn1 method to allow a public key algorithm to express
a default digest type to use. In most cases this will be SHA1 but some
algorithms (such as GOST) need to specify an alternative digest. The
return value indicates how strong the preference is 1 means optional and
2 is mandatory (that is it is the only supported type). Modify
ASN1_item_sign() to accept a NULL digest argument to indicate it should
use the default md. Update openssl utilities to use the default digest
type for signing if it is not explicitly indicated.
[Steve Henson]
*) Use OID cross reference table in ASN1_sign() and ASN1_verify(). New
EVP_MD flag EVP_MD_FLAG_PKEY_METHOD_SIGNATURE. This uses the relevant
signing method from the key type. This effectively removes the link
between digests and public key types.
[Steve Henson]
*) Add an OID cross reference table and utility functions. Its purpose is to
translate between signature OIDs such as SHA1WithrsaEncryption and SHA1,
rsaEncryption. This will allow some of the algorithm specific hackery
needed to use the correct OID to be removed.
[Steve Henson]
*) Remove algorithm specific dependencies when setting PKCS7_SIGNER_INFO
structures for PKCS7_sign(). They are now set up by the relevant public
key ASN1 method.
[Steve Henson]
*) Add provisional EC pkey method with support for ECDSA and ECDH.
[Steve Henson]
*) Add support for key derivation (agreement) in the API, DH method and
pkeyutl.
[Steve Henson]
*) Add DSA pkey method and DH pkey methods, extend DH ASN1 method to support
public and private key formats. As a side effect these add additional
command line functionality not previously available: DSA signatures can be
generated and verified using pkeyutl and DH key support and generation in
pkey, genpkey.
[Steve Henson]
*) BeOS support.
[Oliver Tappe <zooey@hirschkaefer.de>]
*) New make target "install_html_docs" installs HTML renditions of the
manual pages.
[Oliver Tappe <zooey@hirschkaefer.de>]
*) New utility "genpkey" this is analogous to "genrsa" etc except it can
generate keys for any algorithm. Extend and update EVP_PKEY_METHOD to
support key and parameter generation and add initial key generation
functionality for RSA.
[Steve Henson]
*) Add functions for main EVP_PKEY_method operations. The undocumented
functions EVP_PKEY_{encrypt,decrypt} have been renamed to
EVP_PKEY_{encrypt,decrypt}_old.
[Steve Henson]
*) Initial definitions for EVP_PKEY_METHOD. This will be a high level public
key API, doesn't do much yet.
[Steve Henson]
*) New function EVP_PKEY_asn1_get0_info() to retrieve information about
public key algorithms. New option to openssl utility:
"list-public-key-algorithms" to print out info.
[Steve Henson]
*) Implement the Supported Elliptic Curves Extension for
ECC ciphersuites from draft-ietf-tls-ecc-12.txt.
[Douglas Stebila]
*) Don't free up OIDs in OBJ_cleanup() if they are in use by EVP_MD or
EVP_CIPHER structures to avoid later problems in EVP_cleanup().
[Steve Henson]
*) New utilities pkey and pkeyparam. These are similar to algorithm specific
utilities such as rsa, dsa, dsaparam etc except they process any key
type.
[Steve Henson]
*) Transfer public key printing routines to EVP_PKEY_ASN1_METHOD. New
functions EVP_PKEY_print_public(), EVP_PKEY_print_private(),
EVP_PKEY_print_param() to print public key data from an EVP_PKEY
structure.
[Steve Henson]
*) Initial support for pluggable public key ASN1.
De-spaghettify the public key ASN1 handling. Move public and private
key ASN1 handling to a new EVP_PKEY_ASN1_METHOD structure. Relocate
algorithm specific handling to a single module within the relevant
algorithm directory. Add functions to allow (near) opaque processing
of public and private key structures.
[Steve Henson]
*) Implement the Supported Point Formats Extension for
ECC ciphersuites from draft-ietf-tls-ecc-12.txt.
[Douglas Stebila]
*) Add initial support for RFC 4279 PSK TLS ciphersuites. Add members
for the psk identity [hint] and the psk callback functions to the
SSL_SESSION, SSL and SSL_CTX structure.
New ciphersuites:
PSK-RC4-SHA, PSK-3DES-EDE-CBC-SHA, PSK-AES128-CBC-SHA,
PSK-AES256-CBC-SHA
New functions:
SSL_CTX_use_psk_identity_hint
SSL_get_psk_identity_hint
SSL_get_psk_identity
SSL_use_psk_identity_hint
[Mika Kousa and Pasi Eronen of Nokia Corporation]
*) Add RFC 3161 compliant time stamp request creation, response generation
and response verification functionality.
[Zoltán Glózik <zglozik@opentsa.org>, The OpenTSA Project]
*) Add initial support for TLS extensions, specifically for the server_name
extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now
have new members for a host name. The SSL data structure has an
additional member SSL_CTX *initial_ctx so that new sessions can be
stored in that context to allow for session resumption, even after the
SSL has been switched to a new SSL_CTX in reaction to a client's
server_name extension.
New functions (subject to change):
SSL_get_servername()
SSL_get_servername_type()
SSL_set_SSL_CTX()
New CTRL codes and macros (subject to change):
SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
- SSL_CTX_set_tlsext_servername_callback()
SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
- SSL_CTX_set_tlsext_servername_arg()
SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name()
openssl s_client has a new '-servername ...' option.
openssl s_server has new options '-servername_host ...', '-cert2 ...',
'-key2 ...', '-servername_fatal' (subject to change). This allows
testing the HostName extension for a specific single host name ('-cert'
and '-key' remain fallbacks for handshakes without HostName
negotiation). If the unrecognized_name alert has to be sent, this by
default is a warning; it becomes fatal with the '-servername_fatal'
option.
[Peter Sylvester, Remy Allais, Christophe Renou]
*) Whirlpool hash implementation is added.
[Andy Polyakov]
*) BIGNUM code on 64-bit SPARCv9 targets is switched from bn(64,64) to
bn(64,32). Because of instruction set limitations it doesn't have
any negative impact on performance. This was done mostly in order
to make it possible to share assembler modules, such as bn_mul_mont
implementations, between 32- and 64-bit builds without hassle.
[Andy Polyakov]
*) Move code previously exiled into file crypto/ec/ec2_smpt.c
to ec2_smpl.c, and no longer require the OPENSSL_EC_BIN_PT_COMP
macro.
[Bodo Moeller]
*) New candidate for BIGNUM assembler implementation, bn_mul_mont,
dedicated Montgomery multiplication procedure, is introduced.
BN_MONT_CTX is modified to allow bn_mul_mont to reach for higher
"64-bit" performance on certain 32-bit targets.
[Andy Polyakov]
*) New option SSL_OP_NO_COMP to disable use of compression selectively
in SSL structures. New SSL ctrl to set maximum send fragment size.
Save memory by setting the I/O buffer sizes dynamically instead of
using the maximum available value.
[Steve Henson]
*) New option -V for 'openssl ciphers'. This prints the ciphersuite code
in addition to the text details.
[Bodo Moeller]
*) Very, very preliminary EXPERIMENTAL support for printing of general
ASN1 structures. This currently produces rather ugly output and doesn't
handle several customised structures at all.
[Steve Henson]
*) Integrated support for PVK file format and some related formats such
as MS PUBLICKEYBLOB and PRIVATEKEYBLOB. Command line switches to support
these in the 'rsa' and 'dsa' utilities.
[Steve Henson]
*) Support for PKCS#1 RSAPublicKey format on rsa utility command line.
[Steve Henson]
*) Remove the ancient ASN1_METHOD code. This was only ever used in one
place for the (very old) "NETSCAPE" format certificates which are now
handled using new ASN1 code equivalents.
[Steve Henson]
*) Let the TLSv1_method() etc. functions return a 'const' SSL_METHOD
pointer and make the SSL_METHOD parameter in SSL_CTX_new,
SSL_CTX_set_ssl_version and SSL_set_ssl_method 'const'.
[Nils Larsch]
*) Modify CRL distribution points extension code to print out previously
unsupported fields. Enhance extension setting code to allow setting of
all fields.
[Steve Henson]
*) Add print and set support for Issuing Distribution Point CRL extension.
[Steve Henson]
*) Change 'Configure' script to enable Camellia by default.
[NTT]
Changes between 0.9.8m and 0.9.8n [24 Mar 2010]
*) When rejecting SSL/TLS records due to an incorrect version number, never
update s->server with a new major version number. As of
- OpenSSL 0.9.8m if 'short' is a 16-bit type,
- OpenSSL 0.9.8f if 'short' is longer than 16 bits,
the previous behavior could result in a read attempt at NULL when
receiving specific incorrect SSL/TLS records once record payload
protection is active. (CVE-2010-0740)
[Bodo Moeller, Adam Langley <agl@chromium.org>]
*) Fix for CVE-2010-0433 where some kerberos enabled versions of OpenSSL
could be crashed if the relevant tables were not present (e.g. chrooted).
[Tomas Hoger <thoger@redhat.com>]
Changes between 0.9.8l and 0.9.8m [25 Feb 2010]
*) Always check bn_wexpand() return values for failure. (CVE-2009-3245)
[Martin Olsson, Neel Mehta]
*) Fix X509_STORE locking: Every 'objs' access requires a lock (to
accommodate for stack sorting, always a write lock!).
[Bodo Moeller]
*) On some versions of WIN32 Heap32Next is very slow. This can cause
excessive delays in the RAND_poll(): over a minute. As a workaround
include a time check in the inner Heap32Next loop too.
[Steve Henson]
*) The code that handled flushing of data in SSL/TLS originally used the
BIO_CTRL_INFO ctrl to see if any data was pending first. This caused
the problem outlined in PR#1949. The fix suggested there however can
trigger problems with buggy BIO_CTRL_WPENDING (e.g. some versions
of Apache). So instead simplify the code to flush unconditionally.
This should be fine since flushing with no data to flush is a no op.
[Steve Henson]
*) Handle TLS versions 2.0 and later properly and correctly use the
highest version of TLS/SSL supported. Although TLS >= 2.0 is some way
off ancient servers have a habit of sticking around for a while...
[Steve Henson]
*) Modify compression code so it frees up structures without using the
ex_data callbacks. This works around a problem where some applications
call CRYPTO_cleanup_all_ex_data() before application exit (e.g. when
restarting) then use compression (e.g. SSL with compression) later.
This results in significant per-connection memory leaks and
has caused some security issues including CVE-2008-1678 and
CVE-2009-4355.
[Steve Henson]
*) Constify crypto/cast (i.e., <openssl/cast.h>): a CAST_KEY doesn't
change when encrypting or decrypting.
[Bodo Moeller]
*) Add option SSL_OP_LEGACY_SERVER_CONNECT which will allow clients to
connect and renegotiate with servers which do not support RI.
Until RI is more widely deployed this option is enabled by default.
[Steve Henson]
*) Add "missing" ssl ctrls to clear options and mode.
[Steve Henson]
*) If client attempts to renegotiate and doesn't support RI respond with
a no_renegotiation alert as required by RFC5746. Some renegotiating
TLS clients will continue a connection gracefully when they receive
the alert. Unfortunately OpenSSL mishandled this alert and would hang
waiting for a server hello which it will never receive. Now we treat a
received no_renegotiation alert as a fatal error. This is because
applications requesting a renegotiation might well expect it to succeed
and would have no code in place to handle the server denying it so the
only safe thing to do is to terminate the connection.
[Steve Henson]
*) Add ctrl macro SSL_get_secure_renegotiation_support() which returns 1 if
peer supports secure renegotiation and 0 otherwise. Print out peer
renegotiation support in s_client/s_server.
[Steve Henson]
*) Replace the highly broken and deprecated SPKAC certification method with
the updated NID creation version. This should correctly handle UTF8.
[Steve Henson]
*) Implement RFC5746. Re-enable renegotiation but require the extension
as needed. Unfortunately, SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION
turns out to be a bad idea. It has been replaced by
SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION which can be set with
SSL_CTX_set_options(). This is really not recommended unless you
know what you are doing.
[Eric Rescorla <ekr@networkresonance.com>, Ben Laurie, Steve Henson]
*) Fixes to stateless session resumption handling. Use initial_ctx when
issuing and attempting to decrypt tickets in case it has changed during
servername handling. Use a non-zero length session ID when attempting
stateless session resumption: this makes it possible to determine if
a resumption has occurred immediately after receiving server hello
(several places in OpenSSL subtly assume this) instead of later in
the handshake.
[Steve Henson]
*) The functions ENGINE_ctrl(), OPENSSL_isservice(),
CMS_get1_RecipientRequest() and RAND_bytes() can return <=0 on error
fixes for a few places where the return code is not checked
correctly.
[Julia Lawall <julia@diku.dk>]
*) Add --strict-warnings option to Configure script to include devteam
warnings in other configurations.
[Steve Henson]
*) Add support for --libdir option and LIBDIR variable in makefiles. This
makes it possible to install openssl libraries in locations which
have names other than "lib", for example "/usr/lib64" which some
systems need.
[Steve Henson, based on patch from Jeremy Utley]
*) Don't allow the use of leading 0x80 in OIDs. This is a violation of
X690 8.9.12 and can produce some misleading textual output of OIDs.
[Steve Henson, reported by Dan Kaminsky]
*) Delete MD2 from algorithm tables. This follows the recommendation in
several standards that it is not used in new applications due to
several cryptographic weaknesses. For binary compatibility reasons
the MD2 API is still compiled in by default.
[Steve Henson]
*) Add compression id to {d2i,i2d}_SSL_SESSION so it is correctly saved
and restored.
[Steve Henson]
*) Rename uni2asc and asc2uni functions to OPENSSL_uni2asc and
OPENSSL_asc2uni conditionally on Netware platforms to avoid a name
clash.
[Guenter <lists@gknw.net>]
*) Fix the server certificate chain building code to use X509_verify_cert(),
it used to have an ad-hoc builder which was unable to cope with anything
other than a simple chain.
[David Woodhouse <dwmw2@infradead.org>, Steve Henson]
*) Don't check self signed certificate signatures in X509_verify_cert()
by default (a flag can override this): it just wastes time without
adding any security. As a useful side effect self signed root CAs
with non-FIPS digests are now usable in FIPS mode.
[Steve Henson]
*) In dtls1_process_out_of_seq_message() the check if the current message
is already buffered was missing. For every new message was memory
allocated, allowing an attacker to perform an denial of service attack
with sending out of seq handshake messages until there is no memory
left. Additionally every future message was buffered, even if the
sequence number made no sense and would be part of another handshake.
So only messages with sequence numbers less than 10 in advance will be
buffered. (CVE-2009-1378)
[Robin Seggelmann, discovered by Daniel Mentz]
*) Records are buffered if they arrive with a future epoch to be
processed after finishing the corresponding handshake. There is
currently no limitation to this buffer allowing an attacker to perform
a DOS attack with sending records with future epochs until there is no
memory left. This patch adds the pqueue_size() function to determine
the size of a buffer and limits the record buffer to 100 entries.
(CVE-2009-1377)
[Robin Seggelmann, discovered by Daniel Mentz]
*) Keep a copy of frag->msg_header.frag_len so it can be used after the
parent structure is freed. (CVE-2009-1379)
[Daniel Mentz]
*) Handle non-blocking I/O properly in SSL_shutdown() call.
[Darryl Miles <darryl-mailinglists@netbauds.net>]
*) Add 2.5.4.* OIDs
[Ilya O. <vrghost@gmail.com>]
Changes between 0.9.8k and 0.9.8l [5 Nov 2009]
*) Disable renegotiation completely - this fixes a severe security
problem (CVE-2009-3555) at the cost of breaking all
renegotiation. Renegotiation can be re-enabled by setting
SSL3_FLAGS_ALLOW_UNSAFE_LEGACY_RENEGOTIATION in s3->flags at
run-time. This is really not recommended unless you know what
you're doing.
[Ben Laurie]
Changes between 0.9.8j and 0.9.8k [25 Mar 2009]
*) Don't set val to NULL when freeing up structures, it is freed up by
underlying code. If sizeof(void *) > sizeof(long) this can result in
zeroing past the valid field. (CVE-2009-0789)
[Paolo Ganci <Paolo.Ganci@AdNovum.CH>]
*) Fix bug where return value of CMS_SignerInfo_verify_content() was not
checked correctly. This would allow some invalid signed attributes to
appear to verify correctly. (CVE-2009-0591)
[Ivan Nestlerode <inestlerode@us.ibm.com>]
*) Reject UniversalString and BMPString types with invalid lengths. This
prevents a crash in ASN1_STRING_print_ex() which assumes the strings have
a legal length. (CVE-2009-0590)
[Steve Henson]
*) Set S/MIME signing as the default purpose rather than setting it
unconditionally. This allows applications to override it at the store
level.
[Steve Henson]
*) Permit restricted recursion of ASN1 strings. This is needed in practice
to handle some structures.
[Steve Henson]
*) Improve efficiency of mem_gets: don't search whole buffer each time
for a '\n'
[Jeremy Shapiro <jnshapir@us.ibm.com>]
*) New -hex option for openssl rand.
[Matthieu Herrb]
*) Print out UTF8String and NumericString when parsing ASN1.
[Steve Henson]
*) Support NumericString type for name components.
[Steve Henson]
*) Allow CC in the environment to override the automatically chosen
compiler. Note that nothing is done to ensure flags work with the
chosen compiler.
[Ben Laurie]
Changes between 0.9.8i and 0.9.8j [07 Jan 2009]
*) Properly check EVP_VerifyFinal() and similar return values
(CVE-2008-5077).
[Ben Laurie, Bodo Moeller, Google Security Team]
*) Enable TLS extensions by default.
[Ben Laurie]
*) Allow the CHIL engine to be loaded, whether the application is
multithreaded or not. (This does not release the developer from the
obligation to set up the dynamic locking callbacks.)
[Sander Temme <sander@temme.net>]
*) Use correct exit code if there is an error in dgst command.
[Steve Henson; problem pointed out by Roland Dirlewanger]
*) Tweak Configure so that you need to say "experimental-jpake" to enable
JPAKE, and need to use -DOPENSSL_EXPERIMENTAL_JPAKE in applications.
[Bodo Moeller]
*) Add experimental JPAKE support, including demo authentication in
s_client and s_server.
[Ben Laurie]
*) Set the comparison function in v3_addr_canonize().
[Rob Austein <sra@hactrn.net>]
*) Add support for XMPP STARTTLS in s_client.
[Philip Paeps <philip@freebsd.org>]
*) Change the server-side SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG behavior
to ensure that even with this option, only ciphersuites in the
server's preference list will be accepted. (Note that the option
applies only when resuming a session, so the earlier behavior was
just about the algorithm choice for symmetric cryptography.)
[Bodo Moeller]
Changes between 0.9.8h and 0.9.8i [15 Sep 2008]
*) Fix NULL pointer dereference if a DTLS server received
ChangeCipherSpec as first record (CVE-2009-1386).
[PR #1679]
*) Fix a state transition in s3_srvr.c and d1_srvr.c
(was using SSL3_ST_CW_CLNT_HELLO_B, should be ..._ST_SW_SRVR_...).
[Nagendra Modadugu]
*) The fix in 0.9.8c that supposedly got rid of unsafe
double-checked locking was incomplete for RSA blinding,
addressing just one layer of what turns out to have been
doubly unsafe triple-checked locking.
So now fix this for real by retiring the MONT_HELPER macro
in crypto/rsa/rsa_eay.c.
[Bodo Moeller; problem pointed out by Marius Schilder]
*) Various precautionary measures:
- Avoid size_t integer overflow in HASH_UPDATE (md32_common.h).
- Avoid a buffer overflow in d2i_SSL_SESSION() (ssl_asn1.c).
(NB: This would require knowledge of the secret session ticket key
to exploit, in which case you'd be SOL either way.)
- Change bn_nist.c so that it will properly handle input BIGNUMs
outside the expected range.
- Enforce the 'num' check in BN_div() (bn_div.c) for non-BN_DEBUG
builds.
[Neel Mehta, Bodo Moeller]
*) Allow engines to be "soft loaded" - i.e. optionally don't die if
the load fails. Useful for distros.
[Ben Laurie and the FreeBSD team]
*) Add support for Local Machine Keyset attribute in PKCS#12 files.
[Steve Henson]
*) Fix BN_GF2m_mod_arr() top-bit cleanup code.
[Huang Ying]
*) Expand ENGINE to support engine supplied SSL client certificate functions.
This work was sponsored by Logica.
[Steve Henson]
*) Add CryptoAPI ENGINE to support use of RSA and DSA keys held in Windows
keystores. Support for SSL/TLS client authentication too.
Not compiled unless enable-capieng specified to Configure.
This work was sponsored by Logica.
[Steve Henson]
*) Fix bug in X509_ATTRIBUTE creation: don't set attribute using
ASN1_TYPE_set1 if MBSTRING flag set. This bug would crash certain
attribute creation routines such as certificate requests and PKCS#12
files.
[Steve Henson]
Changes between 0.9.8g and 0.9.8h [28 May 2008]
*) Fix flaw if 'Server Key exchange message' is omitted from a TLS
handshake which could lead to a client crash as found using the
Codenomicon TLS test suite (CVE-2008-1672)
[Steve Henson, Mark Cox]
*) Fix double free in TLS server name extensions which could lead to
a remote crash found by Codenomicon TLS test suite (CVE-2008-0891)
[Joe Orton]
*) Clear error queue in SSL_CTX_use_certificate_chain_file()
Clear the error queue to ensure that error entries left from
older function calls do not interfere with the correct operation.
[Lutz Jaenicke, Erik de Castro Lopo]
*) Remove root CA certificates of commercial CAs:
The OpenSSL project does not recommend any specific CA and does not
have any policy with respect to including or excluding any CA.
Therefore it does not make any sense to ship an arbitrary selection
of root CA certificates with the OpenSSL software.
[Lutz Jaenicke]
*) RSA OAEP patches to fix two separate invalid memory reads.
The first one involves inputs when 'lzero' is greater than
'SHA_DIGEST_LENGTH' (it would read about SHA_DIGEST_LENGTH bytes
before the beginning of from). The second one involves inputs where
the 'db' section contains nothing but zeroes (there is a one-byte
invalid read after the end of 'db').
[Ivan Nestlerode <inestlerode@us.ibm.com>]
*) Partial backport from 0.9.9-dev:
Introduce bn_mul_mont (dedicated Montgomery multiplication
procedure) as a candidate for BIGNUM assembler implementation.
While 0.9.9-dev uses assembler for various architectures, only
x86_64 is available by default here in the 0.9.8 branch, and
32-bit x86 is available through a compile-time setting.
To try the 32-bit x86 assembler implementation, use Configure
option "enable-montasm" (which exists only for this backport).
As "enable-montasm" for 32-bit x86 disclaims code stability
anyway, in this constellation we activate additional code
backported from 0.9.9-dev for further performance improvements,
namely BN_from_montgomery_word. (To enable this otherwise,
e.g. x86_64, try "-DMONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD".)
[Andy Polyakov (backport partially by Bodo Moeller)]
*) Add TLS session ticket callback. This allows an application to set
TLS ticket cipher and HMAC keys rather than relying on hardcoded fixed
values. This is useful for key rollover for example where several key
sets may exist with different names.
[Steve Henson]
*) Reverse ENGINE-internal logic for caching default ENGINE handles.
This was broken until now in 0.9.8 releases, such that the only way
a registered ENGINE could be used (assuming it initialises
successfully on the host) was to explicitly set it as the default
for the relevant algorithms. This is in contradiction with 0.9.7
behaviour and the documentation. With this fix, when an ENGINE is
registered into a given algorithm's table of implementations, the
'uptodate' flag is reset so that auto-discovery will be used next
time a new context for that algorithm attempts to select an
implementation.
[Ian Lister (tweaked by Geoff Thorpe)]
*) Backport of CMS code to OpenSSL 0.9.8. This differs from the 0.9.9
implementation in the following ways:
Lack of EVP_PKEY_ASN1_METHOD means algorithm parameters have to be
hard coded.
Lack of BER streaming support means one pass streaming processing is
only supported if data is detached: setting the streaming flag is
ignored for embedded content.
CMS support is disabled by default and must be explicitly enabled
with the enable-cms configuration option.
[Steve Henson]
*) Update the GMP engine glue to do direct copies between BIGNUM and
mpz_t when openssl and GMP use the same limb size. Otherwise the
existing "conversion via a text string export" trick is still used.
[Paul Sheer <paulsheer@gmail.com>]
*) Zlib compression BIO. This is a filter BIO which compressed and
uncompresses any data passed through it.
[Steve Henson]
*) Add AES_wrap_key() and AES_unwrap_key() functions to implement
RFC3394 compatible AES key wrapping.
[Steve Henson]
*) Add utility functions to handle ASN1 structures. ASN1_STRING_set0():
sets string data without copying. X509_ALGOR_set0() and
X509_ALGOR_get0(): set and retrieve X509_ALGOR (AlgorithmIdentifier)
data. Attribute function X509at_get0_data_by_OBJ(): retrieves data
from an X509_ATTRIBUTE structure optionally checking it occurs only
once. ASN1_TYPE_set1(): set and ASN1_TYPE structure copying supplied
data.
[Steve Henson]
*) Fix BN flag handling in RSA_eay_mod_exp() and BN_MONT_CTX_set()
to get the expected BN_FLG_CONSTTIME behavior.
[Bodo Moeller (Google)]
*) Netware support:
- fixed wrong usage of ioctlsocket() when build for LIBC BSD sockets
- fixed do_tests.pl to run the test suite with CLIB builds too (CLIB_OPT)
- added some more tests to do_tests.pl
- fixed RunningProcess usage so that it works with newer LIBC NDKs too
- removed usage of BN_LLONG for CLIB builds to avoid runtime dependency
- added new Configure targets netware-clib-bsdsock, netware-clib-gcc,
netware-clib-bsdsock-gcc, netware-libc-bsdsock-gcc
- various changes to netware.pl to enable gcc-cross builds on Win32
platform
- changed crypto/bio/b_sock.c to work with macro functions (CLIB BSD)
- various changes to fix missing prototype warnings
- fixed x86nasm.pl to create correct asm files for NASM COFF output
- added AES, WHIRLPOOL and CPUID assembler code to build files
- added missing AES assembler make rules to mk1mf.pl
- fixed order of includes in apps/ocsp.c so that e_os.h settings apply
[Guenter Knauf <eflash@gmx.net>]
*) Implement certificate status request TLS extension defined in RFC3546.
A client can set the appropriate parameters and receive the encoded
OCSP response via a callback. A server can query the supplied parameters
and set the encoded OCSP response in the callback. Add simplified examples
to s_client and s_server.
[Steve Henson]
Changes between 0.9.8f and 0.9.8g [19 Oct 2007]
*) Fix various bugs:
+ Binary incompatibility of ssl_ctx_st structure
+ DTLS interoperation with non-compliant servers
+ Don't call get_session_cb() without proposed session
+ Fix ia64 assembler code
[Andy Polyakov, Steve Henson]
Changes between 0.9.8e and 0.9.8f [11 Oct 2007]
*) DTLS Handshake overhaul. There were longstanding issues with
OpenSSL DTLS implementation, which were making it impossible for
RFC 4347 compliant client to communicate with OpenSSL server.
Unfortunately just fixing these incompatibilities would "cut off"
pre-0.9.8f clients. To allow for hassle free upgrade post-0.9.8e
server keeps tolerating non RFC compliant syntax. The opposite is
not true, 0.9.8f client can not communicate with earlier server.
This update even addresses CVE-2007-4995.
[Andy Polyakov]
*) Changes to avoid need for function casts in OpenSSL: some compilers
(gcc 4.2 and later) reject their use.
[Kurt Roeckx <kurt@roeckx.be>, Peter Hartley <pdh@utter.chaos.org.uk>,
Steve Henson]
*) Add RFC4507 support to OpenSSL. This includes the corrections in
RFC4507bis. The encrypted ticket format is an encrypted encoded
SSL_SESSION structure, that way new session features are automatically
supported.
If a client application caches session in an SSL_SESSION structure
support is transparent because tickets are now stored in the encoded
SSL_SESSION.
The SSL_CTX structure automatically generates keys for ticket
protection in servers so again support should be possible
with no application modification.
If a client or server wishes to disable RFC4507 support then the option
SSL_OP_NO_TICKET can be set.
Add a TLS extension debugging callback to allow the contents of any client
or server extensions to be examined.
This work was sponsored by Google.
[Steve Henson]
*) Add initial support for TLS extensions, specifically for the server_name
extension so far. The SSL_SESSION, SSL_CTX, and SSL data structures now
have new members for a host name. The SSL data structure has an
additional member SSL_CTX *initial_ctx so that new sessions can be
stored in that context to allow for session resumption, even after the
SSL has been switched to a new SSL_CTX in reaction to a client's
server_name extension.
New functions (subject to change):
SSL_get_servername()
SSL_get_servername_type()
SSL_set_SSL_CTX()
New CTRL codes and macros (subject to change):
SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
- SSL_CTX_set_tlsext_servername_callback()
SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG
- SSL_CTX_set_tlsext_servername_arg()
SSL_CTRL_SET_TLSEXT_HOSTNAME - SSL_set_tlsext_host_name()
openssl s_client has a new '-servername ...' option.
openssl s_server has new options '-servername_host ...', '-cert2 ...',
'-key2 ...', '-servername_fatal' (subject to change). This allows
testing the HostName extension for a specific single host name ('-cert'
and '-key' remain fallbacks for handshakes without HostName
negotiation). If the unrecognized_name alert has to be sent, this by
default is a warning; it becomes fatal with the '-servername_fatal'
option.
[Peter Sylvester, Remy Allais, Christophe Renou, Steve Henson]
*) Add AES and SSE2 assembly language support to VC++ build.
[Steve Henson]
*) Mitigate attack on final subtraction in Montgomery reduction.
[Andy Polyakov]
*) Fix crypto/ec/ec_mult.c to work properly with scalars of value 0
(which previously caused an internal error).
[Bodo Moeller]
*) Squeeze another 10% out of IGE mode when in != out.
[Ben Laurie]
*) AES IGE mode speedup.
[Dean Gaudet (Google)]
*) Add the Korean symmetric 128-bit cipher SEED (see
http://www.kisa.or.kr/kisa/seed/jsp/seed_eng.jsp) and
add SEED ciphersuites from RFC 4162:
TLS_RSA_WITH_SEED_CBC_SHA = "SEED-SHA"
TLS_DHE_DSS_WITH_SEED_CBC_SHA = "DHE-DSS-SEED-SHA"
TLS_DHE_RSA_WITH_SEED_CBC_SHA = "DHE-RSA-SEED-SHA"
TLS_DH_anon_WITH_SEED_CBC_SHA = "ADH-SEED-SHA"
To minimize changes between patchlevels in the OpenSSL 0.9.8
series, SEED remains excluded from compilation unless OpenSSL
is configured with 'enable-seed'.
[KISA, Bodo Moeller]
*) Mitigate branch prediction attacks, which can be practical if a
single processor is shared, allowing a spy process to extract
information. For detailed background information, see
http://eprint.iacr.org/2007/039 (O. Aciicmez, S. Gueron,
J.-P. Seifert, "New Branch Prediction Vulnerabilities in OpenSSL
and Necessary Software Countermeasures"). The core of the change
are new versions BN_div_no_branch() and
BN_mod_inverse_no_branch() of BN_div() and BN_mod_inverse(),
respectively, which are slower, but avoid the security-relevant
conditional branches. These are automatically called by BN_div()
and BN_mod_inverse() if the flag BN_FLG_CONSTTIME is set for one
of the input BIGNUMs. Also, BN_is_bit_set() has been changed to
remove a conditional branch.
BN_FLG_CONSTTIME is the new name for the previous
BN_FLG_EXP_CONSTTIME flag, since it now affects more than just
modular exponentiation. (Since OpenSSL 0.9.7h, setting this flag
in the exponent causes BN_mod_exp_mont() to use the alternative
implementation in BN_mod_exp_mont_consttime().) The old name
remains as a deprecated alias.
Similarly, RSA_FLAG_NO_EXP_CONSTTIME is replaced by a more general
RSA_FLAG_NO_CONSTTIME flag since the RSA implementation now uses
constant-time implementations for more than just exponentiation.
Here too the old name is kept as a deprecated alias.
BN_BLINDING_new() will now use BN_dup() for the modulus so that
the BN_BLINDING structure gets an independent copy of the
modulus. This means that the previous "BIGNUM *m" argument to
BN_BLINDING_new() and to BN_BLINDING_create_param() now
essentially becomes "const BIGNUM *m", although we can't actually
change this in the header file before 0.9.9. It allows
RSA_setup_blinding() to use BN_with_flags() on the modulus to
enable BN_FLG_CONSTTIME.
[Matthew D Wood (Intel Corp)]
*) In the SSL/TLS server implementation, be strict about session ID
context matching (which matters if an application uses a single
external cache for different purposes). Previously,
out-of-context reuse was forbidden only if SSL_VERIFY_PEER was
set. This did ensure strict client verification, but meant that,
with applications using a single external cache for quite
different requirements, clients could circumvent ciphersuite
restrictions for a given session ID context by starting a session
in a different context.
[Bodo Moeller]
*) Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that
a ciphersuite string such as "DEFAULT:RSA" cannot enable
authentication-only ciphersuites.
[Bodo Moeller]
*) Update the SSL_get_shared_ciphers() fix CVE-2006-3738 which was
not complete and could lead to a possible single byte overflow
(CVE-2007-5135) [Ben Laurie]
Changes between 0.9.8d and 0.9.8e [23 Feb 2007]
*) Since AES128 and AES256 (and similarly Camellia128 and
Camellia256) share a single mask bit in the logic of
ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a
kludge to work properly if AES128 is available and AES256 isn't
(or if Camellia128 is available and Camellia256 isn't).
[Victor Duchovni]
*) Fix the BIT STRING encoding generated by crypto/ec/ec_asn1.c
(within i2d_ECPrivateKey, i2d_ECPKParameters, i2d_ECParameters):
When a point or a seed is encoded in a BIT STRING, we need to
prevent the removal of trailing zero bits to get the proper DER
encoding. (By default, crypto/asn1/a_bitstr.c assumes the case
of a NamedBitList, for which trailing 0 bits need to be removed.)
[Bodo Moeller]
*) Have SSL/TLS server implementation tolerate "mismatched" record
protocol version while receiving ClientHello even if the
ClientHello is fragmented. (The server can't insist on the
particular protocol version it has chosen before the ServerHello
message has informed the client about his choice.)
[Bodo Moeller]
*) Add RFC 3779 support.
[Rob Austein for ARIN, Ben Laurie]
*) Load error codes if they are not already present instead of using a
static variable. This allows them to be cleanly unloaded and reloaded.
Improve header file function name parsing.
[Steve Henson]
*) extend SMTP and IMAP protocol emulation in s_client to use EHLO
or CAPABILITY handshake as required by RFCs.
[Goetz Babin-Ebell]
Changes between 0.9.8c and 0.9.8d [28 Sep 2006]
*) Introduce limits to prevent malicious keys being able to
cause a denial of service. (CVE-2006-2940)
[Steve Henson, Bodo Moeller]
*) Fix ASN.1 parsing of certain invalid structures that can result
in a denial of service. (CVE-2006-2937) [Steve Henson]
*) Fix buffer overflow in SSL_get_shared_ciphers() function.
(CVE-2006-3738) [Tavis Ormandy and Will Drewry, Google Security Team]
*) Fix SSL client code which could crash if connecting to a
malicious SSLv2 server. (CVE-2006-4343)
[Tavis Ormandy and Will Drewry, Google Security Team]
*) Since 0.9.8b, ciphersuite strings naming explicit ciphersuites
match only those. Before that, "AES256-SHA" would be interpreted
as a pattern and match "AES128-SHA" too (since AES128-SHA got
the same strength classification in 0.9.7h) as we currently only
have a single AES bit in the ciphersuite description bitmap.
That change, however, also applied to ciphersuite strings such as
"RC4-MD5" that intentionally matched multiple ciphersuites --
namely, SSL 2.0 ciphersuites in addition to the more common ones
from SSL 3.0/TLS 1.0.
So we change the selection algorithm again: Naming an explicit
ciphersuite selects this one ciphersuite, and any other similar
ciphersuite (same bitmap) from *other* protocol versions.
Thus, "RC4-MD5" again will properly select both the SSL 2.0
ciphersuite and the SSL 3.0/TLS 1.0 ciphersuite.
Since SSL 2.0 does not have any ciphersuites for which the
128/256 bit distinction would be relevant, this works for now.
The proper fix will be to use different bits for AES128 and
AES256, which would have avoided the problems from the beginning;
however, bits are scarce, so we can only do this in a new release
(not just a patchlevel) when we can change the SSL_CIPHER
definition to split the single 'unsigned long mask' bitmap into
multiple values to extend the available space.
[Bodo Moeller]
Changes between 0.9.8b and 0.9.8c [05 Sep 2006]
*) Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher
(CVE-2006-4339) [Ben Laurie and Google Security Team]
*) Add AES IGE and biIGE modes.
[Ben Laurie]
*) Change the Unix randomness entropy gathering to use poll() when
possible instead of select(), since the latter has some
undesirable limitations.
[Darryl Miles via Richard Levitte and Bodo Moeller]
*) Disable "ECCdraft" ciphersuites more thoroughly. Now special
treatment in ssl/ssl_ciph.s makes sure that these ciphersuites
cannot be implicitly activated as part of, e.g., the "AES" alias.
However, please upgrade to OpenSSL 0.9.9[-dev] for
non-experimental use of the ECC ciphersuites to get TLS extension
support, which is required for curve and point format negotiation
to avoid potential handshake problems.
[Bodo Moeller]
*) Disable rogue ciphersuites:
- SSLv2 0x08 0x00 0x80 ("RC4-64-MD5")
- SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5")
- SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5")
The latter two were purportedly from
draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really
appear there.
Also deactivate the remaining ciphersuites from
draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as
unofficial, and the ID has long expired.
[Bodo Moeller]
*) Fix RSA blinding Heisenbug (problems sometimes occurred on
dual-core machines) and other potential thread-safety issues.
[Bodo Moeller]
*) Add the symmetric cipher Camellia (128-bit, 192-bit, 256-bit key
versions), which is now available for royalty-free use
(see http://info.isl.ntt.co.jp/crypt/eng/info/chiteki.html).
Also, add Camellia TLS ciphersuites from RFC 4132.
To minimize changes between patchlevels in the OpenSSL 0.9.8
series, Camellia remains excluded from compilation unless OpenSSL
is configured with 'enable-camellia'.
[NTT]
*) Disable the padding bug check when compression is in use. The padding
bug check assumes the first packet is of even length, this is not
necessarily true if compression is enabled and can result in false
positives causing handshake failure. The actual bug test is ancient
code so it is hoped that implementations will either have fixed it by
now or any which still have the bug do not support compression.
[Steve Henson]
Changes between 0.9.8a and 0.9.8b [04 May 2006]
*) When applying a cipher rule check to see if string match is an explicit
cipher suite and only match that one cipher suite if it is.
[Steve Henson]
*) Link in manifests for VC++ if needed.
[Austin Ziegler <halostatue@gmail.com>]
*) Update support for ECC-based TLS ciphersuites according to
draft-ietf-tls-ecc-12.txt with proposed changes (but without
TLS extensions, which are supported starting with the 0.9.9
branch, not in the OpenSSL 0.9.8 branch).
[Douglas Stebila]
*) New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free() to support
opaque EVP_CIPHER_CTX handling.
[Steve Henson]
*) Fixes and enhancements to zlib compression code. We now only use
"zlib1.dll" and use the default __cdecl calling convention on Win32
to conform with the standards mentioned here:
http://www.zlib.net/DLL_FAQ.txt
Static zlib linking now works on Windows and the new --with-zlib-include
--with-zlib-lib options to Configure can be used to supply the location
of the headers and library. Gracefully handle case where zlib library
can't be loaded.
[Steve Henson]
*) Several fixes and enhancements to the OID generation code. The old code
sometimes allowed invalid OIDs (1.X for X >= 40 for example), couldn't
handle numbers larger than ULONG_MAX, truncated printing and had a
non standard OBJ_obj2txt() behaviour.
[Steve Henson]
*) Add support for building of engines under engine/ as shared libraries
under VC++ build system.
[Steve Henson]
*) Corrected the numerous bugs in the Win32 path splitter in DSO.
Hopefully, we will not see any false combination of paths any more.
[Richard Levitte]
Changes between 0.9.8 and 0.9.8a [11 Oct 2005]
*) Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING
(part of SSL_OP_ALL). This option used to disable the
countermeasure against man-in-the-middle protocol-version
rollback in the SSL 2.0 server implementation, which is a bad
idea. (CVE-2005-2969)
[Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center
for Information Security, National Institute of Advanced Industrial
Science and Technology [AIST], Japan)]
*) Add two function to clear and return the verify parameter flags.
[Steve Henson]
*) Keep cipherlists sorted in the source instead of sorting them at
runtime, thus removing the need for a lock.
[Nils Larsch]
*) Avoid some small subgroup attacks in Diffie-Hellman.
[Nick Mathewson and Ben Laurie]
*) Add functions for well-known primes.
[Nick Mathewson]
*) Extended Windows CE support.
[Satoshi Nakamura and Andy Polyakov]
*) Initialize SSL_METHOD structures at compile time instead of during
runtime, thus removing the need for a lock.
[Steve Henson]
*) Make PKCS7_decrypt() work even if no certificate is supplied by
attempting to decrypt each encrypted key in turn. Add support to
smime utility.
[Steve Henson]
Changes between 0.9.7h and 0.9.8 [05 Jul 2005]
[NB: OpenSSL 0.9.7i and later 0.9.7 patch levels were released after
OpenSSL 0.9.8.]
*) Add libcrypto.pc and libssl.pc for those who feel they need them.
[Richard Levitte]
*) Change CA.sh and CA.pl so they don't bundle the CSR and the private
key into the same file any more.
[Richard Levitte]
*) Add initial support for Win64, both IA64 and AMD64/x64 flavors.
[Andy Polyakov]
*) Add -utf8 command line and config file option to 'ca'.
[Stefan <stf@udoma.org]
*) Removed the macro des_crypt(), as it seems to conflict with some
libraries. Use DES_crypt().
[Richard Levitte]
*) Correct naming of the 'chil' and '4758cca' ENGINEs. This
involves renaming the source and generated shared-libs for
both. The engines will accept the corrected or legacy ids
('ncipher' and '4758_cca' respectively) when binding. NB,
this only applies when building 'shared'.
[Corinna Vinschen <vinschen@redhat.com> and Geoff Thorpe]
*) Add attribute functions to EVP_PKEY structure. Modify
PKCS12_create() to recognize a CSP name attribute and
use it. Make -CSP option work again in pkcs12 utility.
[Steve Henson]
*) Add new functionality to the bn blinding code:
- automatic re-creation of the BN_BLINDING parameters after
a fixed number of uses (currently 32)
- add new function for parameter creation
- introduce flags to control the update behaviour of the
BN_BLINDING parameters
- hide BN_BLINDING structure
Add a second BN_BLINDING slot to the RSA structure to improve
performance when a single RSA object is shared among several
threads.
[Nils Larsch]
*) Add support for DTLS.
[Nagendra Modadugu <nagendra@cs.stanford.edu> and Ben Laurie]
*) Add support for DER encoded private keys (SSL_FILETYPE_ASN1)
to SSL_CTX_use_PrivateKey_file() and SSL_use_PrivateKey_file()
[Walter Goulet]
*) Remove buggy and incomplete DH cert support from
ssl/ssl_rsa.c and ssl/s3_both.c
[Nils Larsch]
*) Use SHA-1 instead of MD5 as the default digest algorithm for
the apps/openssl applications.
[Nils Larsch]
*) Compile clean with "-Wall -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Werror". Currently
DEBUG_SAFESTACK must also be set.
[Ben Laurie]
*) Change ./Configure so that certain algorithms can be disabled by default.
The new counterpiece to "no-xxx" is "enable-xxx".
The patented RC5 and MDC2 algorithms will now be disabled unless
"enable-rc5" and "enable-mdc2", respectively, are specified.
(IDEA remains enabled despite being patented. This is because IDEA
is frequently required for interoperability, and there is no license
fee for non-commercial use. As before, "no-idea" can be used to
avoid this algorithm.)
[Bodo Moeller]
*) Add processing of proxy certificates (see RFC 3820). This work was
sponsored by KTH (The Royal Institute of Technology in Stockholm) and
EGEE (Enabling Grids for E-science in Europe).
[Richard Levitte]
*) RC4 performance overhaul on modern architectures/implementations, such
as Intel P4, IA-64 and AMD64.
[Andy Polyakov]
*) New utility extract-section.pl. This can be used specify an alternative
section number in a pod file instead of having to treat each file as
a separate case in Makefile. This can be done by adding two lines to the
pod file:
=for comment openssl_section:XXX
The blank line is mandatory.
[Steve Henson]
*) New arguments -certform, -keyform and -pass for s_client and s_server
to allow alternative format key and certificate files and passphrase
sources.
[Steve Henson]
*) New structure X509_VERIFY_PARAM which combines current verify parameters,
update associated structures and add various utility functions.
Add new policy related verify parameters, include policy checking in
standard verify code. Enhance 'smime' application with extra parameters
to support policy checking and print out.
[Steve Henson]
*) Add a new engine to support VIA PadLock ACE extensions in the VIA C3
Nehemiah processors. These extensions support AES encryption in hardware
as well as RNG (though RNG support is currently disabled).
[Michal Ludvig <michal@logix.cz>, with help from Andy Polyakov]
*) Deprecate BN_[get|set]_params() functions (they were ignored internally).
[Geoff Thorpe]
*) New FIPS 180-2 algorithms, SHA-224/-256/-384/-512 are implemented.
[Andy Polyakov and a number of other people]
*) Improved PowerPC platform support. Most notably BIGNUM assembler
implementation contributed by IBM.
[Suresh Chari, Peter Waltenberg, Andy Polyakov]
*) The new 'RSA_generate_key_ex' function now takes a BIGNUM for the public
exponent rather than 'unsigned long'. There is a corresponding change to
the new 'rsa_keygen' element of the RSA_METHOD structure.
[Jelte Jansen, Geoff Thorpe]
*) Functionality for creating the initial serial number file is now
moved from CA.pl to the 'ca' utility with a new option -create_serial.
(Before OpenSSL 0.9.7e, CA.pl used to initialize the serial
number file to 1, which is bound to cause problems. To avoid
the problems while respecting compatibility between different 0.9.7
patchlevels, 0.9.7e employed 'openssl x509 -next_serial' in
CA.pl for serial number initialization. With the new release 0.9.8,
we can fix the problem directly in the 'ca' utility.)
[Steve Henson]
*) Reduced header interdependencies by declaring more opaque objects in
ossl_typ.h. As a consequence, including some headers (eg. engine.h) will
give fewer recursive includes, which could break lazy source code - so
this change is covered by the OPENSSL_NO_DEPRECATED symbol. As always,
developers should define this symbol when building and using openssl to
ensure they track the recommended behaviour, interfaces, [etc], but
backwards-compatible behaviour prevails when this isn't defined.
[Geoff Thorpe]
*) New function X509_POLICY_NODE_print() which prints out policy nodes.
[Steve Henson]
*) Add new EVP function EVP_CIPHER_CTX_rand_key and associated functionality.
This will generate a random key of the appropriate length based on the
cipher context. The EVP_CIPHER can provide its own random key generation
routine to support keys of a specific form. This is used in the des and
3des routines to generate a key of the correct parity. Update S/MIME
code to use new functions and hence generate correct parity DES keys.
Add EVP_CHECK_DES_KEY #define to return an error if the key is not
valid (weak or incorrect parity).
[Steve Henson]
*) Add a local set of CRLs that can be used by X509_verify_cert() as well
as looking them up. This is useful when the verified structure may contain
CRLs, for example PKCS#7 signedData. Modify PKCS7_verify() to use any CRLs
present unless the new PKCS7_NO_CRL flag is asserted.
[Steve Henson]
*) Extend ASN1 oid configuration module. It now additionally accepts the
syntax:
shortName = some long name, 1.2.3.4
[Steve Henson]
*) Reimplemented the BN_CTX implementation. There is now no more static
limitation on the number of variables it can handle nor the depth of the
"stack" handling for BN_CTX_start()/BN_CTX_end() pairs. The stack
information can now expand as required, and rather than having a single
static array of bignums, BN_CTX now uses a linked-list of such arrays
allowing it to expand on demand whilst maintaining the usefulness of
BN_CTX's "bundling".
[Geoff Thorpe]
*) Add a missing BN_CTX parameter to the 'rsa_mod_exp' callback in RSA_METHOD
to allow all RSA operations to function using a single BN_CTX.
[Geoff Thorpe]
*) Preliminary support for certificate policy evaluation and checking. This
is initially intended to pass the tests outlined in "Conformance Testing
of Relying Party Client Certificate Path Processing Logic" v1.07.
[Steve Henson]
*) bn_dup_expand() has been deprecated, it was introduced in 0.9.7 and
remained unused and not that useful. A variety of other little bignum
tweaks and fixes have also been made continuing on from the audit (see
below).
[Geoff Thorpe]
*) Constify all or almost all d2i, c2i, s2i and r2i functions, along with
associated ASN1, EVP and SSL functions and old ASN1 macros.
[Richard Levitte]
*) BN_zero() only needs to set 'top' and 'neg' to zero for correct results,
and this should never fail. So the return value from the use of
BN_set_word() (which can fail due to needless expansion) is now deprecated;
if OPENSSL_NO_DEPRECATED is defined, BN_zero() is a void macro.
[Geoff Thorpe]
*) BN_CTX_get() should return zero-valued bignums, providing the same
initialised value as BN_new().
[Geoff Thorpe, suggested by Ulf Möller]
*) Support for inhibitAnyPolicy certificate extension.
[Steve Henson]
*) An audit of the BIGNUM code is underway, for which debugging code is
enabled when BN_DEBUG is defined. This makes stricter enforcements on what
is considered valid when processing BIGNUMs, and causes execution to
assert() when a problem is discovered. If BN_DEBUG_RAND is defined,
further steps are taken to deliberately pollute unused data in BIGNUM
structures to try and expose faulty code further on. For now, openssl will
(in its default mode of operation) continue to tolerate the inconsistent
forms that it has tolerated in the past, but authors and packagers should
consider trying openssl and their own applications when compiled with
these debugging symbols defined. It will help highlight potential bugs in
their own code, and will improve the test coverage for OpenSSL itself. At
some point, these tighter rules will become openssl's default to improve
maintainability, though the assert()s and other overheads will remain only
in debugging configurations. See bn.h for more details.
[Geoff Thorpe, Nils Larsch, Ulf Möller]
*) BN_CTX_init() has been deprecated, as BN_CTX is an opaque structure
that can only be obtained through BN_CTX_new() (which implicitly
initialises it). The presence of this function only made it possible
to overwrite an existing structure (and cause memory leaks).
[Geoff Thorpe]
*) Because of the callback-based approach for implementing LHASH as a
template type, lh_insert() adds opaque objects to hash-tables and
lh_doall() or lh_doall_arg() are typically used with a destructor callback
to clean up those corresponding objects before destroying the hash table
(and losing the object pointers). So some over-zealous constifications in
LHASH have been relaxed so that lh_insert() does not take (nor store) the
objects as "const" and the lh_doall[_arg] callback wrappers are not
prototyped to have "const" restrictions on the object pointers they are
given (and so aren't required to cast them away any more).
[Geoff Thorpe]
*) The tmdiff.h API was so ugly and minimal that our own timing utility
(speed) prefers to use its own implementation. The two implementations
haven't been consolidated as yet (volunteers?) but the tmdiff API has had
its object type properly exposed (MS_TM) instead of casting to/from "char
*". This may still change yet if someone realises MS_TM and "ms_time_***"
aren't necessarily the greatest nomenclatures - but this is what was used
internally to the implementation so I've used that for now.
[Geoff Thorpe]
*) Ensure that deprecated functions do not get compiled when
OPENSSL_NO_DEPRECATED is defined. Some "openssl" subcommands and a few of
the self-tests were still using deprecated key-generation functions so
these have been updated also.
[Geoff Thorpe]
*) Reorganise PKCS#7 code to separate the digest location functionality
into PKCS7_find_digest(), digest addition into PKCS7_bio_add_digest().
New function PKCS7_set_digest() to set the digest type for PKCS#7
digestedData type. Add additional code to correctly generate the
digestedData type and add support for this type in PKCS7 initialization
functions.
[Steve Henson]
*) New function PKCS7_set0_type_other() this initializes a PKCS7
structure of type "other".
[Steve Henson]
*) Fix prime generation loop in crypto/bn/bn_prime.pl by making
sure the loop does correctly stop and breaking ("division by zero")
modulus operations are not performed. The (pre-generated) prime
table crypto/bn/bn_prime.h was already correct, but it could not be
re-generated on some platforms because of the "division by zero"
situation in the script.
[Ralf S. Engelschall]
*) Update support for ECC-based TLS ciphersuites according to
draft-ietf-tls-ecc-03.txt: the KDF1 key derivation function with
SHA-1 now is only used for "small" curves (where the
representation of a field element takes up to 24 bytes); for
larger curves, the field element resulting from ECDH is directly
used as premaster secret.
[Douglas Stebila (Sun Microsystems Laboratories)]
*) Add code for kP+lQ timings to crypto/ec/ectest.c, and add SEC2
curve secp160r1 to the tests.
[Douglas Stebila (Sun Microsystems Laboratories)]
*) Add the possibility to load symbols globally with DSO.
[Götz Babin-Ebell <babin-ebell@trustcenter.de> via Richard Levitte]
*) Add the functions ERR_set_mark() and ERR_pop_to_mark() for better
control of the error stack.
[Richard Levitte]
*) Add support for STORE in ENGINE.
[Richard Levitte]
*) Add the STORE type. The intention is to provide a common interface
to certificate and key stores, be they simple file-based stores, or
HSM-type store, or LDAP stores, or...
NOTE: The code is currently UNTESTED and isn't really used anywhere.
[Richard Levitte]
*) Add a generic structure called OPENSSL_ITEM. This can be used to
pass a list of arguments to any function as well as provide a way
for a function to pass data back to the caller.
[Richard Levitte]
*) Add the functions BUF_strndup() and BUF_memdup(). BUF_strndup()
works like BUF_strdup() but can be used to duplicate a portion of
a string. The copy gets NUL-terminated. BUF_memdup() duplicates
a memory area.
[Richard Levitte]
*) Add the function sk_find_ex() which works like sk_find(), but will
return an index to an element even if an exact match couldn't be
found. The index is guaranteed to point at the element where the
searched-for key would be inserted to preserve sorting order.
[Richard Levitte]
*) Add the function OBJ_bsearch_ex() which works like OBJ_bsearch() but
takes an extra flags argument for optional functionality. Currently,
the following flags are defined:
OBJ_BSEARCH_VALUE_ON_NOMATCH
This one gets OBJ_bsearch_ex() to return a pointer to the first
element where the comparing function returns a negative or zero
number.
OBJ_BSEARCH_FIRST_VALUE_ON_MATCH
This one gets OBJ_bsearch_ex() to return a pointer to the first
element where the comparing function returns zero. This is useful
if there are more than one element where the comparing function
returns zero.
[Richard Levitte]
*) Make it possible to create self-signed certificates with 'openssl ca'
in such a way that the self-signed certificate becomes part of the
CA database and uses the same mechanisms for serial number generation
as all other certificate signing. The new flag '-selfsign' enables
this functionality. Adapt CA.sh and CA.pl.in.
[Richard Levitte]
*) Add functionality to check the public key of a certificate request
against a given private. This is useful to check that a certificate
request can be signed by that key (self-signing).
[Richard Levitte]
*) Make it possible to have multiple active certificates with the same
subject in the CA index file. This is done only if the keyword
'unique_subject' is set to 'no' in the main CA section (default
if 'CA_default') of the configuration file. The value is saved
with the database itself in a separate index attribute file,
named like the index file with '.attr' appended to the name.
[Richard Levitte]
*) Generate multi-valued AVAs using '+' notation in config files for
req and dirName.
[Steve Henson]
*) Support for nameConstraints certificate extension.
[Steve Henson]
*) Support for policyConstraints certificate extension.
[Steve Henson]
*) Support for policyMappings certificate extension.
[Steve Henson]
*) Make sure the default DSA_METHOD implementation only uses its
dsa_mod_exp() and/or bn_mod_exp() handlers if they are non-NULL,
and change its own handlers to be NULL so as to remove unnecessary
indirection. This lets alternative implementations fallback to the
default implementation more easily.
[Geoff Thorpe]
*) Support for directoryName in GeneralName related extensions
in config files.
[Steve Henson]
*) Make it possible to link applications using Makefile.shared.
Make that possible even when linking against static libraries!
[Richard Levitte]
*) Support for single pass processing for S/MIME signing. This now
means that S/MIME signing can be done from a pipe, in addition
cleartext signing (multipart/signed type) is effectively streaming
and the signed data does not need to be all held in memory.
This is done with a new flag PKCS7_STREAM. When this flag is set
PKCS7_sign() only initializes the PKCS7 structure and the actual signing
is done after the data is output (and digests calculated) in
SMIME_write_PKCS7().
[Steve Henson]
*) Add full support for -rpath/-R, both in shared libraries and
applications, at least on the platforms where it's known how
to do it.
[Richard Levitte]
*) In crypto/ec/ec_mult.c, implement fast point multiplication with
precomputation, based on wNAF splitting: EC_GROUP_precompute_mult()
will now compute a table of multiples of the generator that
makes subsequent invocations of EC_POINTs_mul() or EC_POINT_mul()
faster (notably in the case of a single point multiplication,
scalar * generator).
[Nils Larsch, Bodo Moeller]
*) IPv6 support for certificate extensions. The various extensions
which use the IP:a.b.c.d can now take IPv6 addresses using the
formats of RFC1884 2.2 . IPv6 addresses are now also displayed
correctly.
[Steve Henson]
*) Added an ENGINE that implements RSA by performing private key
exponentiations with the GMP library. The conversions to and from
GMP's mpz_t format aren't optimised nor are any montgomery forms
cached, and on x86 it appears OpenSSL's own performance has caught up.
However there are likely to be other architectures where GMP could
provide a boost. This ENGINE is not built in by default, but it can be
specified at Configure time and should be accompanied by the necessary
linker additions, eg;
./config -DOPENSSL_USE_GMP -lgmp
[Geoff Thorpe]
*) "openssl engine" will not display ENGINE/DSO load failure errors when
testing availability of engines with "-t" - the old behaviour is
produced by increasing the feature's verbosity with "-tt".
[Geoff Thorpe]
*) ECDSA routines: under certain error conditions uninitialized BN objects
could be freed. Solution: make sure initialization is performed early
enough. (Reported and fix supplied by Nils Larsch <nla@trustcenter.de>
via PR#459)
[Lutz Jaenicke]
*) Key-generation can now be implemented in RSA_METHOD, DSA_METHOD
and DH_METHOD (eg. by ENGINE implementations) to override the normal
software implementations. For DSA and DH, parameter generation can
also be overridden by providing the appropriate method callbacks.
[Geoff Thorpe]
*) Change the "progress" mechanism used in key-generation and
primality testing to functions that take a new BN_GENCB pointer in
place of callback/argument pairs. The new API functions have "_ex"
postfixes and the older functions are reimplemented as wrappers for
the new ones. The OPENSSL_NO_DEPRECATED symbol can be used to hide
declarations of the old functions to help (graceful) attempts to
migrate to the new functions. Also, the new key-generation API
functions operate on a caller-supplied key-structure and return
success/failure rather than returning a key or NULL - this is to
help make "keygen" another member function of RSA_METHOD etc.
Example for using the new callback interface:
int (*my_callback)(int a, int b, BN_GENCB *cb) = ...;
void *my_arg = ...;
BN_GENCB my_cb;
BN_GENCB_set(&my_cb, my_callback, my_arg);
return BN_is_prime_ex(some_bignum, BN_prime_checks, NULL, &cb);
/* For the meaning of a, b in calls to my_callback(), see the
* documentation of the function that calls the callback.
* cb will point to my_cb; my_arg can be retrieved as cb->arg.
* my_callback should return 1 if it wants BN_is_prime_ex()
* to continue, or 0 to stop.
*/
[Geoff Thorpe]
*) Change the ZLIB compression method to be stateful, and make it
available to TLS with the number defined in
draft-ietf-tls-compression-04.txt.
[Richard Levitte]
*) Add the ASN.1 structures and functions for CertificatePair, which
is defined as follows (according to X.509_4thEditionDraftV6.pdf):
CertificatePair ::= SEQUENCE {
forward [0] Certificate OPTIONAL,
reverse [1] Certificate OPTIONAL,
-- at least one of the pair shall be present -- }
Also implement the PEM functions to read and write certificate
pairs, and defined the PEM tag as "CERTIFICATE PAIR".
This needed to be defined, mostly for the sake of the LDAP
attribute crossCertificatePair, but may prove useful elsewhere as
well.
[Richard Levitte]
*) Make it possible to inhibit symlinking of shared libraries in
Makefile.shared, for Cygwin's sake.
[Richard Levitte]
*) Extend the BIGNUM API by creating a function
void BN_set_negative(BIGNUM *a, int neg);
and a macro that behave like
int BN_is_negative(const BIGNUM *a);
to avoid the need to access 'a->neg' directly in applications.
[Nils Larsch]
*) Implement fast modular reduction for pseudo-Mersenne primes
used in NIST curves (crypto/bn/bn_nist.c, crypto/ec/ecp_nist.c).
EC_GROUP_new_curve_GFp() will now automatically use this
if applicable.
[Nils Larsch <nla@trustcenter.de>]
*) Add new lock type (CRYPTO_LOCK_BN).
[Bodo Moeller]
*) Change the ENGINE framework to automatically load engines
dynamically from specific directories unless they could be
found to already be built in or loaded. Move all the
current engines except for the cryptodev one to a new
directory engines/.
The engines in engines/ are built as shared libraries if
the "shared" options was given to ./Configure or ./config.
Otherwise, they are inserted in libcrypto.a.
/usr/local/ssl/engines is the default directory for dynamic
engines, but that can be overridden at configure time through
the usual use of --prefix and/or --openssldir, and at run
time with the environment variable OPENSSL_ENGINES.
[Geoff Thorpe and Richard Levitte]
*) Add Makefile.shared, a helper makefile to build shared
libraries. Adapt Makefile.org.
[Richard Levitte]
*) Add version info to Win32 DLLs.
[Peter 'Luna' Runestig" <peter@runestig.com>]
*) Add new 'medium level' PKCS#12 API. Certificates and keys
can be added using this API to created arbitrary PKCS#12
files while avoiding the low level API.
New options to PKCS12_create(), key or cert can be NULL and
will then be omitted from the output file. The encryption
algorithm NIDs can be set to -1 for no encryption, the mac
iteration count can be set to 0 to omit the mac.
Enhance pkcs12 utility by making the -nokeys and -nocerts
options work when creating a PKCS#12 file. New option -nomac
to omit the mac, NONE can be set for an encryption algorithm.
New code is modified to use the enhanced PKCS12_create()
instead of the low level API.
[Steve Henson]
*) Extend ASN1 encoder to support indefinite length constructed
encoding. This can output sequences tags and octet strings in
this form. Modify pk7_asn1.c to support indefinite length
encoding. This is experimental and needs additional code to
be useful, such as an ASN1 bio and some enhanced streaming
PKCS#7 code.
Extend template encode functionality so that tagging is passed
down to the template encoder.
[Steve Henson]
*) Let 'openssl req' fail if an argument to '-newkey' is not
recognized instead of using RSA as a default.
[Bodo Moeller]
*) Add support for ECC-based ciphersuites from draft-ietf-tls-ecc-01.txt.
As these are not official, they are not included in "ALL";
the "ECCdraft" ciphersuite group alias can be used to select them.
[Vipul Gupta and Sumit Gupta (Sun Microsystems Laboratories)]
*) Add ECDH engine support.
[Nils Gura and Douglas Stebila (Sun Microsystems Laboratories)]
*) Add ECDH in new directory crypto/ecdh/.
[Douglas Stebila (Sun Microsystems Laboratories)]
*) Let BN_rand_range() abort with an error after 100 iterations
without success (which indicates a broken PRNG).
[Bodo Moeller]
*) Change BN_mod_sqrt() so that it verifies that the input value
is really the square of the return value. (Previously,
BN_mod_sqrt would show GIGO behaviour.)
[Bodo Moeller]
*) Add named elliptic curves over binary fields from X9.62, SECG,
and WAP/WTLS; add OIDs that were still missing.
[Sheueling Chang Shantz and Douglas Stebila
(Sun Microsystems Laboratories)]
*) Extend the EC library for elliptic curves over binary fields
(new files ec2_smpl.c, ec2_smpt.c, ec2_mult.c in crypto/ec/).
New EC_METHOD:
EC_GF2m_simple_method
New API functions:
EC_GROUP_new_curve_GF2m
EC_GROUP_set_curve_GF2m
EC_GROUP_get_curve_GF2m
EC_POINT_set_affine_coordinates_GF2m
EC_POINT_get_affine_coordinates_GF2m
EC_POINT_set_compressed_coordinates_GF2m
Point compression for binary fields is disabled by default for
patent reasons (compile with OPENSSL_EC_BIN_PT_COMP defined to
enable it).
As binary polynomials are represented as BIGNUMs, various members
of the EC_GROUP and EC_POINT data structures can be shared
between the implementations for prime fields and binary fields;
the above ..._GF2m functions (except for EX_GROUP_new_curve_GF2m)
are essentially identical to their ..._GFp counterparts.
(For simplicity, the '..._GFp' prefix has been dropped from
various internal method names.)
An internal 'field_div' method (similar to 'field_mul' and
'field_sqr') has been added; this is used only for binary fields.
[Sheueling Chang Shantz and Douglas Stebila
(Sun Microsystems Laboratories)]
*) Optionally dispatch EC_POINT_mul(), EC_POINT_precompute_mult()
through methods ('mul', 'precompute_mult').
The generic implementations (now internally called 'ec_wNAF_mul'
and 'ec_wNAF_precomputed_mult') remain the default if these
methods are undefined.
[Sheueling Chang Shantz and Douglas Stebila
(Sun Microsystems Laboratories)]
*) New function EC_GROUP_get_degree, which is defined through
EC_METHOD. For curves over prime fields, this returns the bit
length of the modulus.
[Sheueling Chang Shantz and Douglas Stebila
(Sun Microsystems Laboratories)]
*) New functions EC_GROUP_dup, EC_POINT_dup.
(These simply call ..._new and ..._copy).
[Sheueling Chang Shantz and Douglas Stebila
(Sun Microsystems Laboratories)]
*) Add binary polynomial arithmetic software in crypto/bn/bn_gf2m.c.
Polynomials are represented as BIGNUMs (where the sign bit is not
used) in the following functions [macros]:
BN_GF2m_add
BN_GF2m_sub [= BN_GF2m_add]
BN_GF2m_mod [wrapper for BN_GF2m_mod_arr]
BN_GF2m_mod_mul [wrapper for BN_GF2m_mod_mul_arr]
BN_GF2m_mod_sqr [wrapper for BN_GF2m_mod_sqr_arr]
BN_GF2m_mod_inv
BN_GF2m_mod_exp [wrapper for BN_GF2m_mod_exp_arr]
BN_GF2m_mod_sqrt [wrapper for BN_GF2m_mod_sqrt_arr]
BN_GF2m_mod_solve_quad [wrapper for BN_GF2m_mod_solve_quad_arr]
BN_GF2m_cmp [= BN_ucmp]
(Note that only the 'mod' functions are actually for fields GF(2^m).
BN_GF2m_add() is misnomer, but this is for the sake of consistency.)
For some functions, an the irreducible polynomial defining a
field can be given as an 'unsigned int[]' with strictly
decreasing elements giving the indices of those bits that are set;
i.e., p[] represents the polynomial
f(t) = t^p[0] + t^p[1] + ... + t^p[k]
where
p[0] > p[1] > ... > p[k] = 0.
This applies to the following functions:
BN_GF2m_mod_arr
BN_GF2m_mod_mul_arr
BN_GF2m_mod_sqr_arr
BN_GF2m_mod_inv_arr [wrapper for BN_GF2m_mod_inv]
BN_GF2m_mod_div_arr [wrapper for BN_GF2m_mod_div]
BN_GF2m_mod_exp_arr
BN_GF2m_mod_sqrt_arr
BN_GF2m_mod_solve_quad_arr
BN_GF2m_poly2arr
BN_GF2m_arr2poly
Conversion can be performed by the following functions:
BN_GF2m_poly2arr
BN_GF2m_arr2poly
bntest.c has additional tests for binary polynomial arithmetic.
Two implementations for BN_GF2m_mod_div() are available.
The default algorithm simply uses BN_GF2m_mod_inv() and
BN_GF2m_mod_mul(). The alternative algorithm is compiled in only
if OPENSSL_SUN_GF2M_DIV is defined (patent pending; read the
copyright notice in crypto/bn/bn_gf2m.c before enabling it).
[Sheueling Chang Shantz and Douglas Stebila
(Sun Microsystems Laboratories)]
*) Add new error code 'ERR_R_DISABLED' that can be used when some
functionality is disabled at compile-time.
[Douglas Stebila <douglas.stebila@sun.com>]
*) Change default behaviour of 'openssl asn1parse' so that more
information is visible when viewing, e.g., a certificate:
Modify asn1_parse2 (crypto/asn1/asn1_par.c) so that in non-'dump'
mode the content of non-printable OCTET STRINGs is output in a
style similar to INTEGERs, but with '[HEX DUMP]' prepended to
avoid the appearance of a printable string.
[Nils Larsch <nla@trustcenter.de>]
*) Add 'asn1_flag' and 'asn1_form' member to EC_GROUP with access
functions
EC_GROUP_set_asn1_flag()
EC_GROUP_get_asn1_flag()
EC_GROUP_set_point_conversion_form()
EC_GROUP_get_point_conversion_form()
These control ASN1 encoding details:
- Curves (i.e., groups) are encoded explicitly unless asn1_flag
has been set to OPENSSL_EC_NAMED_CURVE.
- Points are encoded in uncompressed form by default; options for
asn1_for are as for point2oct, namely
POINT_CONVERSION_COMPRESSED
POINT_CONVERSION_UNCOMPRESSED
POINT_CONVERSION_HYBRID
Also add 'seed' and 'seed_len' members to EC_GROUP with access
functions
EC_GROUP_set_seed()
EC_GROUP_get0_seed()
EC_GROUP_get_seed_len()
This is used only for ASN1 purposes (so far).
[Nils Larsch <nla@trustcenter.de>]
*) Add 'field_type' member to EC_METHOD, which holds the NID
of the appropriate field type OID. The new function
EC_METHOD_get_field_type() returns this value.
[Nils Larsch <nla@trustcenter.de>]
*) Add functions
EC_POINT_point2bn()
EC_POINT_bn2point()
EC_POINT_point2hex()
EC_POINT_hex2point()
providing useful interfaces to EC_POINT_point2oct() and
EC_POINT_oct2point().
[Nils Larsch <nla@trustcenter.de>]
*) Change internals of the EC library so that the functions
EC_GROUP_set_generator()
EC_GROUP_get_generator()
EC_GROUP_get_order()
EC_GROUP_get_cofactor()
are implemented directly in crypto/ec/ec_lib.c and not dispatched
to methods, which would lead to unnecessary code duplication when
adding different types of curves.
[Nils Larsch <nla@trustcenter.de> with input by Bodo Moeller]
*) Implement compute_wNAF (crypto/ec/ec_mult.c) without BIGNUM
arithmetic, and such that modified wNAFs are generated
(which avoid length expansion in many cases).
[Bodo Moeller]
*) Add a function EC_GROUP_check_discriminant() (defined via
EC_METHOD) that verifies that the curve discriminant is non-zero.
Add a function EC_GROUP_check() that makes some sanity tests
on a EC_GROUP, its generator and order. This includes
EC_GROUP_check_discriminant().
[Nils Larsch <nla@trustcenter.de>]
*) Add ECDSA in new directory crypto/ecdsa/.
Add applications 'openssl ecparam' and 'openssl ecdsa'
(these are based on 'openssl dsaparam' and 'openssl dsa').
ECDSA support is also included in various other files across the
library. Most notably,
- 'openssl req' now has a '-newkey ecdsa:file' option;
- EVP_PKCS82PKEY (crypto/evp/evp_pkey.c) now can handle ECDSA;
- X509_PUBKEY_get (crypto/asn1/x_pubkey.c) and
d2i_PublicKey (crypto/asn1/d2i_pu.c) have been modified to make
them suitable for ECDSA where domain parameters must be
extracted before the specific public key;
- ECDSA engine support has been added.
[Nils Larsch <nla@trustcenter.de>]
*) Include some named elliptic curves, and add OIDs from X9.62,
SECG, and WAP/WTLS. Each curve can be obtained from the new
function
EC_GROUP_new_by_curve_name(),
and the list of available named curves can be obtained with
EC_get_builtin_curves().
Also add a 'curve_name' member to EC_GROUP objects, which can be
accessed via
EC_GROUP_set_curve_name()
EC_GROUP_get_curve_name()
[Nils Larsch <larsch@trustcenter.de, Bodo Moeller]
*) Remove a few calls to bn_wexpand() in BN_sqr() (the one in there
was actually never needed) and in BN_mul(). The removal in BN_mul()
required a small change in bn_mul_part_recursive() and the addition
of the functions bn_cmp_part_words(), bn_sub_part_words() and
bn_add_part_words(), which do the same thing as bn_cmp_words(),
bn_sub_words() and bn_add_words() except they take arrays with
differing sizes.
[Richard Levitte]
Changes between 0.9.7l and 0.9.7m [23 Feb 2007]
*) Cleanse PEM buffers before freeing them since they may contain
sensitive data.
[Benjamin Bennett <ben@psc.edu>]
*) Include "!eNULL" in SSL_DEFAULT_CIPHER_LIST to make sure that
a ciphersuite string such as "DEFAULT:RSA" cannot enable
authentication-only ciphersuites.
[Bodo Moeller]
*) Since AES128 and AES256 share a single mask bit in the logic of
ssl/ssl_ciph.c, the code for masking out disabled ciphers needs a
kludge to work properly if AES128 is available and AES256 isn't.
[Victor Duchovni]
*) Expand security boundary to match 1.1.1 module.
[Steve Henson]
*) Remove redundant features: hash file source, editing of test vectors
modify fipsld to use external fips_premain.c signature.
[Steve Henson]
*) New perl script mkfipsscr.pl to create shell scripts or batch files to
run algorithm test programs.
[Steve Henson]
*) Make algorithm test programs more tolerant of whitespace.
[Steve Henson]
*) Have SSL/TLS server implementation tolerate "mismatched" record
protocol version while receiving ClientHello even if the
ClientHello is fragmented. (The server can't insist on the
particular protocol version it has chosen before the ServerHello
message has informed the client about his choice.)
[Bodo Moeller]
*) Load error codes if they are not already present instead of using a
static variable. This allows them to be cleanly unloaded and reloaded.
[Steve Henson]
Changes between 0.9.7k and 0.9.7l [28 Sep 2006]
*) Introduce limits to prevent malicious keys being able to
cause a denial of service. (CVE-2006-2940)
[Steve Henson, Bodo Moeller]
*) Fix ASN.1 parsing of certain invalid structures that can result
in a denial of service. (CVE-2006-2937) [Steve Henson]
*) Fix buffer overflow in SSL_get_shared_ciphers() function.
(CVE-2006-3738) [Tavis Ormandy and Will Drewry, Google Security Team]
*) Fix SSL client code which could crash if connecting to a
malicious SSLv2 server. (CVE-2006-4343)
[Tavis Ormandy and Will Drewry, Google Security Team]
*) Change ciphersuite string processing so that an explicit
ciphersuite selects this one ciphersuite (so that "AES256-SHA"
will no longer include "AES128-SHA"), and any other similar
ciphersuite (same bitmap) from *other* protocol versions (so that
"RC4-MD5" will still include both the SSL 2.0 ciphersuite and the
SSL 3.0/TLS 1.0 ciphersuite). This is a backport combining
changes from 0.9.8b and 0.9.8d.
[Bodo Moeller]
Changes between 0.9.7j and 0.9.7k [05 Sep 2006]
*) Avoid PKCS #1 v1.5 signature attack discovered by Daniel Bleichenbacher
(CVE-2006-4339) [Ben Laurie and Google Security Team]
*) Change the Unix randomness entropy gathering to use poll() when
possible instead of select(), since the latter has some
undesirable limitations.
[Darryl Miles via Richard Levitte and Bodo Moeller]
*) Disable rogue ciphersuites:
- SSLv2 0x08 0x00 0x80 ("RC4-64-MD5")
- SSLv3/TLSv1 0x00 0x61 ("EXP1024-RC2-CBC-MD5")
- SSLv3/TLSv1 0x00 0x60 ("EXP1024-RC4-MD5")
The latter two were purportedly from
draft-ietf-tls-56-bit-ciphersuites-0[01].txt, but do not really
appear there.
Also deactivate the remaining ciphersuites from
draft-ietf-tls-56-bit-ciphersuites-01.txt. These are just as
unofficial, and the ID has long expired.
[Bodo Moeller]
*) Fix RSA blinding Heisenbug (problems sometimes occurred on
dual-core machines) and other potential thread-safety issues.
[Bodo Moeller]
Changes between 0.9.7i and 0.9.7j [04 May 2006]
*) Adapt fipsld and the build system to link against the validated FIPS
module in FIPS mode.
[Steve Henson]
*) Fixes for VC++ 2005 build under Windows.
[Steve Henson]
*) Add new Windows build target VC-32-GMAKE for VC++. This uses GNU make
from a Windows bash shell such as MSYS. It is autodetected from the
"config" script when run from a VC++ environment. Modify standard VC++
build to use fipscanister.o from the GNU make build.
[Steve Henson]
Changes between 0.9.7h and 0.9.7i [14 Oct 2005]
*) Wrapped the definition of EVP_MAX_MD_SIZE in a #ifdef OPENSSL_FIPS.
The value now differs depending on if you build for FIPS or not.
BEWARE! A program linked with a shared FIPSed libcrypto can't be
safely run with a non-FIPSed libcrypto, as it may crash because of
the difference induced by this change.
[Andy Polyakov]
Changes between 0.9.7g and 0.9.7h [11 Oct 2005]
*) Remove the functionality of SSL_OP_MSIE_SSLV2_RSA_PADDING
(part of SSL_OP_ALL). This option used to disable the
countermeasure against man-in-the-middle protocol-version
rollback in the SSL 2.0 server implementation, which is a bad
idea. (CVE-2005-2969)
[Bodo Moeller; problem pointed out by Yutaka Oiwa (Research Center
for Information Security, National Institute of Advanced Industrial
Science and Technology [AIST], Japan)]
*) Minimal support for X9.31 signatures and PSS padding modes. This is
mainly for FIPS compliance and not fully integrated at this stage.
[Steve Henson]
*) For DSA signing, unless DSA_FLAG_NO_EXP_CONSTTIME is set, perform
the exponentiation using a fixed-length exponent. (Otherwise,
the information leaked through timing could expose the secret key
after many signatures; cf. Bleichenbacher's attack on DSA with
biased k.)
[Bodo Moeller]
*) Make a new fixed-window mod_exp implementation the default for
RSA, DSA, and DH private-key operations so that the sequence of
squares and multiplies and the memory access pattern are
independent of the particular secret key. This will mitigate
cache-timing and potential related attacks.
BN_mod_exp_mont_consttime() is the new exponentiation implementation,
and this is automatically used by BN_mod_exp_mont() if the new flag
BN_FLG_EXP_CONSTTIME is set for the exponent. RSA, DSA, and DH
will use this BN flag for private exponents unless the flag
RSA_FLAG_NO_EXP_CONSTTIME, DSA_FLAG_NO_EXP_CONSTTIME, or
DH_FLAG_NO_EXP_CONSTTIME, respectively, is set.
[Matthew D Wood (Intel Corp), with some changes by Bodo Moeller]
*) Change the client implementation for SSLv23_method() and
SSLv23_client_method() so that is uses the SSL 3.0/TLS 1.0
Client Hello message format if the SSL_OP_NO_SSLv2 option is set.
(Previously, the SSL 2.0 backwards compatible Client Hello
message format would be used even with SSL_OP_NO_SSLv2.)
[Bodo Moeller]
*) Add support for smime-type MIME parameter in S/MIME messages which some
clients need.
[Steve Henson]
*) New function BN_MONT_CTX_set_locked() to set montgomery parameters in
a threadsafe manner. Modify rsa code to use new function and add calls
to dsa and dh code (which had race conditions before).
[Steve Henson]
*) Include the fixed error library code in the C error file definitions
instead of fixing them up at runtime. This keeps the error code
structures constant.
[Steve Henson]
Changes between 0.9.7f and 0.9.7g [11 Apr 2005]
[NB: OpenSSL 0.9.7h and later 0.9.7 patch levels were released after
OpenSSL 0.9.8.]
*) Fixes for newer kerberos headers. NB: the casts are needed because
the 'length' field is signed on one version and unsigned on another
with no (?) obvious way to tell the difference, without these VC++
complains. Also the "definition" of FAR (blank) is no longer included
nor is the error ENOMEM. KRB5_PRIVATE has to be set to 1 to pick up
some needed definitions.
[Steve Henson]
*) Undo Cygwin change.
[Ulf Möller]
*) Added support for proxy certificates according to RFC 3820.
Because they may be a security thread to unaware applications,
they must be explicitly allowed in run-time. See
docs/HOWTO/proxy_certificates.txt for further information.
[Richard Levitte]
Changes between 0.9.7e and 0.9.7f [22 Mar 2005]
*) Use (SSL_RANDOM_VALUE - 4) bytes of pseudo random data when generating
server and client random values. Previously
(SSL_RANDOM_VALUE - sizeof(time_t)) would be used which would result in
less random data when sizeof(time_t) > 4 (some 64 bit platforms).
This change has negligible security impact because:
1. Server and client random values still have 24 bytes of pseudo random
data.
2. Server and client random values are sent in the clear in the initial
handshake.
3. The master secret is derived using the premaster secret (48 bytes in
size for static RSA ciphersuites) as well as client server and random
values.
The OpenSSL team would like to thank the UK NISCC for bringing this issue
to our attention.
[Stephen Henson, reported by UK NISCC]
*) Use Windows randomness collection on Cygwin.
[Ulf Möller]
*) Fix hang in EGD/PRNGD query when communication socket is closed
prematurely by EGD/PRNGD.
[Darren Tucker <dtucker@zip.com.au> via Lutz Jänicke, resolves #1014]
*) Prompt for pass phrases when appropriate for PKCS12 input format.
[Steve Henson]
*) Back-port of selected performance improvements from development
branch, as well as improved support for PowerPC platforms.
[Andy Polyakov]
*) Add lots of checks for memory allocation failure, error codes to indicate
failure and freeing up memory if a failure occurs.
[Nauticus Networks SSL Team <openssl@nauticusnet.com>, Steve Henson]
*) Add new -passin argument to dgst.
[Steve Henson]
*) Perform some character comparisons of different types in X509_NAME_cmp:
this is needed for some certificates that re-encode DNs into UTF8Strings
(in violation of RFC3280) and can't or won't issue name rollover
certificates.
[Steve Henson]
*) Make an explicit check during certificate validation to see that
the CA setting in each certificate on the chain is correct. As a
side effect always do the following basic checks on extensions,
not just when there's an associated purpose to the check:
- if there is an unhandled critical extension (unless the user
has chosen to ignore this fault)
- if the path length has been exceeded (if one is set at all)
- that certain extensions fit the associated purpose (if one has
been given)
[Richard Levitte]
Changes between 0.9.7d and 0.9.7e [25 Oct 2004]
*) Avoid a race condition when CRLs are checked in a multi threaded
environment. This would happen due to the reordering of the revoked
entries during signature checking and serial number lookup. Now the
encoding is cached and the serial number sort performed under a lock.
Add new STACK function sk_is_sorted().
[Steve Henson]
*) Add Delta CRL to the extension code.
[Steve Henson]
*) Various fixes to s3_pkt.c so alerts are sent properly.
[David Holmes <d.holmes@f5.com>]
*) Reduce the chances of duplicate issuer name and serial numbers (in
violation of RFC3280) using the OpenSSL certificate creation utilities.
This is done by creating a random 64 bit value for the initial serial
number when a serial number file is created or when a self signed
certificate is created using 'openssl req -x509'. The initial serial
number file is created using 'openssl x509 -next_serial' in CA.pl
rather than being initialized to 1.
[Steve Henson]
Changes between 0.9.7c and 0.9.7d [17 Mar 2004]
*) Fix null-pointer assignment in do_change_cipher_spec() revealed
by using the Codenomicon TLS Test Tool (CVE-2004-0079)
[Joe Orton, Steve Henson]
*) Fix flaw in SSL/TLS handshaking when using Kerberos ciphersuites
(CVE-2004-0112)
[Joe Orton, Steve Henson]
*) Make it possible to have multiple active certificates with the same
subject in the CA index file. This is done only if the keyword
'unique_subject' is set to 'no' in the main CA section (default
if 'CA_default') of the configuration file. The value is saved
with the database itself in a separate index attribute file,
named like the index file with '.attr' appended to the name.
[Richard Levitte]
*) X509 verify fixes. Disable broken certificate workarounds when
X509_V_FLAGS_X509_STRICT is set. Check CRL issuer has cRLSign set if
keyUsage extension present. Don't accept CRLs with unhandled critical
extensions: since verify currently doesn't process CRL extensions this
rejects a CRL with *any* critical extensions. Add new verify error codes
for these cases.
[Steve Henson]
*) When creating an OCSP nonce use an OCTET STRING inside the extnValue.
A clarification of RFC2560 will require the use of OCTET STRINGs and
some implementations cannot handle the current raw format. Since OpenSSL
copies and compares OCSP nonces as opaque blobs without any attempt at
parsing them this should not create any compatibility issues.
[Steve Henson]
*) New md flag EVP_MD_CTX_FLAG_REUSE this allows md_data to be reused when
calling EVP_MD_CTX_copy_ex() to avoid calling OPENSSL_malloc(). Without
this HMAC (and other) operations are several times slower than OpenSSL
< 0.9.7.
[Steve Henson]
*) Print out GeneralizedTime and UTCTime in ASN1_STRING_print_ex().
[Peter Sylvester <Peter.Sylvester@EdelWeb.fr>]
*) Use the correct content when signing type "other".
[Steve Henson]
Changes between 0.9.7b and 0.9.7c [30 Sep 2003]
*) Fix various bugs revealed by running the NISCC test suite:
Stop out of bounds reads in the ASN1 code when presented with
invalid tags (CVE-2003-0543 and CVE-2003-0544).
Free up ASN1_TYPE correctly if ANY type is invalid (CVE-2003-0545).
If verify callback ignores invalid public key errors don't try to check
certificate signature with the NULL public key.
[Steve Henson]
*) New -ignore_err option in ocsp application to stop the server
exiting on the first error in a request.
[Steve Henson]
*) In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate
if the server requested one: as stated in TLS 1.0 and SSL 3.0
specifications.
[Steve Henson]
*) In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional
extra data after the compression methods not only for TLS 1.0
but also for SSL 3.0 (as required by the specification).
[Bodo Moeller; problem pointed out by Matthias Loepfe]
*) Change X509_certificate_type() to mark the key as exported/exportable
when it's 512 *bits* long, not 512 bytes.
[Richard Levitte]
*) Change AES_cbc_encrypt() so it outputs exact multiple of
blocks during encryption.
[Richard Levitte]
*) Various fixes to base64 BIO and non blocking I/O. On write
flushes were not handled properly if the BIO retried. On read
data was not being buffered properly and had various logic bugs.
This also affects blocking I/O when the data being decoded is a
certain size.
[Steve Henson]
*) Various S/MIME bugfixes and compatibility changes:
output correct application/pkcs7 MIME type if
PKCS7_NOOLDMIMETYPE is set. Tolerate some broken signatures.
Output CR+LF for EOL if PKCS7_CRLFEOL is set (this makes opening
of files as .eml work). Correctly handle very long lines in MIME
parser.
[Steve Henson]
Changes between 0.9.7a and 0.9.7b [10 Apr 2003]
*) Countermeasure against the Klima-Pokorny-Rosa extension of
Bleichbacher's attack on PKCS #1 v1.5 padding: treat
a protocol version number mismatch like a decryption error
in ssl3_get_client_key_exchange (ssl/s3_srvr.c).
[Bodo Moeller]
*) Turn on RSA blinding by default in the default implementation
to avoid a timing attack. Applications that don't want it can call
RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING.
They would be ill-advised to do so in most cases.
[Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller]
*) Change RSA blinding code so that it works when the PRNG is not
seeded (in this case, the secret RSA exponent is abused as
an unpredictable seed -- if it is not unpredictable, there
is no point in blinding anyway). Make RSA blinding thread-safe
by remembering the creator's thread ID in rsa->blinding and
having all other threads use local one-time blinding factors
(this requires more computation than sharing rsa->blinding, but
avoids excessive locking; and if an RSA object is not shared
between threads, blinding will still be very fast).
[Bodo Moeller]
*) Fixed a typo bug that would cause ENGINE_set_default() to set an
ENGINE as defaults for all supported algorithms irrespective of
the 'flags' parameter. 'flags' is now honoured, so applications
should make sure they are passing it correctly.
[Geoff Thorpe]
*) Target "mingw" now allows native Windows code to be generated in
the Cygwin environment as well as with the MinGW compiler.
[Ulf Moeller]
Changes between 0.9.7 and 0.9.7a [19 Feb 2003]
*) In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked
via timing by performing a MAC computation even if incorrect
block cipher padding has been found. This is a countermeasure
against active attacks where the attacker has to distinguish
between bad padding and a MAC verification error. (CVE-2003-0078)
[Bodo Moeller; problem pointed out by Brice Canvel (EPFL),
Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and
Martin Vuagnoux (EPFL, Ilion)]
*) Make the no-err option work as intended. The intention with no-err
is not to have the whole error stack handling routines removed from
libcrypto, it's only intended to remove all the function name and
reason texts, thereby removing some of the footprint that may not
be interesting if those errors aren't displayed anyway.
NOTE: it's still possible for any application or module to have it's
own set of error texts inserted. The routines are there, just not
used by default when no-err is given.
[Richard Levitte]
*) Add support for FreeBSD on IA64.
[dirk.meyer@dinoex.sub.org via Richard Levitte, resolves #454]
*) Adjust DES_cbc_cksum() so it returns the same value as the MIT
Kerberos function mit_des_cbc_cksum(). Before this change,
the value returned by DES_cbc_cksum() was like the one from
mit_des_cbc_cksum(), except the bytes were swapped.
[Kevin Greaney <Kevin.Greaney@hp.com> and Richard Levitte]
*) Allow an application to disable the automatic SSL chain building.
Before this a rather primitive chain build was always performed in
ssl3_output_cert_chain(): an application had no way to send the
correct chain if the automatic operation produced an incorrect result.
Now the chain builder is disabled if either:
1. Extra certificates are added via SSL_CTX_add_extra_chain_cert().
2. The mode flag SSL_MODE_NO_AUTO_CHAIN is set.
The reasoning behind this is that an application would not want the
auto chain building to take place if extra chain certificates are
present and it might also want a means of sending no additional
certificates (for example the chain has two certificates and the
root is omitted).
[Steve Henson]
*) Add the possibility to build without the ENGINE framework.
[Steven Reddie <smr@essemer.com.au> via Richard Levitte]
*) Under Win32 gmtime() can return NULL: check return value in
OPENSSL_gmtime(). Add error code for case where gmtime() fails.
[Steve Henson]
*) DSA routines: under certain error conditions uninitialized BN objects
could be freed. Solution: make sure initialization is performed early
enough. (Reported and fix supplied by Ivan D Nestlerode <nestler@MIT.EDU>,
Nils Larsch <nla@trustcenter.de> via PR#459)
[Lutz Jaenicke]
*) Another fix for SSLv2 session ID handling: the session ID was incorrectly
checked on reconnect on the client side, therefore session resumption
could still fail with a "ssl session id is different" error. This
behaviour is masked when SSL_OP_ALL is used due to
SSL_OP_MICROSOFT_SESS_ID_BUG being set.
Behaviour observed by Crispin Flowerday <crispin@flowerday.cx> as
followup to PR #377.
[Lutz Jaenicke]
*) IA-32 assembler support enhancements: unified ELF targets, support
for SCO/Caldera platforms, fix for Cygwin shared build.
[Andy Polyakov]
*) Add support for FreeBSD on sparc64. As a consequence, support for
FreeBSD on non-x86 processors is separate from x86 processors on
the config script, much like the NetBSD support.
[Richard Levitte & Kris Kennaway <kris@obsecurity.org>]
Changes between 0.9.6h and 0.9.7 [31 Dec 2002]
[NB: OpenSSL 0.9.6i and later 0.9.6 patch levels were released after
OpenSSL 0.9.7.]
*) Fix session ID handling in SSLv2 client code: the SERVER FINISHED
code (06) was taken as the first octet of the session ID and the last
octet was ignored consequently. As a result SSLv2 client side session
caching could not have worked due to the session ID mismatch between
client and server.
Behaviour observed by Crispin Flowerday <crispin@flowerday.cx> as
PR #377.
[Lutz Jaenicke]
*) Change the declaration of needed Kerberos libraries to use EX_LIBS
instead of the special (and badly supported) LIBKRB5. LIBKRB5 is
removed entirely.
[Richard Levitte]
*) The hw_ncipher.c engine requires dynamic locks. Unfortunately, it
seems that in spite of existing for more than a year, many application
author have done nothing to provide the necessary callbacks, which
means that this particular engine will not work properly anywhere.
This is a very unfortunate situation which forces us, in the name
of usability, to give the hw_ncipher.c a static lock, which is part
of libcrypto.
NOTE: This is for the 0.9.7 series ONLY. This hack will never
appear in 0.9.8 or later. We EXPECT application authors to have
dealt properly with this when 0.9.8 is released (unless we actually
make such changes in the libcrypto locking code that changes will
have to be made anyway).
[Richard Levitte]
*) In asn1_d2i_read_bio() repeatedly call BIO_read() until all content
octets have been read, EOF or an error occurs. Without this change
some truncated ASN1 structures will not produce an error.
[Steve Henson]
*) Disable Heimdal support, since it hasn't been fully implemented.
Still give the possibility to force the use of Heimdal, but with
warnings and a request that patches get sent to openssl-dev.
[Richard Levitte]
*) Add the VC-CE target, introduce the WINCE sysname, and add
INSTALL.WCE and appropriate conditionals to make it build.
[Steven Reddie <smr@essemer.com.au> via Richard Levitte]
*) Change the DLL names for Cygwin to cygcrypto-x.y.z.dll and
cygssl-x.y.z.dll, where x, y and z are the major, minor and
edit numbers of the version.
[Corinna Vinschen <vinschen@redhat.com> and Richard Levitte]
*) Introduce safe string copy and catenation functions
(BUF_strlcpy() and BUF_strlcat()).
[Ben Laurie (CHATS) and Richard Levitte]
*) Avoid using fixed-size buffers for one-line DNs.
[Ben Laurie (CHATS)]
*) Add BUF_MEM_grow_clean() to avoid information leakage when
resizing buffers containing secrets, and use where appropriate.
[Ben Laurie (CHATS)]
*) Avoid using fixed size buffers for configuration file location.
[Ben Laurie (CHATS)]
*) Avoid filename truncation for various CA files.
[Ben Laurie (CHATS)]
*) Use sizeof in preference to magic numbers.
[Ben Laurie (CHATS)]
*) Avoid filename truncation in cert requests.
[Ben Laurie (CHATS)]
*) Add assertions to check for (supposedly impossible) buffer
overflows.
[Ben Laurie (CHATS)]
*) Don't cache truncated DNS entries in the local cache (this could
potentially lead to a spoofing attack).
[Ben Laurie (CHATS)]
*) Fix various buffers to be large enough for hex/decimal
representations in a platform independent manner.
[Ben Laurie (CHATS)]
*) Add CRYPTO_realloc_clean() to avoid information leakage when
resizing buffers containing secrets, and use where appropriate.
[Ben Laurie (CHATS)]
*) Add BIO_indent() to avoid much slightly worrying code to do
indents.
[Ben Laurie (CHATS)]
*) Convert sprintf()/BIO_puts() to BIO_printf().
[Ben Laurie (CHATS)]
*) buffer_gets() could terminate with the buffer only half
full. Fixed.
[Ben Laurie (CHATS)]
*) Add assertions to prevent user-supplied crypto functions from
overflowing internal buffers by having large block sizes, etc.
[Ben Laurie (CHATS)]
*) New OPENSSL_assert() macro (similar to assert(), but enabled
unconditionally).
[Ben Laurie (CHATS)]
*) Eliminate unused copy of key in RC4.
[Ben Laurie (CHATS)]
*) Eliminate unused and incorrectly sized buffers for IV in pem.h.
[Ben Laurie (CHATS)]
*) Fix off-by-one error in EGD path.
[Ben Laurie (CHATS)]
*) If RANDFILE path is too long, ignore instead of truncating.
[Ben Laurie (CHATS)]
*) Eliminate unused and incorrectly sized X.509 structure
CBCParameter.
[Ben Laurie (CHATS)]
*) Eliminate unused and dangerous function knumber().
[Ben Laurie (CHATS)]
*) Eliminate unused and dangerous structure, KSSL_ERR.
[Ben Laurie (CHATS)]
*) Protect against overlong session ID context length in an encoded
session object. Since these are local, this does not appear to be
exploitable.
[Ben Laurie (CHATS)]
*) Change from security patch (see 0.9.6e below) that did not affect
the 0.9.6 release series:
Remote buffer overflow in SSL3 protocol - an attacker could
supply an oversized master key in Kerberos-enabled versions.
(CVE-2002-0657)
[Ben Laurie (CHATS)]
*) Change the SSL kerb5 codes to match RFC 2712.
[Richard Levitte]
*) Make -nameopt work fully for req and add -reqopt switch.
[Michael Bell <michael.bell@rz.hu-berlin.de>, Steve Henson]
*) The "block size" for block ciphers in CFB and OFB mode should be 1.
[Steve Henson, reported by Yngve Nysaeter Pettersen <yngve@opera.com>]
*) Make sure tests can be performed even if the corresponding algorithms
have been removed entirely. This was also the last step to make
OpenSSL compilable with DJGPP under all reasonable conditions.
[Richard Levitte, Doug Kaufman <dkaufman@rahul.net>]
*) Add cipher selection rules COMPLEMENTOFALL and COMPLEMENTOFDEFAULT
to allow version independent disabling of normally unselected ciphers,
which may be activated as a side-effect of selecting a single cipher.
(E.g., cipher list string "RSA" enables ciphersuites that are left
out of "ALL" because they do not provide symmetric encryption.
"RSA:!COMPLEMEMENTOFALL" avoids these unsafe ciphersuites.)
[Lutz Jaenicke, Bodo Moeller]
*) Add appropriate support for separate platform-dependent build
directories. The recommended way to make a platform-dependent
build directory is the following (tested on Linux), maybe with
some local tweaks:
# Place yourself outside of the OpenSSL source tree. In
# this example, the environment variable OPENSSL_SOURCE
# is assumed to contain the absolute OpenSSL source directory.
mkdir -p objtree/"`uname -s`-`uname -r`-`uname -m`"
cd objtree/"`uname -s`-`uname -r`-`uname -m`"
(cd $OPENSSL_SOURCE; find . -type f) | while read F; do
mkdir -p `dirname $F`
ln -s $OPENSSL_SOURCE/$F $F
done
To be absolutely sure not to disturb the source tree, a "make clean"
is a good thing. If it isn't successful, don't worry about it,
it probably means the source directory is very clean.
[Richard Levitte]
*) Make sure any ENGINE control commands make local copies of string
pointers passed to them whenever necessary. Otherwise it is possible
the caller may have overwritten (or deallocated) the original string
data when a later ENGINE operation tries to use the stored values.
[Götz Babin-Ebell <babinebell@trustcenter.de>]
*) Improve diagnostics in file reading and command-line digests.
[Ben Laurie aided and abetted by Solar Designer <solar@openwall.com>]
*) Add AES modes CFB and OFB to the object database. Correct an
error in AES-CFB decryption.
[Richard Levitte]
*) Remove most calls to EVP_CIPHER_CTX_cleanup() in evp_enc.c, this
allows existing EVP_CIPHER_CTX structures to be reused after
calling EVP_*Final(). This behaviour is used by encryption
BIOs and some applications. This has the side effect that
applications must explicitly clean up cipher contexts with
EVP_CIPHER_CTX_cleanup() or they will leak memory.
[Steve Henson]
*) Check the values of dna and dnb in bn_mul_recursive before calling
bn_mul_comba (a non zero value means the a or b arrays do not contain
n2 elements) and fallback to bn_mul_normal if either is not zero.
[Steve Henson]
*) Fix escaping of non-ASCII characters when using the -subj option
of the "openssl req" command line tool. (Robert Joop <joop@fokus.gmd.de>)
[Lutz Jaenicke]
*) Make object definitions compliant to LDAP (RFC2256): SN is the short
form for "surname", serialNumber has no short form.
Use "mail" as the short name for "rfc822Mailbox" according to RFC2798;
therefore remove "mail" short name for "internet 7".
The OID for unique identifiers in X509 certificates is
x500UniqueIdentifier, not uniqueIdentifier.
Some more OID additions. (Michael Bell <michael.bell@rz.hu-berlin.de>)
[Lutz Jaenicke]
*) Add an "init" command to the ENGINE config module and auto initialize
ENGINEs. Without any "init" command the ENGINE will be initialized
after all ctrl commands have been executed on it. If init=1 the
ENGINE is initialized at that point (ctrls before that point are run
on the uninitialized ENGINE and after on the initialized one). If
init=0 then the ENGINE will not be initialized at all.
[Steve Henson]
*) Fix the 'app_verify_callback' interface so that the user-defined
argument is actually passed to the callback: In the
SSL_CTX_set_cert_verify_callback() prototype, the callback
declaration has been changed from
int (*cb)()
into
int (*cb)(X509_STORE_CTX *,void *);
in ssl_verify_cert_chain (ssl/ssl_cert.c), the call
i=s->ctx->app_verify_callback(&ctx)
has been changed into
i=s->ctx->app_verify_callback(&ctx, s->ctx->app_verify_arg).
To update applications using SSL_CTX_set_cert_verify_callback(),
a dummy argument can be added to their callback functions.
[D. K. Smetters <smetters@parc.xerox.com>]
*) Added the '4758cca' ENGINE to support IBM 4758 cards.
[Maurice Gittens <maurice@gittens.nl>, touchups by Geoff Thorpe]
*) Add and OPENSSL_LOAD_CONF define which will cause
OpenSSL_add_all_algorithms() to load the openssl.cnf config file.
This allows older applications to transparently support certain
OpenSSL features: such as crypto acceleration and dynamic ENGINE loading.
Two new functions OPENSSL_add_all_algorithms_noconf() which will never
load the config file and OPENSSL_add_all_algorithms_conf() which will
always load it have also been added.
[Steve Henson]
*) Add the OFB, CFB and CTR (all with 128 bit feedback) to AES.
Adjust NIDs and EVP layer.
[Stephen Sprunk <stephen@sprunk.org> and Richard Levitte]
*) Config modules support in openssl utility.
Most commands now load modules from the config file,
though in a few (such as version) this isn't done
because it couldn't be used for anything.
In the case of ca and req the config file used is
the same as the utility itself: that is the -config
command line option can be used to specify an
alternative file.
[Steve Henson]
*) Move default behaviour from OPENSSL_config(). If appname is NULL
use "openssl_conf" if filename is NULL use default openssl config file.
[Steve Henson]
*) Add an argument to OPENSSL_config() to allow the use of an alternative
config section name. Add a new flag to tolerate a missing config file
and move code to CONF_modules_load_file().
[Steve Henson]
*) Support for crypto accelerator cards from Accelerated Encryption
Processing, www.aep.ie. (Use engine 'aep')
The support was copied from 0.9.6c [engine] and adapted/corrected
to work with the new engine framework.
[AEP Inc. and Richard Levitte]
*) Support for SureWare crypto accelerator cards from Baltimore
Technologies. (Use engine 'sureware')
The support was copied from 0.9.6c [engine] and adapted
to work with the new engine framework.
[Richard Levitte]
*) Have the CHIL engine fork-safe (as defined by nCipher) and actually
make the newer ENGINE framework commands for the CHIL engine work.
[Toomas Kiisk <vix@cyber.ee> and Richard Levitte]
*) Make it possible to produce shared libraries on ReliantUNIX.
[Robert Dahlem <Robert.Dahlem@ffm2.siemens.de> via Richard Levitte]
*) Add the configuration target debug-linux-ppro.
Make 'openssl rsa' use the general key loading routines
implemented in apps.c, and make those routines able to
handle the key format FORMAT_NETSCAPE and the variant
FORMAT_IISSGC.
[Toomas Kiisk <vix@cyber.ee> via Richard Levitte]
*) Fix a crashbug and a logic bug in hwcrhk_load_pubkey().
[Toomas Kiisk <vix@cyber.ee> via Richard Levitte]
*) Add -keyform to rsautl, and document -engine.
[Richard Levitte, inspired by Toomas Kiisk <vix@cyber.ee>]
*) Change BIO_new_file (crypto/bio/bss_file.c) to use new
BIO_R_NO_SUCH_FILE error code rather than the generic
ERR_R_SYS_LIB error code if fopen() fails with ENOENT.
[Ben Laurie]
*) Add new functions
ERR_peek_last_error
ERR_peek_last_error_line
ERR_peek_last_error_line_data.
These are similar to
ERR_peek_error
ERR_peek_error_line
ERR_peek_error_line_data,
but report on the latest error recorded rather than the first one
still in the error queue.
[Ben Laurie, Bodo Moeller]
*) default_algorithms option in ENGINE config module. This allows things
like:
default_algorithms = ALL
default_algorithms = RSA, DSA, RAND, CIPHERS, DIGESTS
[Steve Henson]
*) Preliminary ENGINE config module.
[Steve Henson]
*) New experimental application configuration code.
[Steve Henson]
*) Change the AES code to follow the same name structure as all other
symmetric ciphers, and behave the same way. Move everything to
the directory crypto/aes, thereby obsoleting crypto/rijndael.
[Stephen Sprunk <stephen@sprunk.org> and Richard Levitte]
*) SECURITY: remove unsafe setjmp/signal interaction from ui_openssl.c.
[Ben Laurie and Theo de Raadt]
*) Add option to output public keys in req command.
[Massimiliano Pala madwolf@openca.org]
*) Use wNAFs in EC_POINTs_mul() for improved efficiency
(up to about 10% better than before for P-192 and P-224).
[Bodo Moeller]
*) New functions/macros
SSL_CTX_set_msg_callback(ctx, cb)
SSL_CTX_set_msg_callback_arg(ctx, arg)
SSL_set_msg_callback(ssl, cb)
SSL_set_msg_callback_arg(ssl, arg)
to request calling a callback function
void cb(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg)
whenever a protocol message has been completely received
(write_p == 0) or sent (write_p == 1). Here 'version' is the
protocol version according to which the SSL library interprets
the current protocol message (SSL2_VERSION, SSL3_VERSION, or
TLS1_VERSION). 'content_type' is 0 in the case of SSL 2.0, or
the content type as defined in the SSL 3.0/TLS 1.0 protocol
specification (change_cipher_spec(20), alert(21), handshake(22)).
'buf' and 'len' point to the actual message, 'ssl' to the
SSL object, and 'arg' is the application-defined value set by
SSL[_CTX]_set_msg_callback_arg().
'openssl s_client' and 'openssl s_server' have new '-msg' options
to enable a callback that displays all protocol messages.
[Bodo Moeller]
*) Change the shared library support so shared libraries are built as
soon as the corresponding static library is finished, and thereby get
openssl and the test programs linked against the shared library.
This still only happens when the keyword "shard" has been given to
the configuration scripts.
NOTE: shared library support is still an experimental thing, and
backward binary compatibility is still not guaranteed.
["Maciej W. Rozycki" <macro@ds2.pg.gda.pl> and Richard Levitte]
*) Add support for Subject Information Access extension.
[Peter Sylvester <Peter.Sylvester@EdelWeb.fr>]
*) Make BUF_MEM_grow() behaviour more consistent: Initialise to zero
additional bytes when new memory had to be allocated, not just
when reusing an existing buffer.
[Bodo Moeller]
*) New command line and configuration option 'utf8' for the req command.
This allows field values to be specified as UTF8 strings.
[Steve Henson]
*) Add -multi and -mr options to "openssl speed" - giving multiple parallel
runs for the former and machine-readable output for the latter.
[Ben Laurie]
*) Add '-noemailDN' option to 'openssl ca'. This prevents inclusion
of the e-mail address in the DN (i.e., it will go into a certificate
extension only). The new configuration file option 'email_in_dn = no'
has the same effect.
[Massimiliano Pala madwolf@openca.org]
*) Change all functions with names starting with des_ to be starting
with DES_ instead. Add wrappers that are compatible with libdes,
but are named _ossl_old_des_*. Finally, add macros that map the
des_* symbols to the corresponding _ossl_old_des_* if libdes
compatibility is desired. If OpenSSL 0.9.6c compatibility is
desired, the des_* symbols will be mapped to DES_*, with one
exception.
Since we provide two compatibility mappings, the user needs to
define the macro OPENSSL_DES_LIBDES_COMPATIBILITY if libdes
compatibility is desired. The default (i.e., when that macro
isn't defined) is OpenSSL 0.9.6c compatibility.
There are also macros that enable and disable the support of old
des functions altogether. Those are OPENSSL_ENABLE_OLD_DES_SUPPORT
and OPENSSL_DISABLE_OLD_DES_SUPPORT. If none or both of those
are defined, the default will apply: to support the old des routines.
In either case, one must include openssl/des.h to get the correct
definitions. Do not try to just include openssl/des_old.h, that
won't work.
NOTE: This is a major break of an old API into a new one. Software
authors are encouraged to switch to the DES_ style functions. Some
time in the future, des_old.h and the libdes compatibility functions
will be disable (i.e. OPENSSL_DISABLE_OLD_DES_SUPPORT will be the
default), and then completely removed.
[Richard Levitte]
*) Test for certificates which contain unsupported critical extensions.
If such a certificate is found during a verify operation it is
rejected by default: this behaviour can be overridden by either
handling the new error X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION or
by setting the verify flag X509_V_FLAG_IGNORE_CRITICAL. A new function
X509_supported_extension() has also been added which returns 1 if a
particular extension is supported.
[Steve Henson]
*) Modify the behaviour of EVP cipher functions in similar way to digests
to retain compatibility with existing code.
[Steve Henson]
*) Modify the behaviour of EVP_DigestInit() and EVP_DigestFinal() to retain
compatibility with existing code. In particular the 'ctx' parameter does
not have to be to be initialized before the call to EVP_DigestInit() and
it is tidied up after a call to EVP_DigestFinal(). New function
EVP_DigestFinal_ex() which does not tidy up the ctx. Similarly function
EVP_MD_CTX_copy() changed to not require the destination to be
initialized valid and new function EVP_MD_CTX_copy_ex() added which
requires the destination to be valid.
Modify all the OpenSSL digest calls to use EVP_DigestInit_ex(),
EVP_DigestFinal_ex() and EVP_MD_CTX_copy_ex().
[Steve Henson]
*) Change ssl3_get_message (ssl/s3_both.c) and the functions using it
so that complete 'Handshake' protocol structures are kept in memory
instead of overwriting 'msg_type' and 'length' with 'body' data.
[Bodo Moeller]
*) Add an implementation of SSL_add_dir_cert_subjects_to_stack for Win32.
[Massimo Santin via Richard Levitte]
*) Major restructuring to the underlying ENGINE code. This includes
reduction of linker bloat, separation of pure "ENGINE" manipulation
(initialisation, etc) from functionality dealing with implementations
of specific crypto interfaces. This change also introduces integrated
support for symmetric ciphers and digest implementations - so ENGINEs
can now accelerate these by providing EVP_CIPHER and EVP_MD
implementations of their own. This is detailed in crypto/engine/README
as it couldn't be adequately described here. However, there are a few
API changes worth noting - some RSA, DSA, DH, and RAND functions that
were changed in the original introduction of ENGINE code have now
reverted back - the hooking from this code to ENGINE is now a good
deal more passive and at run-time, operations deal directly with
RSA_METHODs, DSA_METHODs (etc) as they did before, rather than
dereferencing through an ENGINE pointer any more. Also, the ENGINE
functions dealing with BN_MOD_EXP[_CRT] handlers have been removed -
they were not being used by the framework as there is no concept of a
BIGNUM_METHOD and they could not be generalised to the new
'ENGINE_TABLE' mechanism that underlies the new code. Similarly,
ENGINE_cpy() has been removed as it cannot be consistently defined in
the new code.
[Geoff Thorpe]
*) Change ASN1_GENERALIZEDTIME_check() to allow fractional seconds.
[Steve Henson]
*) Change mkdef.pl to sort symbols that get the same entry number,
and make sure the automatically generated functions ERR_load_*
become part of libeay.num as well.
[Richard Levitte]
*) New function SSL_renegotiate_pending(). This returns true once
renegotiation has been requested (either SSL_renegotiate() call
or HelloRequest/ClientHello received from the peer) and becomes
false once a handshake has been completed.
(For servers, SSL_renegotiate() followed by SSL_do_handshake()
sends a HelloRequest, but does not ensure that a handshake takes
place. SSL_renegotiate_pending() is useful for checking if the
client has followed the request.)
[Bodo Moeller]
*) New SSL option SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION.
By default, clients may request session resumption even during
renegotiation (if session ID contexts permit); with this option,
session resumption is possible only in the first handshake.
SSL_OP_ALL is now 0x00000FFFL instead of 0x000FFFFFL. This makes
more bits available for options that should not be part of
SSL_OP_ALL (such as SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION).
[Bodo Moeller]
*) Add some demos for certificate and certificate request creation.
[Steve Henson]
*) Make maximum certificate chain size accepted from the peer application
settable (SSL*_get/set_max_cert_list()), as proposed by
"Douglas E. Engert" <deengert@anl.gov>.
[Lutz Jaenicke]
*) Add support for shared libraries for Unixware-7
(Boyd Lynn Gerber <gerberb@zenez.com>).
[Lutz Jaenicke]
*) Add a "destroy" handler to ENGINEs that allows structural cleanup to
be done prior to destruction. Use this to unload error strings from
ENGINEs that load their own error strings. NB: This adds two new API
functions to "get" and "set" this destroy handler in an ENGINE.
[Geoff Thorpe]
*) Alter all existing ENGINE implementations (except "openssl" and
"openbsd") to dynamically instantiate their own error strings. This
makes them more flexible to be built both as statically-linked ENGINEs
and self-contained shared-libraries loadable via the "dynamic" ENGINE.
Also, add stub code to each that makes building them as self-contained
shared-libraries easier (see README.ENGINE).
[Geoff Thorpe]
*) Add a "dynamic" ENGINE that provides a mechanism for binding ENGINE
implementations into applications that are completely implemented in
self-contained shared-libraries. The "dynamic" ENGINE exposes control
commands that can be used to configure what shared-library to load and
to control aspects of the way it is handled. Also, made an update to
the README.ENGINE file that brings its information up-to-date and
provides some information and instructions on the "dynamic" ENGINE
(ie. how to use it, how to build "dynamic"-loadable ENGINEs, etc).
[Geoff Thorpe]
*) Make it possible to unload ranges of ERR strings with a new
"ERR_unload_strings" function.
[Geoff Thorpe]
*) Add a copy() function to EVP_MD.
[Ben Laurie]
*) Make EVP_MD routines take a context pointer instead of just the
md_data void pointer.
[Ben Laurie]
*) Add flags to EVP_MD and EVP_MD_CTX. EVP_MD_FLAG_ONESHOT indicates
that the digest can only process a single chunk of data
(typically because it is provided by a piece of
hardware). EVP_MD_CTX_FLAG_ONESHOT indicates that the application
is only going to provide a single chunk of data, and hence the
framework needn't accumulate the data for oneshot drivers.
[Ben Laurie]
*) As with "ERR", make it possible to replace the underlying "ex_data"
functions. This change also alters the storage and management of global
ex_data state - it's now all inside ex_data.c and all "class" code (eg.
RSA, BIO, SSL_CTX, etc) no longer stores its own STACKS and per-class
index counters. The API functions that use this state have been changed
to take a "class_index" rather than pointers to the class's local STACK
and counter, and there is now an API function to dynamically create new
classes. This centralisation allows us to (a) plug a lot of the
thread-safety problems that existed, and (b) makes it possible to clean
up all allocated state using "CRYPTO_cleanup_all_ex_data()". W.r.t. (b)
such data would previously have always leaked in application code and
workarounds were in place to make the memory debugging turn a blind eye
to it. Application code that doesn't use this new function will still
leak as before, but their memory debugging output will announce it now
rather than letting it slide.
Besides the addition of CRYPTO_cleanup_all_ex_data(), another API change
induced by the "ex_data" overhaul is that X509_STORE_CTX_init() now
has a return value to indicate success or failure.
[Geoff Thorpe]
*) Make it possible to replace the underlying "ERR" functions such that the
global state (2 LHASH tables and 2 locks) is only used by the "default"
implementation. This change also adds two functions to "get" and "set"
the implementation prior to it being automatically set the first time
any other ERR function takes place. Ie. an application can call "get",
pass the return value to a module it has just loaded, and that module
can call its own "set" function using that value. This means the
module's "ERR" operations will use (and modify) the error state in the
application and not in its own statically linked copy of OpenSSL code.
[Geoff Thorpe]
*) Give DH, DSA, and RSA types their own "**_up_ref()" function to increment
reference counts. This performs normal REF_PRINT/REF_CHECK macros on
the operation, and provides a more encapsulated way for external code
(crypto/evp/ and ssl/) to do this. Also changed the evp and ssl code
to use these functions rather than manually incrementing the counts.
Also rename "DSO_up()" function to more descriptive "DSO_up_ref()".
[Geoff Thorpe]
*) Add EVP test program.
[Ben Laurie]
*) Add symmetric cipher support to ENGINE. Expect the API to change!
[Ben Laurie]
*) New CRL functions: X509_CRL_set_version(), X509_CRL_set_issuer_name()
X509_CRL_set_lastUpdate(), X509_CRL_set_nextUpdate(), X509_CRL_sort(),
X509_REVOKED_set_serialNumber(), and X509_REVOKED_set_revocationDate().
These allow a CRL to be built without having to access X509_CRL fields
directly. Modify 'ca' application to use new functions.
[Steve Henson]
*) Move SSL_OP_TLS_ROLLBACK_BUG out of the SSL_OP_ALL list of recommended
bug workarounds. Rollback attack detection is a security feature.
The problem will only arise on OpenSSL servers when TLSv1 is not
available (sslv3_server_method() or SSL_OP_NO_TLSv1).
Software authors not wanting to support TLSv1 will have special reasons
for their choice and can explicitly enable this option.
[Bodo Moeller, Lutz Jaenicke]
*) Rationalise EVP so it can be extended: don't include a union of
cipher/digest structures, add init/cleanup functions for EVP_MD_CTX
(similar to those existing for EVP_CIPHER_CTX).
Usage example:
EVP_MD_CTX md;
EVP_MD_CTX_init(&md); /* new function call */
EVP_DigestInit(&md, EVP_sha1());
EVP_DigestUpdate(&md, in, len);
EVP_DigestFinal(&md, out, NULL);
EVP_MD_CTX_cleanup(&md); /* new function call */
[Ben Laurie]
*) Make DES key schedule conform to the usual scheme, as well as
correcting its structure. This means that calls to DES functions
now have to pass a pointer to a des_key_schedule instead of a
plain des_key_schedule (which was actually always a pointer
anyway): E.g.,
des_key_schedule ks;
des_set_key_checked(..., &ks);
des_ncbc_encrypt(..., &ks, ...);
(Note that a later change renames 'des_...' into 'DES_...'.)
[Ben Laurie]
*) Initial reduction of linker bloat: the use of some functions, such as
PEM causes large amounts of unused functions to be linked in due to
poor organisation. For example pem_all.c contains every PEM function
which has a knock on effect of linking in large amounts of (unused)
ASN1 code. Grouping together similar functions and splitting unrelated
functions prevents this.
[Steve Henson]
*) Cleanup of EVP macros.
[Ben Laurie]
*) Change historical references to {NID,SN,LN}_des_ede and ede3 to add the
correct _ecb suffix.
[Ben Laurie]
*) Add initial OCSP responder support to ocsp application. The
revocation information is handled using the text based index
use by the ca application. The responder can either handle
requests generated internally, supplied in files (for example
via a CGI script) or using an internal minimal server.
[Steve Henson]
*) Add configuration choices to get zlib compression for TLS.
[Richard Levitte]
*) Changes to Kerberos SSL for RFC 2712 compliance:
1. Implemented real KerberosWrapper, instead of just using
KRB5 AP_REQ message. [Thanks to Simon Wilkinson <sxw@sxw.org.uk>]
2. Implemented optional authenticator field of KerberosWrapper.
Added openssl-style ASN.1 macros for Kerberos ticket, ap_req,
and authenticator structs; see crypto/krb5/.
Generalized Kerberos calls to support multiple Kerberos libraries.
[Vern Staats <staatsvr@asc.hpc.mil>,
Jeffrey Altman <jaltman@columbia.edu>
via Richard Levitte]
*) Cause 'openssl speed' to use fully hard-coded DSA keys as it
already does with RSA. testdsa.h now has 'priv_key/pub_key'
values for each of the key sizes rather than having just
parameters (and 'speed' generating keys each time).
[Geoff Thorpe]
*) Speed up EVP routines.
Before:
encrypt
type 8 bytes 64 bytes 256 bytes 1024 bytes 8192 bytes
des-cbc 4408.85k 5560.51k 5778.46k 5862.20k 5825.16k
des-cbc 4389.55k 5571.17k 5792.23k 5846.91k 5832.11k
des-cbc 4394.32k 5575.92k 5807.44k 5848.37k 5841.30k
decrypt
des-cbc 3482.66k 5069.49k 5496.39k 5614.16k 5639.28k
des-cbc 3480.74k 5068.76k 5510.34k 5609.87k 5635.52k
des-cbc 3483.72k 5067.62k 5504.60k 5708.01k 5724.80k
After:
encrypt
des-cbc 4660.16k 5650.19k 5807.19k 5827.13k 5783.32k
decrypt
des-cbc 3624.96k 5258.21k 5530.91k 5624.30k 5628.26k
[Ben Laurie]
*) Added the OS2-EMX target.
["Brian Havard" <brianh@kheldar.apana.org.au> and Richard Levitte]
*) Rewrite apps to use NCONF routines instead of the old CONF. New functions
to support NCONF routines in extension code. New function CONF_set_nconf()
to allow functions which take an NCONF to also handle the old LHASH
structure: this means that the old CONF compatible routines can be
retained (in particular wrt extensions) without having to duplicate the
code. New function X509V3_add_ext_nconf_sk to add extensions to a stack.
[Steve Henson]
*) Enhance the general user interface with mechanisms for inner control
and with possibilities to have yes/no kind of prompts.
[Richard Levitte]
*) Change all calls to low level digest routines in the library and
applications to use EVP. Add missing calls to HMAC_cleanup() and
don't assume HMAC_CTX can be copied using memcpy().
[Verdon Walker <VWalker@novell.com>, Steve Henson]
*) Add the possibility to control engines through control names but with
arbitrary arguments instead of just a string.
Change the key loaders to take a UI_METHOD instead of a callback
function pointer. NOTE: this breaks binary compatibility with earlier
versions of OpenSSL [engine].
Adapt the nCipher code for these new conditions and add a card insertion
callback.
[Richard Levitte]
*) Enhance the general user interface with mechanisms to better support
dialog box interfaces, application-defined prompts, the possibility
to use defaults (for example default passwords from somewhere else)
and interrupts/cancellations.
[Richard Levitte]
*) Tidy up PKCS#12 attribute handling. Add support for the CSP name
attribute in PKCS#12 files, add new -CSP option to pkcs12 utility.
[Steve Henson]
*) Fix a memory leak in 'sk_dup()' in the case reallocation fails. (Also
tidy up some unnecessarily weird code in 'sk_new()').
[Geoff, reported by Diego Tartara <dtartara@novamens.com>]
*) Change the key loading routines for ENGINEs to use the same kind
callback (pem_password_cb) as all other routines that need this
kind of callback.
[Richard Levitte]
*) Increase ENTROPY_NEEDED to 32 bytes, as Rijndael can operate with
256 bit (=32 byte) keys. Of course seeding with more entropy bytes
than this minimum value is recommended.
[Lutz Jaenicke]
*) New random seeder for OpenVMS, using the system process statistics
that are easily reachable.
[Richard Levitte]
*) Windows apparently can't transparently handle global
variables defined in DLLs. Initialisations such as:
const ASN1_ITEM *it = &ASN1_INTEGER_it;
won't compile. This is used by the any applications that need to
declare their own ASN1 modules. This was fixed by adding the option
EXPORT_VAR_AS_FN to all Win32 platforms, although this isn't strictly
needed for static libraries under Win32.
[Steve Henson]
*) New functions X509_PURPOSE_set() and X509_TRUST_set() to handle
setting of purpose and trust fields. New X509_STORE trust and
purpose functions and tidy up setting in other SSL functions.
[Steve Henson]
*) Add copies of X509_STORE_CTX fields and callbacks to X509_STORE
structure. These are inherited by X509_STORE_CTX when it is
initialised. This allows various defaults to be set in the
X509_STORE structure (such as flags for CRL checking and custom
purpose or trust settings) for functions which only use X509_STORE_CTX
internally such as S/MIME.
Modify X509_STORE_CTX_purpose_inherit() so it only sets purposes and
trust settings if they are not set in X509_STORE. This allows X509_STORE
purposes and trust (in S/MIME for example) to override any set by default.
Add command line options for CRL checking to smime, s_client and s_server
applications.
[Steve Henson]
*) Initial CRL based revocation checking. If the CRL checking flag(s)
are set then the CRL is looked up in the X509_STORE structure and
its validity and signature checked, then if the certificate is found
in the CRL the verify fails with a revoked error.
Various new CRL related callbacks added to X509_STORE_CTX structure.
Command line options added to 'verify' application to support this.
This needs some additional work, such as being able to handle multiple
CRLs with different times, extension based lookup (rather than just
by subject name) and ultimately more complete V2 CRL extension
handling.
[Steve Henson]
*) Add a general user interface API (crypto/ui/). This is designed
to replace things like des_read_password and friends (backward
compatibility functions using this new API are provided).
The purpose is to remove prompting functions from the DES code
section as well as provide for prompting through dialog boxes in
a window system and the like.
[Richard Levitte]
*) Add "ex_data" support to ENGINE so implementations can add state at a
per-structure level rather than having to store it globally.
[Geoff]
*) Make it possible for ENGINE structures to be copied when retrieved by
ENGINE_by_id() if the ENGINE specifies a new flag: ENGINE_FLAGS_BY_ID_COPY.
This causes the "original" ENGINE structure to act like a template,
analogous to the RSA vs. RSA_METHOD type of separation. Because of this
operational state can be localised to each ENGINE structure, despite the
fact they all share the same "methods". New ENGINE structures returned in
this case have no functional references and the return value is the single
structural reference. This matches the single structural reference returned
by ENGINE_by_id() normally, when it is incremented on the pre-existing
ENGINE structure.
[Geoff]
*) Fix ASN1 decoder when decoding type ANY and V_ASN1_OTHER: since this
needs to match any other type at all we need to manually clear the
tag cache.
[Steve Henson]
*) Changes to the "openssl engine" utility to include;
- verbosity levels ('-v', '-vv', and '-vvv') that provide information
about an ENGINE's available control commands.
- executing control commands from command line arguments using the
'-pre' and '-post' switches. '-post' is only used if '-t' is
specified and the ENGINE is successfully initialised. The syntax for
the individual commands are colon-separated, for example;
openssl engine chil -pre FORK_CHECK:0 -pre SO_PATH:/lib/test.so
[Geoff]
*) New dynamic control command support for ENGINEs. ENGINEs can now
declare their own commands (numbers), names (strings), descriptions,
and input types for run-time discovery by calling applications. A
subset of these commands are implicitly classed as "executable"
depending on their input type, and only these can be invoked through
the new string-based API function ENGINE_ctrl_cmd_string(). (Eg. this
can be based on user input, config files, etc). The distinction is
that "executable" commands cannot return anything other than a boolean
result and can only support numeric or string input, whereas some
discoverable commands may only be for direct use through
ENGINE_ctrl(), eg. supporting the exchange of binary data, function
pointers, or other custom uses. The "executable" commands are to
support parameterisations of ENGINE behaviour that can be
unambiguously defined by ENGINEs and used consistently across any
OpenSSL-based application. Commands have been added to all the
existing hardware-supporting ENGINEs, noticeably "SO_PATH" to allow
control over shared-library paths without source code alterations.
[Geoff]
*) Changed all ENGINE implementations to dynamically allocate their
ENGINEs rather than declaring them statically. Apart from this being
necessary with the removal of the ENGINE_FLAGS_MALLOCED distinction,
this also allows the implementations to compile without using the
internal engine_int.h header.
[Geoff]
*) Minor adjustment to "rand" code. RAND_get_rand_method() now returns a
'const' value. Any code that should be able to modify a RAND_METHOD
should already have non-const pointers to it (ie. they should only
modify their own ones).
[Geoff]
*) Made a variety of little tweaks to the ENGINE code.
- "atalla" and "ubsec" string definitions were moved from header files
to C code. "nuron" string definitions were placed in variables
rather than hard-coded - allowing parameterisation of these values
later on via ctrl() commands.
- Removed unused "#if 0"'d code.
- Fixed engine list iteration code so it uses ENGINE_free() to release
structural references.
- Constified the RAND_METHOD element of ENGINE structures.
- Constified various get/set functions as appropriate and added
missing functions (including a catch-all ENGINE_cpy that duplicates
all ENGINE values onto a new ENGINE except reference counts/state).
- Removed NULL parameter checks in get/set functions. Setting a method
or function to NULL is a way of cancelling out a previously set
value. Passing a NULL ENGINE parameter is just plain stupid anyway
and doesn't justify the extra error symbols and code.
- Deprecate the ENGINE_FLAGS_MALLOCED define and move the area for
flags from engine_int.h to engine.h.
- Changed prototypes for ENGINE handler functions (init(), finish(),
ctrl(), key-load functions, etc) to take an (ENGINE*) parameter.
[Geoff]
*) Implement binary inversion algorithm for BN_mod_inverse in addition
to the algorithm using long division. The binary algorithm can be
used only if the modulus is odd. On 32-bit systems, it is faster
only for relatively small moduli (roughly 20-30% for 128-bit moduli,
roughly 5-15% for 256-bit moduli), so we use it only for moduli
up to 450 bits. In 64-bit environments, the binary algorithm
appears to be advantageous for much longer moduli; here we use it
for moduli up to 2048 bits.
[Bodo Moeller]
*) Rewrite CHOICE field setting in ASN1_item_ex_d2i(). The old code
could not support the combine flag in choice fields.
[Steve Henson]
*) Add a 'copy_extensions' option to the 'ca' utility. This copies
extensions from a certificate request to the certificate.
[Steve Henson]
*) Allow multiple 'certopt' and 'nameopt' options to be separated
by commas. Add 'namopt' and 'certopt' options to the 'ca' config
file: this allows the display of the certificate about to be
signed to be customised, to allow certain fields to be included
or excluded and extension details. The old system didn't display
multicharacter strings properly, omitted fields not in the policy
and couldn't display additional details such as extensions.
[Steve Henson]
*) Function EC_POINTs_mul for multiple scalar multiplication
of an arbitrary number of elliptic curve points
\sum scalars[i]*points[i],
optionally including the generator defined for the EC_GROUP:
scalar*generator + \sum scalars[i]*points[i].
EC_POINT_mul is a simple wrapper function for the typical case
that the point list has just one item (besides the optional
generator).
[Bodo Moeller]
*) First EC_METHODs for curves over GF(p):
EC_GFp_simple_method() uses the basic BN_mod_mul and BN_mod_sqr
operations and provides various method functions that can also
operate with faster implementations of modular arithmetic.
EC_GFp_mont_method() reuses most functions that are part of
EC_GFp_simple_method, but uses Montgomery arithmetic.
[Bodo Moeller; point addition and point doubling
implementation directly derived from source code provided by
Lenka Fibikova <fibikova@exp-math.uni-essen.de>]
*) Framework for elliptic curves (crypto/ec/ec.h, crypto/ec/ec_lcl.h,
crypto/ec/ec_lib.c):
Curves are EC_GROUP objects (with an optional group generator)
based on EC_METHODs that are built into the library.
Points are EC_POINT objects based on EC_GROUP objects.
Most of the framework would be able to handle curves over arbitrary
finite fields, but as there are no obvious types for fields other
than GF(p), some functions are limited to that for now.
[Bodo Moeller]
*) Add the -HTTP option to s_server. It is similar to -WWW, but requires
that the file contains a complete HTTP response.
[Richard Levitte]
*) Add the ec directory to mkdef.pl and mkfiles.pl. In mkdef.pl
change the def and num file printf format specifier from "%-40sXXX"
to "%-39s XXX". The latter will always guarantee a space after the
field while the former will cause them to run together if the field
is 40 of more characters long.
[Steve Henson]
*) Constify the cipher and digest 'method' functions and structures
and modify related functions to take constant EVP_MD and EVP_CIPHER
pointers.
[Steve Henson]
*) Hide BN_CTX structure details in bn_lcl.h instead of publishing them
in <openssl/bn.h>. Also further increase BN_CTX_NUM to 32.
[Bodo Moeller]
*) Modify EVP_Digest*() routines so they now return values. Although the
internal software routines can never fail additional hardware versions
might.
[Steve Henson]
*) Clean up crypto/err/err.h and change some error codes to avoid conflicts:
Previously ERR_R_FATAL was too small and coincided with ERR_LIB_PKCS7
(= ERR_R_PKCS7_LIB); it is now 64 instead of 32.
ASN1 error codes
ERR_R_NESTED_ASN1_ERROR
...
ERR_R_MISSING_ASN1_EOS
were 4 .. 9, conflicting with
ERR_LIB_RSA (= ERR_R_RSA_LIB)
...
ERR_LIB_PEM (= ERR_R_PEM_LIB).
They are now 58 .. 63 (i.e., just below ERR_R_FATAL).
Add new error code 'ERR_R_INTERNAL_ERROR'.
[Bodo Moeller]
*) Don't overuse locks in crypto/err/err.c: For data retrieval, CRYPTO_r_lock
suffices.
[Bodo Moeller]
*) New option '-subj arg' for 'openssl req' and 'openssl ca'. This
sets the subject name for a new request or supersedes the
subject name in a given request. Formats that can be parsed are
'CN=Some Name, OU=myOU, C=IT'
and
'CN=Some Name/OU=myOU/C=IT'.
Add options '-batch' and '-verbose' to 'openssl req'.
[Massimiliano Pala <madwolf@hackmasters.net>]
*) Introduce the possibility to access global variables through
functions on platform were that's the best way to handle exporting
global variables in shared libraries. To enable this functionality,
one must configure with "EXPORT_VAR_AS_FN" or defined the C macro
"OPENSSL_EXPORT_VAR_AS_FUNCTION" in crypto/opensslconf.h (the latter
is normally done by Configure or something similar).
To implement a global variable, use the macro OPENSSL_IMPLEMENT_GLOBAL
in the source file (foo.c) like this:
OPENSSL_IMPLEMENT_GLOBAL(int,foo)=1;
OPENSSL_IMPLEMENT_GLOBAL(double,bar);
To declare a global variable, use the macros OPENSSL_DECLARE_GLOBAL
and OPENSSL_GLOBAL_REF in the header file (foo.h) like this:
OPENSSL_DECLARE_GLOBAL(int,foo);
#define foo OPENSSL_GLOBAL_REF(foo)
OPENSSL_DECLARE_GLOBAL(double,bar);
#define bar OPENSSL_GLOBAL_REF(bar)
The #defines are very important, and therefore so is including the
header file everywhere where the defined globals are used.
The macro OPENSSL_EXPORT_VAR_AS_FUNCTION also affects the definition
of ASN.1 items, but that structure is a bit different.
The largest change is in util/mkdef.pl which has been enhanced with
better and easier to understand logic to choose which symbols should
go into the Windows .def files as well as a number of fixes and code
cleanup (among others, algorithm keywords are now sorted
lexicographically to avoid constant rewrites).
[Richard Levitte]
*) In BN_div() keep a copy of the sign of 'num' before writing the
result to 'rm' because if rm==num the value will be overwritten
and produce the wrong result if 'num' is negative: this caused
problems with BN_mod() and BN_nnmod().
[Steve Henson]
*) Function OCSP_request_verify(). This checks the signature on an
OCSP request and verifies the signer certificate. The signer
certificate is just checked for a generic purpose and OCSP request
trust settings.
[Steve Henson]
*) Add OCSP_check_validity() function to check the validity of OCSP
responses. OCSP responses are prepared in real time and may only
be a few seconds old. Simply checking that the current time lies
between thisUpdate and nextUpdate max reject otherwise valid responses
caused by either OCSP responder or client clock inaccuracy. Instead
we allow thisUpdate and nextUpdate to fall within a certain period of
the current time. The age of the response can also optionally be
checked. Two new options -validity_period and -status_age added to
ocsp utility.
[Steve Henson]
*) If signature or public key algorithm is unrecognized print out its
OID rather that just UNKNOWN.
[Steve Henson]
*) Change OCSP_cert_to_id() to tolerate a NULL subject certificate and
OCSP_cert_id_new() a NULL serialNumber. This allows a partial certificate
ID to be generated from the issuer certificate alone which can then be
passed to OCSP_id_issuer_cmp().
[Steve Henson]
*) New compilation option ASN1_ITEM_FUNCTIONS. This causes the new
ASN1 modules to export functions returning ASN1_ITEM pointers
instead of the ASN1_ITEM structures themselves. This adds several
new macros which allow the underlying ASN1 function/structure to
be accessed transparently. As a result code should not use ASN1_ITEM
references directly (such as &X509_it) but instead use the relevant
macros (such as ASN1_ITEM_rptr(X509)). This option is to allow
use of the new ASN1 code on platforms where exporting structures
is problematical (for example in shared libraries) but exporting
functions returning pointers to structures is not.
[Steve Henson]
*) Add support for overriding the generation of SSL/TLS session IDs.
These callbacks can be registered either in an SSL_CTX or per SSL.
The purpose of this is to allow applications to control, if they wish,
the arbitrary values chosen for use as session IDs, particularly as it
can be useful for session caching in multiple-server environments. A
command-line switch for testing this (and any client code that wishes
to use such a feature) has been added to "s_server".
[Geoff Thorpe, Lutz Jaenicke]
*) Modify mkdef.pl to recognise and parse preprocessor conditionals
of the form '#if defined(...) || defined(...) || ...' and
'#if !defined(...) && !defined(...) && ...'. This also avoids
the growing number of special cases it was previously handling.
[Richard Levitte]
*) Make all configuration macros available for application by making
sure they are available in opensslconf.h, by giving them names starting
with "OPENSSL_" to avoid conflicts with other packages and by making
sure e_os2.h will cover all platform-specific cases together with
opensslconf.h.
Additionally, it is now possible to define configuration/platform-
specific names (called "system identities"). In the C code, these
are prefixed with "OPENSSL_SYSNAME_". e_os2.h will create another
macro with the name beginning with "OPENSSL_SYS_", which is determined
from "OPENSSL_SYSNAME_*" or compiler-specific macros depending on
what is available.
[Richard Levitte]
*) New option -set_serial to 'req' and 'x509' this allows the serial
number to use to be specified on the command line. Previously self
signed certificates were hard coded with serial number 0 and the
CA options of 'x509' had to use a serial number in a file which was
auto incremented.
[Steve Henson]
*) New options to 'ca' utility to support V2 CRL entry extensions.
Currently CRL reason, invalidity date and hold instruction are
supported. Add new CRL extensions to V3 code and some new objects.
[Steve Henson]
*) New function EVP_CIPHER_CTX_set_padding() this is used to
disable standard block padding (aka PKCS#5 padding) in the EVP
API, which was previously mandatory. This means that the data is
not padded in any way and so the total length much be a multiple
of the block size, otherwise an error occurs.
[Steve Henson]
*) Initial (incomplete) OCSP SSL support.
[Steve Henson]
*) New function OCSP_parse_url(). This splits up a URL into its host,
port and path components: primarily to parse OCSP URLs. New -url
option to ocsp utility.
[Steve Henson]
*) New nonce behavior. The return value of OCSP_check_nonce() now
reflects the various checks performed. Applications can decide
whether to tolerate certain situations such as an absent nonce
in a response when one was present in a request: the ocsp application
just prints out a warning. New function OCSP_add1_basic_nonce()
this is to allow responders to include a nonce in a response even if
the request is nonce-less.
[Steve Henson]
*) Disable stdin buffering in load_cert (apps/apps.c) so that no certs are
skipped when using openssl x509 multiple times on a single input file,
e.g. "(openssl x509 -out cert1; openssl x509 -out cert2) <certs".
[Bodo Moeller]
*) Make ASN1_UTCTIME_set_string() and ASN1_GENERALIZEDTIME_set_string()
set string type: to handle setting ASN1_TIME structures. Fix ca
utility to correctly initialize revocation date of CRLs.
[Steve Henson]
*) New option SSL_OP_CIPHER_SERVER_PREFERENCE allows the server to override
the clients preferred ciphersuites and rather use its own preferences.
Should help to work around M$ SGC (Server Gated Cryptography) bug in
Internet Explorer by ensuring unchanged hash method during stepup.
(Also replaces the broken/deactivated SSL_OP_NON_EXPORT_FIRST option.)
[Lutz Jaenicke]
*) Make mkdef.pl recognise all DECLARE_ASN1 macros, change rijndael
to aes and add a new 'exist' option to print out symbols that don't
appear to exist.
[Steve Henson]
*) Additional options to ocsp utility to allow flags to be set and
additional certificates supplied.
[Steve Henson]
*) Add the option -VAfile to 'openssl ocsp', so the user can give the
OCSP client a number of certificate to only verify the response
signature against.
[Richard Levitte]
*) Update Rijndael code to version 3.0 and change EVP AES ciphers to
handle the new API. Currently only ECB, CBC modes supported. Add new
AES OIDs.
Add TLS AES ciphersuites as described in RFC3268, "Advanced
Encryption Standard (AES) Ciphersuites for Transport Layer
Security (TLS)". (In beta versions of OpenSSL 0.9.7, these were
not enabled by default and were not part of the "ALL" ciphersuite
alias because they were not yet official; they could be
explicitly requested by specifying the "AESdraft" ciphersuite
group alias. In the final release of OpenSSL 0.9.7, the group
alias is called "AES" and is part of "ALL".)
[Ben Laurie, Steve Henson, Bodo Moeller]
*) New function OCSP_copy_nonce() to copy nonce value (if present) from
request to response.
[Steve Henson]
*) Functions for OCSP responders. OCSP_request_onereq_count(),
OCSP_request_onereq_get0(), OCSP_onereq_get0_id() and OCSP_id_get0_info()
extract information from a certificate request. OCSP_response_create()
creates a response and optionally adds a basic response structure.
OCSP_basic_add1_status() adds a complete single response to a basic
response and returns the OCSP_SINGLERESP structure just added (to allow
extensions to be included for example). OCSP_basic_add1_cert() adds a
certificate to a basic response and OCSP_basic_sign() signs a basic
response with various flags. New helper functions ASN1_TIME_check()
(checks validity of ASN1_TIME structure) and ASN1_TIME_to_generalizedtime()
(converts ASN1_TIME to GeneralizedTime).
[Steve Henson]
*) Various new functions. EVP_Digest() combines EVP_Digest{Init,Update,Final}()
in a single operation. X509_get0_pubkey_bitstr() extracts the public_key
structure from a certificate. X509_pubkey_digest() digests the public_key
contents: this is used in various key identifiers.
[Steve Henson]
*) Make sk_sort() tolerate a NULL argument.
[Steve Henson reported by Massimiliano Pala <madwolf@comune.modena.it>]
*) New OCSP verify flag OCSP_TRUSTOTHER. When set the "other" certificates
passed by the function are trusted implicitly. If any of them signed the
response then it is assumed to be valid and is not verified.
[Steve Henson]
*) In PKCS7_set_type() initialise content_type in PKCS7_ENC_CONTENT
to data. This was previously part of the PKCS7 ASN1 code. This
was causing problems with OpenSSL created PKCS#12 and PKCS#7 structures.
[Steve Henson, reported by Kenneth R. Robinette
<support@securenetterm.com>]
*) Add CRYPTO_push_info() and CRYPTO_pop_info() calls to new ASN1
routines: without these tracing memory leaks is very painful.
Fix leaks in PKCS12 and PKCS7 routines.
[Steve Henson]
*) Make X509_time_adj() cope with the new behaviour of ASN1_TIME_new().
Previously it initialised the 'type' argument to V_ASN1_UTCTIME which
effectively meant GeneralizedTime would never be used. Now it
is initialised to -1 but X509_time_adj() now has to check the value
and use ASN1_TIME_set() if the value is not V_ASN1_UTCTIME or
V_ASN1_GENERALIZEDTIME, without this it always uses GeneralizedTime.
[Steve Henson, reported by Kenneth R. Robinette
<support@securenetterm.com>]
*) Fixes to BN_to_ASN1_INTEGER when bn is zero. This would previously
result in a zero length in the ASN1_INTEGER structure which was
not consistent with the structure when d2i_ASN1_INTEGER() was used
and would cause ASN1_INTEGER_cmp() to fail. Enhance s2i_ASN1_INTEGER()
to cope with hex and negative integers. Fix bug in i2a_ASN1_INTEGER()
where it did not print out a minus for negative ASN1_INTEGER.
[Steve Henson]
*) Add summary printout to ocsp utility. The various functions which
convert status values to strings have been renamed to:
OCSP_response_status_str(), OCSP_cert_status_str() and
OCSP_crl_reason_str() and are no longer static. New options
to verify nonce values and to disable verification. OCSP response
printout format cleaned up.
[Steve Henson]
*) Add additional OCSP certificate checks. These are those specified
in RFC2560. This consists of two separate checks: the CA of the
certificate being checked must either be the OCSP signer certificate
or the issuer of the OCSP signer certificate. In the latter case the
OCSP signer certificate must contain the OCSP signing extended key
usage. This check is performed by attempting to match the OCSP
signer or the OCSP signer CA to the issuerNameHash and issuerKeyHash
in the OCSP_CERTID structures of the response.
[Steve Henson]
*) Initial OCSP certificate verification added to OCSP_basic_verify()
and related routines. This uses the standard OpenSSL certificate
verify routines to perform initial checks (just CA validity) and
to obtain the certificate chain. Then additional checks will be
performed on the chain. Currently the root CA is checked to see
if it is explicitly trusted for OCSP signing. This is used to set
a root CA as a global signing root: that is any certificate that
chains to that CA is an acceptable OCSP signing certificate.
[Steve Henson]
*) New '-extfile ...' option to 'openssl ca' for reading X.509v3
extensions from a separate configuration file.
As when reading extensions from the main configuration file,
the '-extensions ...' option may be used for specifying the
section to use.
[Massimiliano Pala <madwolf@comune.modena.it>]
*) New OCSP utility. Allows OCSP requests to be generated or
read. The request can be sent to a responder and the output
parsed, outputed or printed in text form. Not complete yet:
still needs to check the OCSP response validity.
[Steve Henson]
*) New subcommands for 'openssl ca':
'openssl ca -status <serial>' prints the status of the cert with
the given serial number (according to the index file).
'openssl ca -updatedb' updates the expiry status of certificates
in the index file.
[Massimiliano Pala <madwolf@comune.modena.it>]
*) New '-newreq-nodes' command option to CA.pl. This is like
'-newreq', but calls 'openssl req' with the '-nodes' option
so that the resulting key is not encrypted.
[Damien Miller <djm@mindrot.org>]
*) New configuration for the GNU Hurd.
[Jonathan Bartlett <johnnyb@wolfram.com> via Richard Levitte]
*) Initial code to implement OCSP basic response verify. This
is currently incomplete. Currently just finds the signer's
certificate and verifies the signature on the response.
[Steve Henson]
*) New SSLeay_version code SSLEAY_DIR to determine the compiled-in
value of OPENSSLDIR. This is available via the new '-d' option
to 'openssl version', and is also included in 'openssl version -a'.
[Bodo Moeller]
*) Allowing defining memory allocation callbacks that will be given
file name and line number information in additional arguments
(a const char* and an int). The basic functionality remains, as
well as the original possibility to just replace malloc(),
realloc() and free() by functions that do not know about these
additional arguments. To register and find out the current
settings for extended allocation functions, the following
functions are provided:
CRYPTO_set_mem_ex_functions
CRYPTO_set_locked_mem_ex_functions
CRYPTO_get_mem_ex_functions
CRYPTO_get_locked_mem_ex_functions
These work the same way as CRYPTO_set_mem_functions and friends.
CRYPTO_get_[locked_]mem_functions now writes 0 where such an
extended allocation function is enabled.
Similarly, CRYPTO_get_[locked_]mem_ex_functions writes 0 where
a conventional allocation function is enabled.
[Richard Levitte, Bodo Moeller]
*) Finish off removing the remaining LHASH function pointer casts.
There should no longer be any prototype-casting required when using
the LHASH abstraction, and any casts that remain are "bugs". See
the callback types and macros at the head of lhash.h for details
(and "OBJ_cleanup" in crypto/objects/obj_dat.c as an example).
[Geoff Thorpe]
*) Add automatic query of EGD sockets in RAND_poll() for the unix variant.
If /dev/[u]random devices are not available or do not return enough
entropy, EGD style sockets (served by EGD or PRNGD) will automatically
be queried.
The locations /var/run/egd-pool, /dev/egd-pool, /etc/egd-pool, and
/etc/entropy will be queried once each in this sequence, querying stops
when enough entropy was collected without querying more sockets.
[Lutz Jaenicke]
*) Change the Unix RAND_poll() variant to be able to poll several
random devices, as specified by DEVRANDOM, until a sufficient amount
of data has been collected. We spend at most 10 ms on each file
(select timeout) and read in non-blocking mode. DEVRANDOM now
defaults to the list "/dev/urandom", "/dev/random", "/dev/srandom"
(previously it was just the string "/dev/urandom"), so on typical
platforms the 10 ms delay will never occur.
Also separate out the Unix variant to its own file, rand_unix.c.
For VMS, there's a currently-empty rand_vms.c.
[Richard Levitte]
*) Move OCSP client related routines to ocsp_cl.c. These
provide utility functions which an application needing
to issue a request to an OCSP responder and analyse the
response will typically need: as opposed to those which an
OCSP responder itself would need which will be added later.
OCSP_request_sign() signs an OCSP request with an API similar
to PKCS7_sign(). OCSP_response_status() returns status of OCSP
response. OCSP_response_get1_basic() extracts basic response
from response. OCSP_resp_find_status(): finds and extracts status
information from an OCSP_CERTID structure (which will be created
when the request structure is built). These are built from lower
level functions which work on OCSP_SINGLERESP structures but
won't normally be used unless the application wishes to examine
extensions in the OCSP response for example.
Replace nonce routines with a pair of functions.
OCSP_request_add1_nonce() adds a nonce value and optionally
generates a random value. OCSP_check_nonce() checks the
validity of the nonce in an OCSP response.
[Steve Henson]
*) Change function OCSP_request_add() to OCSP_request_add0_id().
This doesn't copy the supplied OCSP_CERTID and avoids the
need to free up the newly created id. Change return type
to OCSP_ONEREQ to return the internal OCSP_ONEREQ structure.
This can then be used to add extensions to the request.
Deleted OCSP_request_new(), since most of its functionality
is now in OCSP_REQUEST_new() (and the case insensitive name
clash) apart from the ability to set the request name which
will be added elsewhere.
[Steve Henson]
*) Update OCSP API. Remove obsolete extensions argument from
various functions. Extensions are now handled using the new
OCSP extension code. New simple OCSP HTTP function which
can be used to send requests and parse the response.
[Steve Henson]
*) Fix the PKCS#7 (S/MIME) code to work with new ASN1. Two new
ASN1_ITEM structures help with sign and verify. PKCS7_ATTR_SIGN
uses the special reorder version of SET OF to sort the attributes
and reorder them to match the encoded order. This resolves a long
standing problem: a verify on a PKCS7 structure just after signing
it used to fail because the attribute order did not match the
encoded order. PKCS7_ATTR_VERIFY does not reorder the attributes:
it uses the received order. This is necessary to tolerate some broken
software that does not order SET OF. This is handled by encoding
as a SEQUENCE OF but using implicit tagging (with UNIVERSAL class)
to produce the required SET OF.
[Steve Henson]
*) Have mk1mf.pl generate the macros OPENSSL_BUILD_SHLIBCRYPTO and
OPENSSL_BUILD_SHLIBSSL and use them appropriately in the header
files to get correct declarations of the ASN.1 item variables.
[Richard Levitte]
*) Rewrite of PKCS#12 code to use new ASN1 functionality. Replace many
PKCS#12 macros with real functions. Fix two unrelated ASN1 bugs:
asn1_check_tlen() would sometimes attempt to use 'ctx' when it was
NULL and ASN1_TYPE was not dereferenced properly in asn1_ex_c2i().
New ASN1 macro: DECLARE_ASN1_ITEM() which just declares the relevant
ASN1_ITEM and no wrapper functions.
[Steve Henson]
*) New functions or ASN1_item_d2i_fp() and ASN1_item_d2i_bio(). These
replace the old function pointer based I/O routines. Change most of
the *_d2i_bio() and *_d2i_fp() functions to use these.
[Steve Henson]
*) Enhance mkdef.pl to be more accepting about spacing in C preprocessor
lines, recognize more "algorithms" that can be deselected, and make
it complain about algorithm deselection that isn't recognised.
[Richard Levitte]
*) New ASN1 functions to handle dup, sign, verify, digest, pack and
unpack operations in terms of ASN1_ITEM. Modify existing wrappers
to use new functions. Add NO_ASN1_OLD which can be set to remove
some old style ASN1 functions: this can be used to determine if old
code will still work when these eventually go away.
[Steve Henson]
*) New extension functions for OCSP structures, these follow the
same conventions as certificates and CRLs.
[Steve Henson]
*) New function X509V3_add1_i2d(). This automatically encodes and
adds an extension. Its behaviour can be customised with various
flags to append, replace or delete. Various wrappers added for
certificates and CRLs.
[Steve Henson]
*) Fix to avoid calling the underlying ASN1 print routine when
an extension cannot be parsed. Correct a typo in the
OCSP_SERVICELOC extension. Tidy up print OCSP format.
[Steve Henson]
*) Make mkdef.pl parse some of the ASN1 macros and add appropriate
entries for variables.
[Steve Henson]
*) Add functionality to apps/openssl.c for detecting locking
problems: As the program is single-threaded, all we have
to do is register a locking callback using an array for
storing which locks are currently held by the program.
[Bodo Moeller]
*) Use a lock around the call to CRYPTO_get_ex_new_index() in
SSL_get_ex_data_X509_STORE_idx(), which is used in
ssl_verify_cert_chain() and thus can be called at any time
during TLS/SSL handshakes so that thread-safety is essential.
Unfortunately, the ex_data design is not at all suited
for multi-threaded use, so it probably should be abolished.
[Bodo Moeller]
*) Added Broadcom "ubsec" ENGINE to OpenSSL.
[Broadcom, tweaked and integrated by Geoff Thorpe]
*) Move common extension printing code to new function
X509V3_print_extensions(). Reorganise OCSP print routines and
implement some needed OCSP ASN1 functions. Add OCSP extensions.
[Steve Henson]
*) New function X509_signature_print() to remove duplication in some
print routines.
[Steve Henson]
*) Add a special meaning when SET OF and SEQUENCE OF flags are both
set (this was treated exactly the same as SET OF previously). This
is used to reorder the STACK representing the structure to match the
encoding. This will be used to get round a problem where a PKCS7
structure which was signed could not be verified because the STACK
order did not reflect the encoded order.
[Steve Henson]
*) Reimplement the OCSP ASN1 module using the new code.
[Steve Henson]
*) Update the X509V3 code to permit the use of an ASN1_ITEM structure
for its ASN1 operations. The old style function pointers still exist
for now but they will eventually go away.
[Steve Henson]
*) Merge in replacement ASN1 code from the ASN1 branch. This almost
completely replaces the old ASN1 functionality with a table driven
encoder and decoder which interprets an ASN1_ITEM structure describing
the ASN1 module. Compatibility with the existing ASN1 API (i2d,d2i) is
largely maintained. Almost all of the old asn1_mac.h macro based ASN1
has also been converted to the new form.
[Steve Henson]
*) Change BN_mod_exp_recp so that negative moduli are tolerated
(the sign is ignored). Similarly, ignore the sign in BN_MONT_CTX_set
so that BN_mod_exp_mont and BN_mod_exp_mont_word work
for negative moduli.
[Bodo Moeller]
*) Fix BN_uadd and BN_usub: Always return non-negative results instead
of not touching the result's sign bit.
[Bodo Moeller]
*) BN_div bugfix: If the result is 0, the sign (res->neg) must not be
set.
[Bodo Moeller]
*) Changed the LHASH code to use prototypes for callbacks, and created
macros to declare and implement thin (optionally static) functions
that provide type-safety and avoid function pointer casting for the
type-specific callbacks.
[Geoff Thorpe]
*) Added Kerberos Cipher Suites to be used with TLS, as written in
RFC 2712.
[Veers Staats <staatsvr@asc.hpc.mil>,
Jeffrey Altman <jaltman@columbia.edu>, via Richard Levitte]
*) Reformat the FAQ so the different questions and answers can be divided
in sections depending on the subject.
[Richard Levitte]
*) Have the zlib compression code load ZLIB.DLL dynamically under
Windows.
[Richard Levitte]
*) New function BN_mod_sqrt for computing square roots modulo a prime
(using the probabilistic Tonelli-Shanks algorithm unless
p == 3 (mod 4) or p == 5 (mod 8), which are cases that can
be handled deterministically).
[Lenka Fibikova <fibikova@exp-math.uni-essen.de>, Bodo Moeller]
*) Make BN_mod_inverse faster by explicitly handling small quotients
in the Euclid loop. (Speed gain about 20% for small moduli [256 or
512 bits], about 30% for larger ones [1024 or 2048 bits].)
[Bodo Moeller]
*) New function BN_kronecker.
[Bodo Moeller]
*) Fix BN_gcd so that it works on negative inputs; the result is
positive unless both parameters are zero.
Previously something reasonably close to an infinite loop was
possible because numbers could be growing instead of shrinking
in the implementation of Euclid's algorithm.
[Bodo Moeller]
*) Fix BN_is_word() and BN_is_one() macros to take into account the
sign of the number in question.
Fix BN_is_word(a,w) to work correctly for w == 0.
The old BN_is_word(a,w) macro is now called BN_abs_is_word(a,w)
because its test if the absolute value of 'a' equals 'w'.
Note that BN_abs_is_word does *not* handle w == 0 reliably;
it exists mostly for use in the implementations of BN_is_zero(),
BN_is_one(), and BN_is_word().
[Bodo Moeller]
*) New function BN_swap.
[Bodo Moeller]
*) Use BN_nnmod instead of BN_mod in crypto/bn/bn_exp.c so that
the exponentiation functions are more likely to produce reasonable
results on negative inputs.
[Bodo Moeller]
*) Change BN_mod_mul so that the result is always non-negative.
Previously, it could be negative if one of the factors was negative;
I don't think anyone really wanted that behaviour.
[Bodo Moeller]
*) Move BN_mod_... functions into new file crypto/bn/bn_mod.c
(except for exponentiation, which stays in crypto/bn/bn_exp.c,
and BN_mod_mul_reciprocal, which stays in crypto/bn/bn_recp.c)
and add new functions:
BN_nnmod
BN_mod_sqr
BN_mod_add
BN_mod_add_quick
BN_mod_sub
BN_mod_sub_quick
BN_mod_lshift1
BN_mod_lshift1_quick
BN_mod_lshift
BN_mod_lshift_quick
These functions always generate non-negative results.
BN_nnmod otherwise is like BN_mod (if BN_mod computes a remainder r
such that |m| < r < 0, BN_nnmod will output rem + |m| instead).
BN_mod_XXX_quick(r, a, [b,] m) generates the same result as
BN_mod_XXX(r, a, [b,] m, ctx), but requires that a [and b]
be reduced modulo m.
[Lenka Fibikova <fibikova@exp-math.uni-essen.de>, Bodo Moeller]
#if 0
The following entry accidentally appeared in the CHANGES file
distributed with OpenSSL 0.9.7. The modifications described in
it do *not* apply to OpenSSL 0.9.7.
*) Remove a few calls to bn_wexpand() in BN_sqr() (the one in there
was actually never needed) and in BN_mul(). The removal in BN_mul()
required a small change in bn_mul_part_recursive() and the addition
of the functions bn_cmp_part_words(), bn_sub_part_words() and
bn_add_part_words(), which do the same thing as bn_cmp_words(),
bn_sub_words() and bn_add_words() except they take arrays with
differing sizes.
[Richard Levitte]
#endif
*) In 'openssl passwd', verify passwords read from the terminal
unless the '-salt' option is used (which usually means that
verification would just waste user's time since the resulting
hash is going to be compared with some given password hash)
or the new '-noverify' option is used.
This is an incompatible change, but it does not affect
non-interactive use of 'openssl passwd' (passwords on the command
line, '-stdin' option, '-in ...' option) and thus should not
cause any problems.
[Bodo Moeller]
*) Remove all references to RSAref, since there's no more need for it.
[Richard Levitte]
*) Make DSO load along a path given through an environment variable
(SHLIB_PATH) with shl_load().
[Richard Levitte]
*) Constify the ENGINE code as a result of BIGNUM constification.
Also constify the RSA code and most things related to it. In a
few places, most notable in the depth of the ASN.1 code, ugly
casts back to non-const were required (to be solved at a later
time)
[Richard Levitte]
*) Make it so the openssl application has all engines loaded by default.
[Richard Levitte]
*) Constify the BIGNUM routines a little more.
[Richard Levitte]
*) Add the following functions:
ENGINE_load_cswift()
ENGINE_load_chil()
ENGINE_load_atalla()
ENGINE_load_nuron()
ENGINE_load_builtin_engines()
That way, an application can itself choose if external engines that
are built-in in OpenSSL shall ever be used or not. The benefit is
that applications won't have to be linked with libdl or other dso
libraries unless it's really needed.
Changed 'openssl engine' to load all engines on demand.
Changed the engine header files to avoid the duplication of some
declarations (they differed!).
[Richard Levitte]
*) 'openssl engine' can now list capabilities.
[Richard Levitte]
*) Better error reporting in 'openssl engine'.
[Richard Levitte]
*) Never call load_dh_param(NULL) in s_server.
[Bodo Moeller]
*) Add engine application. It can currently list engines by name and
identity, and test if they are actually available.
[Richard Levitte]
*) Improve RPM specification file by forcing symbolic linking and making
sure the installed documentation is also owned by root.root.
[Damien Miller <djm@mindrot.org>]
*) Give the OpenSSL applications more possibilities to make use of
keys (public as well as private) handled by engines.
[Richard Levitte]
*) Add OCSP code that comes from CertCo.
[Richard Levitte]
*) Add VMS support for the Rijndael code.
[Richard Levitte]
*) Added untested support for Nuron crypto accelerator.
[Ben Laurie]
*) Add support for external cryptographic devices. This code was
previously distributed separately as the "engine" branch.
[Geoff Thorpe, Richard Levitte]
*) Rework the filename-translation in the DSO code. It is now possible to
have far greater control over how a "name" is turned into a filename
depending on the operating environment and any oddities about the
different shared library filenames on each system.
[Geoff Thorpe]
*) Support threads on FreeBSD-elf in Configure.
[Richard Levitte]
*) Fix for SHA1 assembly problem with MASM: it produces
warnings about corrupt line number information when assembling
with debugging information. This is caused by the overlapping
of two sections.
[Bernd Matthes <mainbug@celocom.de>, Steve Henson]
*) NCONF changes.
NCONF_get_number() has no error checking at all. As a replacement,
NCONF_get_number_e() is defined (_e for "error checking") and is
promoted strongly. The old NCONF_get_number is kept around for
binary backward compatibility.
Make it possible for methods to load from something other than a BIO,
by providing a function pointer that is given a name instead of a BIO.
For example, this could be used to load configuration data from an
LDAP server.
[Richard Levitte]
*) Fix for non blocking accept BIOs. Added new I/O special reason
BIO_RR_ACCEPT to cover this case. Previously use of accept BIOs
with non blocking I/O was not possible because no retry code was
implemented. Also added new SSL code SSL_WANT_ACCEPT to cover
this case.
[Steve Henson]
*) Added the beginnings of Rijndael support.
[Ben Laurie]
*) Fix for bug in DirectoryString mask setting. Add support for
X509_NAME_print_ex() in 'req' and X509_print_ex() function
to allow certificate printing to more controllable, additional
'certopt' option to 'x509' to allow new printing options to be
set.
[Steve Henson]
*) Clean old EAY MD5 hack from e_os.h.
[Richard Levitte]
Changes between 0.9.6l and 0.9.6m [17 Mar 2004]
*) Fix null-pointer assignment in do_change_cipher_spec() revealed
by using the Codenomicon TLS Test Tool (CVE-2004-0079)
[Joe Orton, Steve Henson]
Changes between 0.9.6k and 0.9.6l [04 Nov 2003]
*) Fix additional bug revealed by the NISCC test suite:
Stop bug triggering large recursion when presented with
certain ASN.1 tags (CVE-2003-0851)
[Steve Henson]
Changes between 0.9.6j and 0.9.6k [30 Sep 2003]
*) Fix various bugs revealed by running the NISCC test suite:
Stop out of bounds reads in the ASN1 code when presented with
invalid tags (CVE-2003-0543 and CVE-2003-0544).
If verify callback ignores invalid public key errors don't try to check
certificate signature with the NULL public key.
[Steve Henson]
*) In ssl3_accept() (ssl/s3_srvr.c) only accept a client certificate
if the server requested one: as stated in TLS 1.0 and SSL 3.0
specifications.
[Steve Henson]
*) In ssl3_get_client_hello() (ssl/s3_srvr.c), tolerate additional
extra data after the compression methods not only for TLS 1.0
but also for SSL 3.0 (as required by the specification).
[Bodo Moeller; problem pointed out by Matthias Loepfe]
*) Change X509_certificate_type() to mark the key as exported/exportable
when it's 512 *bits* long, not 512 bytes.
[Richard Levitte]
Changes between 0.9.6i and 0.9.6j [10 Apr 2003]
*) Countermeasure against the Klima-Pokorny-Rosa extension of
Bleichbacher's attack on PKCS #1 v1.5 padding: treat
a protocol version number mismatch like a decryption error
in ssl3_get_client_key_exchange (ssl/s3_srvr.c).
[Bodo Moeller]
*) Turn on RSA blinding by default in the default implementation
to avoid a timing attack. Applications that don't want it can call
RSA_blinding_off() or use the new flag RSA_FLAG_NO_BLINDING.
They would be ill-advised to do so in most cases.
[Ben Laurie, Steve Henson, Geoff Thorpe, Bodo Moeller]
*) Change RSA blinding code so that it works when the PRNG is not
seeded (in this case, the secret RSA exponent is abused as
an unpredictable seed -- if it is not unpredictable, there
is no point in blinding anyway). Make RSA blinding thread-safe
by remembering the creator's thread ID in rsa->blinding and
having all other threads use local one-time blinding factors
(this requires more computation than sharing rsa->blinding, but
avoids excessive locking; and if an RSA object is not shared
between threads, blinding will still be very fast).
[Bodo Moeller]
Changes between 0.9.6h and 0.9.6i [19 Feb 2003]
*) In ssl3_get_record (ssl/s3_pkt.c), minimize information leaked
via timing by performing a MAC computation even if incorrect
block cipher padding has been found. This is a countermeasure
against active attacks where the attacker has to distinguish
between bad padding and a MAC verification error. (CVE-2003-0078)
[Bodo Moeller; problem pointed out by Brice Canvel (EPFL),
Alain Hiltgen (UBS), Serge Vaudenay (EPFL), and
Martin Vuagnoux (EPFL, Ilion)]
Changes between 0.9.6g and 0.9.6h [5 Dec 2002]
*) New function OPENSSL_cleanse(), which is used to cleanse a section of
memory from it's contents. This is done with a counter that will
place alternating values in each byte. This can be used to solve
two issues: 1) the removal of calls to memset() by highly optimizing
compilers, and 2) cleansing with other values than 0, since those can
be read through on certain media, for example a swap space on disk.
[Geoff Thorpe]
*) Bugfix: client side session caching did not work with external caching,
because the session->cipher setting was not restored when reloading
from the external cache. This problem was masked, when
SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG (part of SSL_OP_ALL) was set.
(Found by Steve Haslam <steve@araqnid.ddts.net>.)
[Lutz Jaenicke]
*) Fix client_certificate (ssl/s2_clnt.c): The permissible total
length of the REQUEST-CERTIFICATE message is 18 .. 34, not 17 .. 33.
[Zeev Lieber <zeev-l@yahoo.com>]
*) Undo an undocumented change introduced in 0.9.6e which caused
repeated calls to OpenSSL_add_all_ciphers() and
OpenSSL_add_all_digests() to be ignored, even after calling
EVP_cleanup().
[Richard Levitte]
*) Change the default configuration reader to deal with last line not
being properly terminated.
[Richard Levitte]
*) Change X509_NAME_cmp() so it applies the special rules on handling
DN values that are of type PrintableString, as well as RDNs of type
emailAddress where the value has the type ia5String.
[stefank@valicert.com via Richard Levitte]
*) Add a SSL_SESS_CACHE_NO_INTERNAL_STORE flag to take over half
the job SSL_SESS_CACHE_NO_INTERNAL_LOOKUP was inconsistently
doing, define a new flag (SSL_SESS_CACHE_NO_INTERNAL) to be
the bitwise-OR of the two for use by the majority of applications
wanting this behaviour, and update the docs. The documented
behaviour and actual behaviour were inconsistent and had been
changing anyway, so this is more a bug-fix than a behavioural
change.
[Geoff Thorpe, diagnosed by Nadav Har'El]
*) Don't impose a 16-byte length minimum on session IDs in ssl/s3_clnt.c
(the SSL 3.0 and TLS 1.0 specifications allow any length up to 32 bytes).
[Bodo Moeller]
*) Fix initialization code race conditions in
SSLv23_method(), SSLv23_client_method(), SSLv23_server_method(),
SSLv2_method(), SSLv2_client_method(), SSLv2_server_method(),
SSLv3_method(), SSLv3_client_method(), SSLv3_server_method(),
TLSv1_method(), TLSv1_client_method(), TLSv1_server_method(),
ssl2_get_cipher_by_char(),
ssl3_get_cipher_by_char().
[Patrick McCormick <patrick@tellme.com>, Bodo Moeller]
*) Reorder cleanup sequence in SSL_CTX_free(): only remove the ex_data after
the cached sessions are flushed, as the remove_cb() might use ex_data
contents. Bug found by Sam Varshavchik <mrsam@courier-mta.com>
(see [openssl.org #212]).
[Geoff Thorpe, Lutz Jaenicke]
*) Fix typo in OBJ_txt2obj which incorrectly passed the content
length, instead of the encoding length to d2i_ASN1_OBJECT.
[Steve Henson]
Changes between 0.9.6f and 0.9.6g [9 Aug 2002]
*) [In 0.9.6g-engine release:]
Fix crypto/engine/vendor_defns/cswift.h for WIN32 (use '_stdcall').
[Lynn Gazis <lgazis@rainbow.com>]
Changes between 0.9.6e and 0.9.6f [8 Aug 2002]
*) Fix ASN1 checks. Check for overflow by comparing with LONG_MAX
and get fix the header length calculation.
[Florian Weimer <Weimer@CERT.Uni-Stuttgart.DE>,
Alon Kantor <alonk@checkpoint.com> (and others),
Steve Henson]
*) Use proper error handling instead of 'assertions' in buffer
overflow checks added in 0.9.6e. This prevents DoS (the
assertions could call abort()).
[Arne Ansper <arne@ats.cyber.ee>, Bodo Moeller]
Changes between 0.9.6d and 0.9.6e [30 Jul 2002]
*) Add various sanity checks to asn1_get_length() to reject
the ASN1 length bytes if they exceed sizeof(long), will appear
negative or the content length exceeds the length of the
supplied buffer.
[Steve Henson, Adi Stav <stav@mercury.co.il>, James Yonan <jim@ntlp.com>]
*) Fix cipher selection routines: ciphers without encryption had no flags
for the cipher strength set and where therefore not handled correctly
by the selection routines (PR #130).
[Lutz Jaenicke]
*) Fix EVP_dsa_sha macro.
[Nils Larsch]
*) New option
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS
for disabling the SSL 3.0/TLS 1.0 CBC vulnerability countermeasure
that was added in OpenSSL 0.9.6d.
As the countermeasure turned out to be incompatible with some
broken SSL implementations, the new option is part of SSL_OP_ALL.
SSL_OP_ALL is usually employed when compatibility with weird SSL
implementations is desired (e.g. '-bugs' option to 's_client' and
's_server'), so the new option is automatically set in many
applications.
[Bodo Moeller]
*) Changes in security patch:
Changes marked "(CHATS)" were sponsored by the Defense Advanced
Research Projects Agency (DARPA) and Air Force Research Laboratory,
Air Force Materiel Command, USAF, under agreement number
F30602-01-2-0537.
*) Add various sanity checks to asn1_get_length() to reject
the ASN1 length bytes if they exceed sizeof(long), will appear
negative or the content length exceeds the length of the
supplied buffer. (CVE-2002-0659)
[Steve Henson, Adi Stav <stav@mercury.co.il>, James Yonan <jim@ntlp.com>]
*) Assertions for various potential buffer overflows, not known to
happen in practice.
[Ben Laurie (CHATS)]
*) Various temporary buffers to hold ASCII versions of integers were
too small for 64 bit platforms. (CVE-2002-0655)
[Matthew Byng-Maddick <mbm@aldigital.co.uk> and Ben Laurie (CHATS)>
*) Remote buffer overflow in SSL3 protocol - an attacker could
supply an oversized session ID to a client. (CVE-2002-0656)
[Ben Laurie (CHATS)]
*) Remote buffer overflow in SSL2 protocol - an attacker could
supply an oversized client master key. (CVE-2002-0656)
[Ben Laurie (CHATS)]
Changes between 0.9.6c and 0.9.6d [9 May 2002]
*) Fix crypto/asn1/a_sign.c so that 'parameters' is omitted (not
encoded as NULL) with id-dsa-with-sha1.
[Nils Larsch <nla@trustcenter.de>; problem pointed out by Bodo Moeller]
*) Check various X509_...() return values in apps/req.c.
[Nils Larsch <nla@trustcenter.de>]
*) Fix BASE64 decode (EVP_DecodeUpdate) for data with CR/LF ended lines:
an end-of-file condition would erroneously be flagged, when the CRLF
was just at the end of a processed block. The bug was discovered when
processing data through a buffering memory BIO handing the data to a
BASE64-decoding BIO. Bug fund and patch submitted by Pavel Tsekov
<ptsekov@syntrex.com> and Nedelcho Stanev.
[Lutz Jaenicke]
*) Implement a countermeasure against a vulnerability recently found
in CBC ciphersuites in SSL 3.0/TLS 1.0: Send an empty fragment
before application data chunks to avoid the use of known IVs
with data potentially chosen by the attacker.
[Bodo Moeller]
*) Fix length checks in ssl3_get_client_hello().
[Bodo Moeller]
*) TLS/SSL library bugfix: use s->s3->in_read_app_data differently
to prevent ssl3_read_internal() from incorrectly assuming that
ssl3_read_bytes() found application data while handshake
processing was enabled when in fact s->s3->in_read_app_data was
merely automatically cleared during the initial handshake.
[Bodo Moeller; problem pointed out by Arne Ansper <arne@ats.cyber.ee>]
*) Fix object definitions for Private and Enterprise: they were not
recognized in their shortname (=lowercase) representation. Extend
obj_dat.pl to issue an error when using undefined keywords instead
of silently ignoring the problem (Svenning Sorensen
<sss@sss.dnsalias.net>).
[Lutz Jaenicke]
*) Fix DH_generate_parameters() so that it works for 'non-standard'
generators, i.e. generators other than 2 and 5. (Previously, the
code did not properly initialise the 'add' and 'rem' values to
BN_generate_prime().)
In the new general case, we do not insist that 'generator' is
actually a primitive root: This requirement is rather pointless;
a generator of the order-q subgroup is just as good, if not
better.
[Bodo Moeller]
*) Map new X509 verification errors to alerts. Discovered and submitted by
Tom Wu <tom@arcot.com>.
[Lutz Jaenicke]
*) Fix ssl3_pending() (ssl/s3_lib.c) to prevent SSL_pending() from
returning non-zero before the data has been completely received
when using non-blocking I/O.
[Bodo Moeller; problem pointed out by John Hughes]
*) Some of the ciphers missed the strength entry (SSL_LOW etc).
[Ben Laurie, Lutz Jaenicke]
*) Fix bug in SSL_clear(): bad sessions were not removed (found by
Yoram Zahavi <YoramZ@gilian.com>).
[Lutz Jaenicke]
*) Add information about CygWin 1.3 and on, and preserve proper
configuration for the versions before that.
[Corinna Vinschen <vinschen@redhat.com> and Richard Levitte]
*) Make removal from session cache (SSL_CTX_remove_session()) more robust:
check whether we deal with a copy of a session and do not delete from
the cache in this case. Problem reported by "Izhar Shoshani Levi"
<izhar@checkpoint.com>.
[Lutz Jaenicke]
*) Do not store session data into the internal session cache, if it
is never intended to be looked up (SSL_SESS_CACHE_NO_INTERNAL_LOOKUP
flag is set). Proposed by Aslam <aslam@funk.com>.
[Lutz Jaenicke]
*) Have ASN1_BIT_STRING_set_bit() really clear a bit when the requested
value is 0.
[Richard Levitte]
*) [In 0.9.6d-engine release:]
Fix a crashbug and a logic bug in hwcrhk_load_pubkey().
[Toomas Kiisk <vix@cyber.ee> via Richard Levitte]
*) Add the configuration target linux-s390x.
[Neale Ferguson <Neale.Ferguson@SoftwareAG-USA.com> via Richard Levitte]
*) The earlier bugfix for the SSL3_ST_SW_HELLO_REQ_C case of
ssl3_accept (ssl/s3_srvr.c) incorrectly used a local flag
variable as an indication that a ClientHello message has been
received. As the flag value will be lost between multiple
invocations of ssl3_accept when using non-blocking I/O, the
function may not be aware that a handshake has actually taken
place, thus preventing a new session from being added to the
session cache.
To avoid this problem, we now set s->new_session to 2 instead of
using a local variable.
[Lutz Jaenicke, Bodo Moeller]
*) Bugfix: Return -1 from ssl3_get_server_done (ssl3/s3_clnt.c)
if the SSL_R_LENGTH_MISMATCH error is detected.
[Geoff Thorpe, Bodo Moeller]
*) New 'shared_ldflag' column in Configure platform table.
[Richard Levitte]
*) Fix EVP_CIPHER_mode macro.
["Dan S. Camper" <dan@bti.net>]
*) Fix ssl3_read_bytes (ssl/s3_pkt.c): To ignore messages of unknown
type, we must throw them away by setting rr->length to 0.
[D P Chang <dpc@qualys.com>]
Changes between 0.9.6b and 0.9.6c [21 dec 2001]
*) Fix BN_rand_range bug pointed out by Dominikus Scherkl
<Dominikus.Scherkl@biodata.com>. (The previous implementation
worked incorrectly for those cases where range = 10..._2 and
3*range is two bits longer than range.)
[Bodo Moeller]
*) Only add signing time to PKCS7 structures if it is not already
present.
[Steve Henson]
*) Fix crypto/objects/objects.h: "ld-ce" should be "id-ce",
OBJ_ld_ce should be OBJ_id_ce.
Also some ip-pda OIDs in crypto/objects/objects.txt were
incorrect (cf. RFC 3039).
[Matt Cooper, Frederic Giudicelli, Bodo Moeller]
*) Release CRYPTO_LOCK_DYNLOCK when CRYPTO_destroy_dynlockid()
returns early because it has nothing to do.
[Andy Schneider <andy.schneider@bjss.co.uk>]
*) [In 0.9.6c-engine release:]
Fix mutex callback return values in crypto/engine/hw_ncipher.c.
[Andy Schneider <andy.schneider@bjss.co.uk>]
*) [In 0.9.6c-engine release:]
Add support for Cryptographic Appliance's keyserver technology.
(Use engine 'keyclient')
[Cryptographic Appliances and Geoff Thorpe]
*) Add a configuration entry for OS/390 Unix. The C compiler 'c89'
is called via tools/c89.sh because arguments have to be
rearranged (all '-L' options must appear before the first object
modules).
[Richard Shapiro <rshapiro@abinitio.com>]
*) [In 0.9.6c-engine release:]
Add support for Broadcom crypto accelerator cards, backported
from 0.9.7.
[Broadcom, Nalin Dahyabhai <nalin@redhat.com>, Mark Cox]
*) [In 0.9.6c-engine release:]
Add support for SureWare crypto accelerator cards from
Baltimore Technologies. (Use engine 'sureware')
[Baltimore Technologies and Mark Cox]
*) [In 0.9.6c-engine release:]
Add support for crypto accelerator cards from Accelerated
Encryption Processing, www.aep.ie. (Use engine 'aep')
[AEP Inc. and Mark Cox]
*) Add a configuration entry for gcc on UnixWare.
[Gary Benson <gbenson@redhat.com>]
*) Change ssl/s2_clnt.c and ssl/s2_srvr.c so that received handshake
messages are stored in a single piece (fixed-length part and
variable-length part combined) and fix various bugs found on the way.
[Bodo Moeller]
*) Disable caching in BIO_gethostbyname(), directly use gethostbyname()
instead. BIO_gethostbyname() does not know what timeouts are
appropriate, so entries would stay in cache even when they have
become invalid.
[Bodo Moeller; problem pointed out by Rich Salz <rsalz@zolera.com>
*) Change ssl23_get_client_hello (ssl/s23_srvr.c) behaviour when
faced with a pathologically small ClientHello fragment that does
not contain client_version: Instead of aborting with an error,
simply choose the highest available protocol version (i.e.,
TLS 1.0 unless it is disabled). In practice, ClientHello
messages are never sent like this, but this change gives us
strictly correct behaviour at least for TLS.
[Bodo Moeller]
*) Fix SSL handshake functions and SSL_clear() such that SSL_clear()
never resets s->method to s->ctx->method when called from within
one of the SSL handshake functions.
[Bodo Moeller; problem pointed out by Niko Baric]
*) In ssl3_get_client_hello (ssl/s3_srvr.c), generate a fatal alert
(sent using the client's version number) if client_version is
smaller than the protocol version in use. Also change
ssl23_get_client_hello (ssl/s23_srvr.c) to select TLS 1.0 if
the client demanded SSL 3.0 but only TLS 1.0 is enabled; then
the client will at least see that alert.
[Bodo Moeller]
*) Fix ssl3_get_message (ssl/s3_both.c) to handle message fragmentation
correctly.
[Bodo Moeller]
*) Avoid infinite loop in ssl3_get_message (ssl/s3_both.c) if a
client receives HelloRequest while in a handshake.
[Bodo Moeller; bug noticed by Andy Schneider <andy.schneider@bjss.co.uk>]
*) Bugfix in ssl3_accept (ssl/s3_srvr.c): Case SSL3_ST_SW_HELLO_REQ_C
should end in 'break', not 'goto end' which circumvents various
cleanups done in state SSL_ST_OK. But session related stuff
must be disabled for SSL_ST_OK in the case that we just sent a
HelloRequest.
Also avoid some overhead by not calling ssl_init_wbio_buffer()
before just sending a HelloRequest.
[Bodo Moeller, Eric Rescorla <ekr@rtfm.com>]
*) Fix ssl/s3_enc.c, ssl/t1_enc.c and ssl/s3_pkt.c so that we don't
reveal whether illegal block cipher padding was found or a MAC
verification error occurred. (Neither SSLerr() codes nor alerts
are directly visible to potential attackers, but the information
may leak via logfiles.)
Similar changes are not required for the SSL 2.0 implementation
because the number of padding bytes is sent in clear for SSL 2.0,
and the extra bytes are just ignored. However ssl/s2_pkt.c
failed to verify that the purported number of padding bytes is in
the legal range.
[Bodo Moeller]
*) Add OpenUNIX-8 support including shared libraries
(Boyd Lynn Gerber <gerberb@zenez.com>).
[Lutz Jaenicke]
*) Improve RSA_padding_check_PKCS1_OAEP() check again to avoid
'wristwatch attack' using huge encoding parameters (cf.
James H. Manger's CRYPTO 2001 paper). Note that the
RSA_PKCS1_OAEP_PADDING case of RSA_private_decrypt() does not use
encoding parameters and hence was not vulnerable.
[Bodo Moeller]
*) BN_sqr() bug fix.
[Ulf Möller, reported by Jim Ellis <jim.ellis@cavium.com>]
*) Rabin-Miller test analyses assume uniformly distributed witnesses,
so use BN_pseudo_rand_range() instead of using BN_pseudo_rand()
followed by modular reduction.
[Bodo Moeller; pointed out by Adam Young <AYoung1@NCSUS.JNJ.COM>]
*) Add BN_pseudo_rand_range() with obvious functionality: BN_rand_range()
equivalent based on BN_pseudo_rand() instead of BN_rand().
[Bodo Moeller]
*) s3_srvr.c: allow sending of large client certificate lists (> 16 kB).
This function was broken, as the check for a new client hello message
to handle SGC did not allow these large messages.
(Tracked down by "Douglas E. Engert" <deengert@anl.gov>.)
[Lutz Jaenicke]
*) Add alert descriptions for TLSv1 to SSL_alert_desc_string[_long]().
[Lutz Jaenicke]
*) Fix buggy behaviour of BIO_get_num_renegotiates() and BIO_ctrl()
for BIO_C_GET_WRITE_BUF_SIZE ("Stephen Hinton" <shinton@netopia.com>).
[Lutz Jaenicke]
*) Rework the configuration and shared library support for Tru64 Unix.
The configuration part makes use of modern compiler features and
still retains old compiler behavior for those that run older versions
of the OS. The shared library support part includes a variant that
uses the RPATH feature, and is available through the special
configuration target "alpha-cc-rpath", which will never be selected
automatically.
[Tim Mooney <mooney@dogbert.cc.ndsu.NoDak.edu> via Richard Levitte]
*) In ssl3_get_key_exchange (ssl/s3_clnt.c), call ssl3_get_message()
with the same message size as in ssl3_get_certificate_request().
Otherwise, if no ServerKeyExchange message occurs, CertificateRequest
messages might inadvertently be reject as too long.
[Petr Lampa <lampa@fee.vutbr.cz>]
*) Enhanced support for IA-64 Unix platforms (well, Linux and HP-UX).
[Andy Polyakov]
*) Modified SSL library such that the verify_callback that has been set
specificly for an SSL object with SSL_set_verify() is actually being
used. Before the change, a verify_callback set with this function was
ignored and the verify_callback() set in the SSL_CTX at the time of
the call was used. New function X509_STORE_CTX_set_verify_cb() introduced
to allow the necessary settings.
[Lutz Jaenicke]
*) Initialize static variable in crypto/dsa/dsa_lib.c and crypto/dh/dh_lib.c
explicitly to NULL, as at least on Solaris 8 this seems not always to be
done automatically (in contradiction to the requirements of the C
standard). This made problems when used from OpenSSH.
[Lutz Jaenicke]
*) In OpenSSL 0.9.6a and 0.9.6b, crypto/dh/dh_key.c ignored
dh->length and always used
BN_rand_range(priv_key, dh->p).
BN_rand_range() is not necessary for Diffie-Hellman, and this
specific range makes Diffie-Hellman unnecessarily inefficient if
dh->length (recommended exponent length) is much smaller than the
length of dh->p. We could use BN_rand_range() if the order of
the subgroup was stored in the DH structure, but we only have
dh->length.
So switch back to
BN_rand(priv_key, l, ...)
where 'l' is dh->length if this is defined, or BN_num_bits(dh->p)-1
otherwise.
[Bodo Moeller]
*) In
RSA_eay_public_encrypt
RSA_eay_private_decrypt
RSA_eay_private_encrypt (signing)
RSA_eay_public_decrypt (signature verification)
(default implementations for RSA_public_encrypt,
RSA_private_decrypt, RSA_private_encrypt, RSA_public_decrypt),
always reject numbers >= n.
[Bodo Moeller]
*) In crypto/rand/md_rand.c, use a new short-time lock CRYPTO_LOCK_RAND2
to synchronize access to 'locking_thread'. This is necessary on
systems where access to 'locking_thread' (an 'unsigned long'
variable) is not atomic.
[Bodo Moeller]
*) In crypto/rand/md_rand.c, set 'locking_thread' to current thread's ID
*before* setting the 'crypto_lock_rand' flag. The previous code had
a race condition if 0 is a valid thread ID.
[Travis Vitek <vitek@roguewave.com>]
*) Add support for shared libraries under Irix.
[Albert Chin-A-Young <china@thewrittenword.com>]
*) Add configuration option to build on Linux on both big-endian and
little-endian MIPS.
[Ralf Baechle <ralf@uni-koblenz.de>]
*) Add the possibility to create shared libraries on HP-UX.
[Richard Levitte]
Changes between 0.9.6a and 0.9.6b [9 Jul 2001]
*) Change ssleay_rand_bytes (crypto/rand/md_rand.c)
to avoid a SSLeay/OpenSSL PRNG weakness pointed out by
Markku-Juhani O. Saarinen <markku-juhani.saarinen@nokia.com>:
PRNG state recovery was possible based on the output of
one PRNG request appropriately sized to gain knowledge on
'md' followed by enough consecutive 1-byte PRNG requests
to traverse all of 'state'.
1. When updating 'md_local' (the current thread's copy of 'md')
during PRNG output generation, hash all of the previous
'md_local' value, not just the half used for PRNG output.
2. Make the number of bytes from 'state' included into the hash
independent from the number of PRNG bytes requested.
The first measure alone would be sufficient to avoid
Markku-Juhani's attack. (Actually it had never occurred
to me that the half of 'md_local' used for chaining was the
half from which PRNG output bytes were taken -- I had always
assumed that the secret half would be used.) The second
measure makes sure that additional data from 'state' is never
mixed into 'md_local' in small portions; this heuristically
further strengthens the PRNG.
[Bodo Moeller]
*) Fix crypto/bn/asm/mips3.s.
[Andy Polyakov]
*) When only the key is given to "enc", the IV is undefined. Print out
an error message in this case.
[Lutz Jaenicke]
*) Handle special case when X509_NAME is empty in X509 printing routines.
[Steve Henson]
*) In dsa_do_verify (crypto/dsa/dsa_ossl.c), verify that r and s are
positive and less than q.
[Bodo Moeller]
*) Don't change *pointer in CRYPTO_add_lock() is add_lock_callback is
used: it isn't thread safe and the add_lock_callback should handle
that itself.
[Paul Rose <Paul.Rose@bridge.com>]
*) Verify that incoming data obeys the block size in
ssl3_enc (ssl/s3_enc.c) and tls1_enc (ssl/t1_enc.c).
[Bodo Moeller]
*) Fix OAEP check.
[Ulf Möller, Bodo Möller]
*) The countermeasure against Bleichbacher's attack on PKCS #1 v1.5
RSA encryption was accidentally removed in s3_srvr.c in OpenSSL 0.9.5
when fixing the server behaviour for backwards-compatible 'client
hello' messages. (Note that the attack is impractical against
SSL 3.0 and TLS 1.0 anyway because length and version checking
means that the probability of guessing a valid ciphertext is
around 2^-40; see section 5 in Bleichenbacher's CRYPTO '98
paper.)
Before 0.9.5, the countermeasure (hide the error by generating a
random 'decryption result') did not work properly because
ERR_clear_error() was missing, meaning that SSL_get_error() would
detect the supposedly ignored error.
Both problems are now fixed.
[Bodo Moeller]
*) In crypto/bio/bf_buff.c, increase DEFAULT_BUFFER_SIZE to 4096
(previously it was 1024).
[Bodo Moeller]
*) Fix for compatibility mode trust settings: ignore trust settings
unless some valid trust or reject settings are present.
[Steve Henson]
*) Fix for blowfish EVP: its a variable length cipher.
[Steve Henson]
*) Fix various bugs related to DSA S/MIME verification. Handle missing
parameters in DSA public key structures and return an error in the
DSA routines if parameters are absent.
[Steve Henson]
*) In versions up to 0.9.6, RAND_file_name() resorted to file ".rnd"
in the current directory if neither $RANDFILE nor $HOME was set.
RAND_file_name() in 0.9.6a returned NULL in this case. This has
caused some confusion to Windows users who haven't defined $HOME.
Thus RAND_file_name() is changed again: e_os.h can define a
DEFAULT_HOME, which will be used if $HOME is not set.
For Windows, we use "C:"; on other platforms, we still require
environment variables.
*) Move 'if (!initialized) RAND_poll()' into regions protected by
CRYPTO_LOCK_RAND. This is not strictly necessary, but avoids
having multiple threads call RAND_poll() concurrently.
[Bodo Moeller]
*) In crypto/rand/md_rand.c, replace 'add_do_not_lock' flag by a
combination of a flag and a thread ID variable.
Otherwise while one thread is in ssleay_rand_bytes (which sets the
flag), *other* threads can enter ssleay_add_bytes without obeying
the CRYPTO_LOCK_RAND lock (and may even illegally release the lock
that they do not hold after the first thread unsets add_do_not_lock).
[Bodo Moeller]
*) Change bctest again: '-x' expressions are not available in all
versions of 'test'.
[Bodo Moeller]
Changes between 0.9.6 and 0.9.6a [5 Apr 2001]
*) Fix a couple of memory leaks in PKCS7_dataDecode()
[Steve Henson, reported by Heyun Zheng <hzheng@atdsprint.com>]
*) Change Configure and Makefiles to provide EXE_EXT, which will contain
the default extension for executables, if any. Also, make the perl
scripts that use symlink() to test if it really exists and use "cp"
if it doesn't. All this made OpenSSL compilable and installable in
CygWin.
[Richard Levitte]
*) Fix for asn1_GetSequence() for indefinite length constructed data.
If SEQUENCE is length is indefinite just set c->slen to the total
amount of data available.
[Steve Henson, reported by shige@FreeBSD.org]
[This change does not apply to 0.9.7.]
*) Change bctest to avoid here-documents inside command substitution
(workaround for FreeBSD /bin/sh bug).
For compatibility with Ultrix, avoid shell functions (introduced
in the bctest version that searches along $PATH).
[Bodo Moeller]
*) Rename 'des_encrypt' to 'des_encrypt1'. This avoids the clashes
with des_encrypt() defined on some operating systems, like Solaris
and UnixWare.
[Richard Levitte]
*) Check the result of RSA-CRT (see D. Boneh, R. DeMillo, R. Lipton:
On the Importance of Eliminating Errors in Cryptographic
Computations, J. Cryptology 14 (2001) 2, 101-119,
http://theory.stanford.edu/~dabo/papers/faults.ps.gz).
[Ulf Moeller]
*) MIPS assembler BIGNUM division bug fix.
[Andy Polyakov]
*) Disabled incorrect Alpha assembler code.
[Richard Levitte]
*) Fix PKCS#7 decode routines so they correctly update the length
after reading an EOC for the EXPLICIT tag.
[Steve Henson]
[This change does not apply to 0.9.7.]
*) Fix bug in PKCS#12 key generation routines. This was triggered
if a 3DES key was generated with a 0 initial byte. Include
PKCS12_BROKEN_KEYGEN compilation option to retain the old
(but broken) behaviour.
[Steve Henson]
*) Enhance bctest to search for a working bc along $PATH and print
it when found.
[Tim Rice <tim@multitalents.net> via Richard Levitte]
*) Fix memory leaks in err.c: free err_data string if necessary;
don't write to the wrong index in ERR_set_error_data.
[Bodo Moeller]
*) Implement ssl23_peek (analogous to ssl23_read), which previously
did not exist.
[Bodo Moeller]
*) Replace rdtsc with _emit statements for VC++ version 5.
[Jeremy Cooper <jeremy@baymoo.org>]
*) Make it possible to reuse SSLv2 sessions.
[Richard Levitte]
*) In copy_email() check for >= 0 as a return value for
X509_NAME_get_index_by_NID() since 0 is a valid index.
[Steve Henson reported by Massimiliano Pala <madwolf@opensca.org>]
*) Avoid coredump with unsupported or invalid public keys by checking if
X509_get_pubkey() fails in PKCS7_verify(). Fix memory leak when
PKCS7_verify() fails with non detached data.
[Steve Henson]
*) Don't use getenv in library functions when run as setuid/setgid.
New function OPENSSL_issetugid().
[Ulf Moeller]
*) Avoid false positives in memory leak detection code (crypto/mem_dbg.c)
due to incorrect handling of multi-threading:
1. Fix timing glitch in the MemCheck_off() portion of CRYPTO_mem_ctrl().
2. Fix logical glitch in is_MemCheck_on() aka CRYPTO_is_mem_check_on().
3. Count how many times MemCheck_off() has been called so that
nested use can be treated correctly. This also avoids
inband-signalling in the previous code (which relied on the
assumption that thread ID 0 is impossible).
[Bodo Moeller]
*) Add "-rand" option also to s_client and s_server.
[Lutz Jaenicke]
*) Fix CPU detection on Irix 6.x.
[Kurt Hockenbury <khockenb@stevens-tech.edu> and
"Bruce W. Forsberg" <bruce.forsberg@baesystems.com>]
*) Fix X509_NAME bug which produced incorrect encoding if X509_NAME
was empty.
[Steve Henson]
[This change does not apply to 0.9.7.]
*) Use the cached encoding of an X509_NAME structure rather than
copying it. This is apparently the reason for the libsafe "errors"
but the code is actually correct.
[Steve Henson]
*) Add new function BN_rand_range(), and fix DSA_sign_setup() to prevent
Bleichenbacher's DSA attack.
Extend BN_[pseudo_]rand: As before, top=1 forces the highest two bits
to be set and top=0 forces the highest bit to be set; top=-1 is new
and leaves the highest bit random.
[Ulf Moeller, Bodo Moeller]
*) In the NCONF_...-based implementations for CONF_... queries
(crypto/conf/conf_lib.c), if the input LHASH is NULL, avoid using
a temporary CONF structure with the data component set to NULL
(which gives segmentation faults in lh_retrieve).
Instead, use NULL for the CONF pointer in CONF_get_string and
CONF_get_number (which may use environment variables) and directly
return NULL from CONF_get_section.
[Bodo Moeller]
*) Fix potential buffer overrun for EBCDIC.
[Ulf Moeller]
*) Tolerate nonRepudiation as being valid for S/MIME signing and certSign
keyUsage if basicConstraints absent for a CA.
[Steve Henson]
*) Make SMIME_write_PKCS7() write mail header values with a format that
is more generally accepted (no spaces before the semicolon), since
some programs can't parse those values properly otherwise. Also make
sure BIO's that break lines after each write do not create invalid
headers.
[Richard Levitte]
*) Make the CRL encoding routines work with empty SEQUENCE OF. The
macros previously used would not encode an empty SEQUENCE OF
and break the signature.
[Steve Henson]
[This change does not apply to 0.9.7.]
*) Zero the premaster secret after deriving the master secret in
DH ciphersuites.
[Steve Henson]
*) Add some EVP_add_digest_alias registrations (as found in
OpenSSL_add_all_digests()) to SSL_library_init()
aka OpenSSL_add_ssl_algorithms(). This provides improved
compatibility with peers using X.509 certificates
with unconventional AlgorithmIdentifier OIDs.
[Bodo Moeller]
*) Fix for Irix with NO_ASM.
["Bruce W. Forsberg" <bruce.forsberg@baesystems.com>]
*) ./config script fixes.
[Ulf Moeller, Richard Levitte]
*) Fix 'openssl passwd -1'.
[Bodo Moeller]
*) Change PKCS12_key_gen_asc() so it can cope with non null
terminated strings whose length is passed in the passlen
parameter, for example from PEM callbacks. This was done
by adding an extra length parameter to asc2uni().
[Steve Henson, reported by <oddissey@samsung.co.kr>]
*) Fix C code generated by 'openssl dsaparam -C': If a BN_bin2bn
call failed, free the DSA structure.
[Bodo Moeller]
*) Fix to uni2asc() to cope with zero length Unicode strings.
These are present in some PKCS#12 files.
[Steve Henson]
*) Increase s2->wbuf allocation by one byte in ssl2_new (ssl/s2_lib.c).
Otherwise do_ssl_write (ssl/s2_pkt.c) will write beyond buffer limits
when writing a 32767 byte record.
[Bodo Moeller; problem reported by Eric Day <eday@concentric.net>]
*) In RSA_eay_public_{en,ed}crypt and RSA_eay_mod_exp (rsa_eay.c),
obtain lock CRYPTO_LOCK_RSA before setting rsa->_method_mod_{n,p,q}.
(RSA objects have a reference count access to which is protected
by CRYPTO_LOCK_RSA [see rsa_lib.c, s3_srvr.c, ssl_cert.c, ssl_rsa.c],
so they are meant to be shared between threads.)
[Bodo Moeller, Geoff Thorpe; original patch submitted by
"Reddie, Steven" <Steven.Reddie@ca.com>]
*) Fix a deadlock in CRYPTO_mem_leaks().
[Bodo Moeller]
*) Use better test patterns in bntest.
[Ulf Möller]
*) rand_win.c fix for Borland C.
[Ulf Möller]
*) BN_rshift bugfix for n == 0.
[Bodo Moeller]
*) Add a 'bctest' script that checks for some known 'bc' bugs
so that 'make test' does not abort just because 'bc' is broken.
[Bodo Moeller]
*) Store verify_result within SSL_SESSION also for client side to
avoid potential security hole. (Re-used sessions on the client side
always resulted in verify_result==X509_V_OK, not using the original
result of the server certificate verification.)
[Lutz Jaenicke]
*) Fix ssl3_pending: If the record in s->s3->rrec is not of type
SSL3_RT_APPLICATION_DATA, return 0.
Similarly, change ssl2_pending to return 0 if SSL_in_init(s) is true.
[Bodo Moeller]
*) Fix SSL_peek:
Both ssl2_peek and ssl3_peek, which were totally broken in earlier
releases, have been re-implemented by renaming the previous
implementations of ssl2_read and ssl3_read to ssl2_read_internal
and ssl3_read_internal, respectively, and adding 'peek' parameters
to them. The new ssl[23]_{read,peek} functions are calls to
ssl[23]_read_internal with the 'peek' flag set appropriately.
A 'peek' parameter has also been added to ssl3_read_bytes, which
does the actual work for ssl3_read_internal.
[Bodo Moeller]
*) Initialise "ex_data" member of RSA/DSA/DH structures prior to calling
the method-specific "init()" handler. Also clean up ex_data after
calling the method-specific "finish()" handler. Previously, this was
happening the other way round.
[Geoff Thorpe]
*) Increase BN_CTX_NUM (the number of BIGNUMs in a BN_CTX) to 16.
The previous value, 12, was not always sufficient for BN_mod_exp().
[Bodo Moeller]
*) Make sure that shared libraries get the internal name engine with
the full version number and not just 0. This should mark the
shared libraries as not backward compatible. Of course, this should
be changed again when we can guarantee backward binary compatibility.
[Richard Levitte]
*) Fix typo in get_cert_by_subject() in by_dir.c
[Jean-Marc Desperrier <jean-marc.desperrier@certplus.com>]
*) Rework the system to generate shared libraries:
- Make note of the expected extension for the shared libraries and
if there is a need for symbolic links from for example libcrypto.so.0
to libcrypto.so.0.9.7. There is extended info in Configure for
that.
- Make as few rebuilds of the shared libraries as possible.
- Still avoid linking the OpenSSL programs with the shared libraries.
- When installing, install the shared libraries separately from the
static ones.
[Richard Levitte]
*) Fix SSL_CTX_set_read_ahead macro to actually use its argument.
Copy SSL_CTX's read_ahead flag to SSL object directly in SSL_new
and not in SSL_clear because the latter is also used by the
accept/connect functions; previously, the settings made by
SSL_set_read_ahead would be lost during the handshake.
[Bodo Moeller; problems reported by Anders Gertz <gertz@epact.se>]
*) Correct util/mkdef.pl to be selective about disabled algorithms.
Previously, it would create entries for disabled algorithms no
matter what.
[Richard Levitte]
*) Added several new manual pages for SSL_* function.
[Lutz Jaenicke]
Changes between 0.9.5a and 0.9.6 [24 Sep 2000]
*) In ssl23_get_client_hello, generate an error message when faced
with an initial SSL 3.0/TLS record that is too small to contain the
first two bytes of the ClientHello message, i.e. client_version.
(Note that this is a pathologic case that probably has never happened
in real life.) The previous approach was to use the version number
from the record header as a substitute; but our protocol choice
should not depend on that one because it is not authenticated
by the Finished messages.
[Bodo Moeller]
*) More robust randomness gathering functions for Windows.
[Jeffrey Altman <jaltman@columbia.edu>]
*) For compatibility reasons if the flag X509_V_FLAG_ISSUER_CHECK is
not set then we don't setup the error code for issuer check errors
to avoid possibly overwriting other errors which the callback does
handle. If an application does set the flag then we assume it knows
what it is doing and can handle the new informational codes
appropriately.
[Steve Henson]
*) Fix for a nasty bug in ASN1_TYPE handling. ASN1_TYPE is used for
a general "ANY" type, as such it should be able to decode anything
including tagged types. However it didn't check the class so it would
wrongly interpret tagged types in the same way as their universal
counterpart and unknown types were just rejected. Changed so that the
tagged and unknown types are handled in the same way as a SEQUENCE:
that is the encoding is stored intact. There is also a new type
"V_ASN1_OTHER" which is used when the class is not universal, in this
case we have no idea what the actual type is so we just lump them all
together.
[Steve Henson]
*) On VMS, stdout may very well lead to a file that is written to
in a record-oriented fashion. That means that every write() will
write a separate record, which will be read separately by the
programs trying to read from it. This can be very confusing.
The solution is to put a BIO filter in the way that will buffer
text until a linefeed is reached, and then write everything a
line at a time, so every record written will be an actual line,
not chunks of lines and not (usually doesn't happen, but I've
seen it once) several lines in one record. BIO_f_linebuffer() is
the answer.
Currently, it's a VMS-only method, because that's where it has
been tested well enough.
[Richard Levitte]
*) Remove 'optimized' squaring variant in BN_mod_mul_montgomery,
it can return incorrect results.
(Note: The buggy variant was not enabled in OpenSSL 0.9.5a,
but it was in 0.9.6-beta[12].)
[Bodo Moeller]
*) Disable the check for content being present when verifying detached
signatures in pk7_smime.c. Some versions of Netscape (wrongly)
include zero length content when signing messages.
[Steve Henson]
*) New BIO_shutdown_wr macro, which invokes the BIO_C_SHUTDOWN_WR
BIO_ctrl (for BIO pairs).
[Bodo Möller]
*) Add DSO method for VMS.
[Richard Levitte]
*) Bug fix: Montgomery multiplication could produce results with the
wrong sign.
[Ulf Möller]
*) Add RPM specification openssl.spec and modify it to build three
packages. The default package contains applications, application
documentation and run-time libraries. The devel package contains
include files, static libraries and function documentation. The
doc package contains the contents of the doc directory. The original
openssl.spec was provided by Damien Miller <djm@mindrot.org>.
[Richard Levitte]
*) Add a large number of documentation files for many SSL routines.
[Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE>]
*) Add a configuration entry for Sony News 4.
[NAKAJI Hiroyuki <nakaji@tutrp.tut.ac.jp>]
*) Don't set the two most significant bits to one when generating a
random number < q in the DSA library.
[Ulf Möller]
*) New SSL API mode 'SSL_MODE_AUTO_RETRY'. This disables the default
behaviour that SSL_read may result in SSL_ERROR_WANT_READ (even if
the underlying transport is blocking) if a handshake took place.
(The default behaviour is needed by applications such as s_client
and s_server that use select() to determine when to use SSL_read;
but for applications that know in advance when to expect data, it
just makes things more complicated.)
[Bodo Moeller]
*) Add RAND_egd_bytes(), which gives control over the number of bytes read
from EGD.
[Ben Laurie]
*) Add a few more EBCDIC conditionals that make `req' and `x509'
work better on such systems.
[Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>]
*) Add two demo programs for PKCS12_parse() and PKCS12_create().
Update PKCS12_parse() so it copies the friendlyName and the
keyid to the certificates aux info.
[Steve Henson]
*) Fix bug in PKCS7_verify() which caused an infinite loop
if there was more than one signature.
[Sven Uszpelkat <su@celocom.de>]
*) Major change in util/mkdef.pl to include extra information
about each symbol, as well as presenting variables as well
as functions. This change means that there's n more need
to rebuild the .num files when some algorithms are excluded.
[Richard Levitte]
*) Allow the verify time to be set by an application,
rather than always using the current time.
[Steve Henson]
*) Phase 2 verify code reorganisation. The certificate
verify code now looks up an issuer certificate by a
number of criteria: subject name, authority key id
and key usage. It also verifies self signed certificates
by the same criteria. The main comparison function is
X509_check_issued() which performs these checks.
Lot of changes were necessary in order to support this
without completely rewriting the lookup code.
Authority and subject key identifier are now cached.
The LHASH 'certs' is X509_STORE has now been replaced
by a STACK_OF(X509_OBJECT). This is mainly because an
LHASH can't store or retrieve multiple objects with
the same hash value.
As a result various functions (which were all internal
use only) have changed to handle the new X509_STORE
structure. This will break anything that messed round
with X509_STORE internally.
The functions X509_STORE_add_cert() now checks for an
exact match, rather than just subject name.
The X509_STORE API doesn't directly support the retrieval
of multiple certificates matching a given criteria, however
this can be worked round by performing a lookup first
(which will fill the cache with candidate certificates)
and then examining the cache for matches. This is probably
the best we can do without throwing out X509_LOOKUP
entirely (maybe later...).
The X509_VERIFY_CTX structure has been enhanced considerably.
All certificate lookup operations now go via a get_issuer()
callback. Although this currently uses an X509_STORE it
can be replaced by custom lookups. This is a simple way
to bypass the X509_STORE hackery necessary to make this
work and makes it possible to use more efficient techniques
in future. A very simple version which uses a simple
STACK for its trusted certificate store is also provided
using X509_STORE_CTX_trusted_stack().
The verify_cb() and verify() callbacks now have equivalents
in the X509_STORE_CTX structure.
X509_STORE_CTX also has a 'flags' field which can be used
to customise the verify behaviour.
[Steve Henson]
*) Add new PKCS#7 signing option PKCS7_NOSMIMECAP which
excludes S/MIME capabilities.
[Steve Henson]
*) When a certificate request is read in keep a copy of the
original encoding of the signed data and use it when outputting
again. Signatures then use the original encoding rather than
a decoded, encoded version which may cause problems if the
request is improperly encoded.
[Steve Henson]
*) For consistency with other BIO_puts implementations, call
buffer_write(b, ...) directly in buffer_puts instead of calling
BIO_write(b, ...).
In BIO_puts, increment b->num_write as in BIO_write.
[Peter.Sylvester@EdelWeb.fr]
*) Fix BN_mul_word for the case where the word is 0. (We have to use
BN_zero, we may not return a BIGNUM with an array consisting of
words set to zero.)
[Bodo Moeller]
*) Avoid calling abort() from within the library when problems are
detected, except if preprocessor symbols have been defined
(such as REF_CHECK, BN_DEBUG etc.).
[Bodo Moeller]
*) New openssl application 'rsautl'. This utility can be
used for low level RSA operations. DER public key
BIO/fp routines also added.
[Steve Henson]
*) New Configure entry and patches for compiling on QNX 4.
[Andreas Schneider <andreas@ds3.etech.fh-hamburg.de>]
*) A demo state-machine implementation was sponsored by
Nuron (http://www.nuron.com/) and is now available in
demos/state_machine.
[Ben Laurie]
*) New options added to the 'dgst' utility for signature
generation and verification.
[Steve Henson]
*) Unrecognized PKCS#7 content types are now handled via a
catch all ASN1_TYPE structure. This allows unsupported
types to be stored as a "blob" and an application can
encode and decode it manually.
[Steve Henson]
*) Fix various signed/unsigned issues to make a_strex.c
compile under VC++.
[Oscar Jacobsson <oscar.jacobsson@celocom.com>]
*) ASN1 fixes. i2d_ASN1_OBJECT was not returning the correct
length if passed a buffer. ASN1_INTEGER_to_BN failed
if passed a NULL BN and its argument was negative.
[Steve Henson, pointed out by Sven Heiberg <sven@tartu.cyber.ee>]
*) Modification to PKCS#7 encoding routines to output definite
length encoding. Since currently the whole structures are in
memory there's not real point in using indefinite length
constructed encoding. However if OpenSSL is compiled with
the flag PKCS7_INDEFINITE_ENCODING the old form is used.
[Steve Henson]
*) Added BIO_vprintf() and BIO_vsnprintf().
[Richard Levitte]
*) Added more prefixes to parse for in the strings written
through a logging bio, to cover all the levels that are available
through syslog. The prefixes are now:
PANIC, EMERG, EMR => LOG_EMERG
ALERT, ALR => LOG_ALERT
CRIT, CRI => LOG_CRIT
ERROR, ERR => LOG_ERR
WARNING, WARN, WAR => LOG_WARNING
NOTICE, NOTE, NOT => LOG_NOTICE
INFO, INF => LOG_INFO
DEBUG, DBG => LOG_DEBUG
and as before, if none of those prefixes are present at the
beginning of the string, LOG_ERR is chosen.
On Win32, the LOG_* levels are mapped according to this:
LOG_EMERG, LOG_ALERT, LOG_CRIT, LOG_ERR => EVENTLOG_ERROR_TYPE
LOG_WARNING => EVENTLOG_WARNING_TYPE
LOG_NOTICE, LOG_INFO, LOG_DEBUG => EVENTLOG_INFORMATION_TYPE
[Richard Levitte]
*) Made it possible to reconfigure with just the configuration
argument "reconf" or "reconfigure". The command line arguments
are stored in Makefile.ssl in the variable CONFIGURE_ARGS,
and are retrieved from there when reconfiguring.
[Richard Levitte]
*) MD4 implemented.
[Assar Westerlund <assar@sics.se>, Richard Levitte]
*) Add the arguments -CAfile and -CApath to the pkcs12 utility.
[Richard Levitte]
*) The obj_dat.pl script was messing up the sorting of object
names. The reason was that it compared the quoted version
of strings as a result "OCSP" > "OCSP Signing" because
" > SPACE. Changed script to store unquoted versions of
names and add quotes on output. It was also omitting some
names from the lookup table if they were given a default
value (that is if SN is missing it is given the same
value as LN and vice versa), these are now added on the
grounds that if an object has a name we should be able to
look it up. Finally added warning output when duplicate
short or long names are found.
[Steve Henson]
*) Changes needed for Tandem NSK.
[Scott Uroff <scott@xypro.com>]
*) Fix SSL 2.0 rollback checking: Due to an off-by-one error in
RSA_padding_check_SSLv23(), special padding was never detected
and thus the SSL 3.0/TLS 1.0 countermeasure against protocol
version rollback attacks was not effective.
In s23_clnt.c, don't use special rollback-attack detection padding
(RSA_SSLV23_PADDING) if SSL 2.0 is the only protocol enabled in the
client; similarly, in s23_srvr.c, don't do the rollback check if
SSL 2.0 is the only protocol enabled in the server.
[Bodo Moeller]
*) Make it possible to get hexdumps of unprintable data with 'openssl
asn1parse'. By implication, the functions ASN1_parse_dump() and
BIO_dump_indent() are added.
[Richard Levitte]
*) New functions ASN1_STRING_print_ex() and X509_NAME_print_ex()
these print out strings and name structures based on various
flags including RFC2253 support and proper handling of
multibyte characters. Added options to the 'x509' utility
to allow the various flags to be set.
[Steve Henson]
*) Various fixes to use ASN1_TIME instead of ASN1_UTCTIME.
Also change the functions X509_cmp_current_time() and
X509_gmtime_adj() work with an ASN1_TIME structure,
this will enable certificates using GeneralizedTime in validity
dates to be checked.
[Steve Henson]
*) Make the NEG_PUBKEY_BUG code (which tolerates invalid
negative public key encodings) on by default,
NO_NEG_PUBKEY_BUG can be set to disable it.
[Steve Henson]
*) New function c2i_ASN1_OBJECT() which acts on ASN1_OBJECT
content octets. An i2c_ASN1_OBJECT is unnecessary because
the encoding can be trivially obtained from the structure.
[Steve Henson]
*) crypto/err.c locking bugfix: Use write locks (CRYPTO_w_[un]lock),
not read locks (CRYPTO_r_[un]lock).
[Bodo Moeller]
*) A first attempt at creating official support for shared
libraries through configuration. I've kept it so the
default is static libraries only, and the OpenSSL programs
are always statically linked for now, but there are
preparations for dynamic linking in place.
This has been tested on Linux and Tru64.
[Richard Levitte]
*) Randomness polling function for Win9x, as described in:
Peter Gutmann, Software Generation of Practically Strong
Random Numbers.
[Ulf Möller]
*) Fix so PRNG is seeded in req if using an already existing
DSA key.
[Steve Henson]
*) New options to smime application. -inform and -outform
allow alternative formats for the S/MIME message including
PEM and DER. The -content option allows the content to be
specified separately. This should allow things like Netscape
form signing output easier to verify.
[Steve Henson]
*) Fix the ASN1 encoding of tags using the 'long form'.
[Steve Henson]
*) New ASN1 functions, i2c_* and c2i_* for INTEGER and BIT
STRING types. These convert content octets to and from the
underlying type. The actual tag and length octets are
already assumed to have been read in and checked. These
are needed because all other string types have virtually
identical handling apart from the tag. By having versions
of the ASN1 functions that just operate on content octets
IMPLICIT tagging can be handled properly. It also allows
the ASN1_ENUMERATED code to be cut down because ASN1_ENUMERATED
and ASN1_INTEGER are identical apart from the tag.
[Steve Henson]
*) Change the handling of OID objects as follows:
- New object identifiers are inserted in objects.txt, following
the syntax given in objects.README.
- objects.pl is used to process obj_mac.num and create a new
obj_mac.h.
- obj_dat.pl is used to create a new obj_dat.h, using the data in
obj_mac.h.
This is currently kind of a hack, and the perl code in objects.pl
isn't very elegant, but it works as I intended. The simplest way
to check that it worked correctly is to look in obj_dat.h and
check the array nid_objs and make sure the objects haven't moved
around (this is important!). Additions are OK, as well as
consistent name changes.
[Richard Levitte]
*) Add BSD-style MD5-based passwords to 'openssl passwd' (option '-1').
[Bodo Moeller]
*) Addition of the command line parameter '-rand file' to 'openssl req'.
The given file adds to whatever has already been seeded into the
random pool through the RANDFILE configuration file option or
environment variable, or the default random state file.
[Richard Levitte]
*) mkstack.pl now sorts each macro group into lexical order.
Previously the output order depended on the order the files
appeared in the directory, resulting in needless rewriting
of safestack.h .
[Steve Henson]
*) Patches to make OpenSSL compile under Win32 again. Mostly
work arounds for the VC++ problem that it treats func() as
func(void). Also stripped out the parts of mkdef.pl that
added extra typesafe functions: these no longer exist.
[Steve Henson]
*) Reorganisation of the stack code. The macros are now all
collected in safestack.h . Each macro is defined in terms of
a "stack macro" of the form SKM_<name>(type, a, b). The
DEBUG_SAFESTACK is now handled in terms of function casts,
this has the advantage of retaining type safety without the
use of additional functions. If DEBUG_SAFESTACK is not defined
then the non typesafe macros are used instead. Also modified the
mkstack.pl script to handle the new form. Needs testing to see
if which (if any) compilers it chokes and maybe make DEBUG_SAFESTACK
the default if no major problems. Similar behaviour for ASN1_SET_OF
and PKCS12_STACK_OF.
[Steve Henson]
*) When some versions of IIS use the 'NET' form of private key the
key derivation algorithm is different. Normally MD5(password) is
used as a 128 bit RC4 key. In the modified case
MD5(MD5(password) + "SGCKEYSALT") is used instead. Added some
new functions i2d_RSA_NET(), d2i_RSA_NET() etc which are the same
as the old Netscape_RSA functions except they have an additional
'sgckey' parameter which uses the modified algorithm. Also added
an -sgckey command line option to the rsa utility. Thanks to
Adrian Peck <bertie@ncipher.com> for posting details of the modified
algorithm to openssl-dev.
[Steve Henson]
*) The evp_local.h macros were using 'c.##kname' which resulted in
invalid expansion on some systems (SCO 5.0.5 for example).
Corrected to 'c.kname'.
[Phillip Porch <root@theporch.com>]
*) New X509_get1_email() and X509_REQ_get1_email() functions that return
a STACK of email addresses from a certificate or request, these look
in the subject name and the subject alternative name extensions and
omit any duplicate addresses.
[Steve Henson]
*) Re-implement BN_mod_exp2_mont using independent (and larger) windows.
This makes DSA verification about 2 % faster.
[Bodo Moeller]
*) Increase maximum window size in BN_mod_exp_... to 6 bits instead of 5
(meaning that now 2^5 values will be precomputed, which is only 4 KB
plus overhead for 1024 bit moduli).
This makes exponentiations about 0.5 % faster for 1024 bit
exponents (as measured by "openssl speed rsa2048").
[Bodo Moeller]
*) Rename memory handling macros to avoid conflicts with other
software:
Malloc => OPENSSL_malloc
Malloc_locked => OPENSSL_malloc_locked
Realloc => OPENSSL_realloc
Free => OPENSSL_free
[Richard Levitte]
*) New function BN_mod_exp_mont_word for small bases (roughly 15%
faster than BN_mod_exp_mont, i.e. 7% for a full DH exchange).
[Bodo Moeller]
*) CygWin32 support.
[John Jarvie <jjarvie@newsguy.com>]
*) The type-safe stack code has been rejigged. It is now only compiled
in when OpenSSL is configured with the DEBUG_SAFESTACK option and
by default all type-specific stack functions are "#define"d back to
standard stack functions. This results in more streamlined output
but retains the type-safety checking possibilities of the original
approach.
[Geoff Thorpe]
*) The STACK code has been cleaned up, and certain type declarations
that didn't make a lot of sense have been brought in line. This has
also involved a cleanup of sorts in safestack.h to more correctly
map type-safe stack functions onto their plain stack counterparts.
This work has also resulted in a variety of "const"ifications of
lots of the code, especially "_cmp" operations which should normally
be prototyped with "const" parameters anyway.
[Geoff Thorpe]
*) When generating bytes for the first time in md_rand.c, 'stir the pool'
by seeding with STATE_SIZE dummy bytes (with zero entropy count).
(The PRNG state consists of two parts, the large pool 'state' and 'md',
where all of 'md' is used each time the PRNG is used, but 'state'
is used only indexed by a cyclic counter. As entropy may not be
well distributed from the beginning, 'md' is important as a
chaining variable. However, the output function chains only half
of 'md', i.e. 80 bits. ssleay_rand_add, on the other hand, chains
all of 'md', and seeding with STATE_SIZE dummy bytes will result
in all of 'state' being rewritten, with the new values depending
on virtually all of 'md'. This overcomes the 80 bit limitation.)
[Bodo Moeller]
*) In ssl/s2_clnt.c and ssl/s3_clnt.c, call ERR_clear_error() when
the handshake is continued after ssl_verify_cert_chain();
otherwise, if SSL_VERIFY_NONE is set, remaining error codes
can lead to 'unexplainable' connection aborts later.
[Bodo Moeller; problem tracked down by Lutz Jaenicke]
*) Major EVP API cipher revision.
Add hooks for extra EVP features. This allows various cipher
parameters to be set in the EVP interface. Support added for variable
key length ciphers via the EVP_CIPHER_CTX_set_key_length() function and
setting of RC2 and RC5 parameters.
Modify EVP_OpenInit() and EVP_SealInit() to cope with variable key length
ciphers.
Remove lots of duplicated code from the EVP library. For example *every*
cipher init() function handles the 'iv' in the same way according to the
cipher mode. They also all do nothing if the 'key' parameter is NULL and
for CFB and OFB modes they zero ctx->num.
New functionality allows removal of S/MIME code RC2 hack.
Most of the routines have the same form and so can be declared in terms
of macros.
By shifting this to the top level EVP_CipherInit() it can be removed from
all individual ciphers. If the cipher wants to handle IVs or keys
differently it can set the EVP_CIPH_CUSTOM_IV or EVP_CIPH_ALWAYS_CALL_INIT
flags.
Change lots of functions like EVP_EncryptUpdate() to now return a
value: although software versions of the algorithms cannot fail
any installed hardware versions can.
[Steve Henson]
*) Implement SSL_OP_TLS_ROLLBACK_BUG: In ssl3_get_client_key_exchange, if
this option is set, tolerate broken clients that send the negotiated
protocol version number instead of the requested protocol version
number.
[Bodo Moeller]
*) Call dh_tmp_cb (set by ..._TMP_DH_CB) with correct 'is_export' flag;
i.e. non-zero for export ciphersuites, zero otherwise.
Previous versions had this flag inverted, inconsistent with
rsa_tmp_cb (..._TMP_RSA_CB).
[Bodo Moeller; problem reported by Amit Chopra]
*) Add missing DSA library text string. Work around for some IIS
key files with invalid SEQUENCE encoding.
[Steve Henson]
*) Add a document (doc/standards.txt) that list all kinds of standards
and so on that are implemented in OpenSSL.
[Richard Levitte]
*) Enhance c_rehash script. Old version would mishandle certificates
with the same subject name hash and wouldn't handle CRLs at all.
Added -fingerprint option to crl utility, to support new c_rehash
features.
[Steve Henson]
*) Eliminate non-ANSI declarations in crypto.h and stack.h.
[Ulf Möller]
*) Fix for SSL server purpose checking. Server checking was
rejecting certificates which had extended key usage present
but no ssl client purpose.
[Steve Henson, reported by Rene Grosser <grosser@hisolutions.com>]
*) Make PKCS#12 code work with no password. The PKCS#12 spec
is a little unclear about how a blank password is handled.
Since the password in encoded as a BMPString with terminating
double NULL a zero length password would end up as just the
double NULL. However no password at all is different and is
handled differently in the PKCS#12 key generation code. NS
treats a blank password as zero length. MSIE treats it as no
password on export: but it will try both on import. We now do
the same: PKCS12_parse() tries zero length and no password if
the password is set to "" or NULL (NULL is now a valid password:
it wasn't before) as does the pkcs12 application.
[Steve Henson]
*) Bugfixes in apps/x509.c: Avoid a memory leak; and don't use
perror when PEM_read_bio_X509_REQ fails, the error message must
be obtained from the error queue.
[Bodo Moeller]
*) Avoid 'thread_hash' memory leak in crypto/err/err.c by freeing
it in ERR_remove_state if appropriate, and change ERR_get_state
accordingly to avoid race conditions (this is necessary because
thread_hash is no longer constant once set).
[Bodo Moeller]
*) Bugfix for linux-elf makefile.one.
[Ulf Möller]
*) RSA_get_default_method() will now cause a default
RSA_METHOD to be chosen if one doesn't exist already.
Previously this was only set during a call to RSA_new()
or RSA_new_method(NULL) meaning it was possible for
RSA_get_default_method() to return NULL.
[Geoff Thorpe]
*) Added native name translation to the existing DSO code
that will convert (if the flag to do so is set) filenames
that are sufficiently small and have no path information
into a canonical native form. Eg. "blah" converted to
"libblah.so" or "blah.dll" etc.
[Geoff Thorpe]
*) New function ERR_error_string_n(e, buf, len) which is like
ERR_error_string(e, buf), but writes at most 'len' bytes
including the 0 terminator. For ERR_error_string_n, 'buf'
may not be NULL.
[Damien Miller <djm@mindrot.org>, Bodo Moeller]
*) CONF library reworked to become more general. A new CONF
configuration file reader "class" is implemented as well as a
new functions (NCONF_*, for "New CONF") to handle it. The now
old CONF_* functions are still there, but are reimplemented to
work in terms of the new functions. Also, a set of functions
to handle the internal storage of the configuration data is
provided to make it easier to write new configuration file
reader "classes" (I can definitely see something reading a
configuration file in XML format, for example), called _CONF_*,
or "the configuration storage API"...
The new configuration file reading functions are:
NCONF_new, NCONF_free, NCONF_load, NCONF_load_fp, NCONF_load_bio,
NCONF_get_section, NCONF_get_string, NCONF_get_numbre
NCONF_default, NCONF_WIN32
NCONF_dump_fp, NCONF_dump_bio
NCONF_default and NCONF_WIN32 are method (or "class") choosers,
NCONF_new creates a new CONF object. This works in the same way
as other interfaces in OpenSSL, like the BIO interface.
NCONF_dump_* dump the internal storage of the configuration file,
which is useful for debugging. All other functions take the same
arguments as the old CONF_* functions wth the exception of the
first that must be a `CONF *' instead of a `LHASH *'.
To make it easer to use the new classes with the old CONF_* functions,
the function CONF_set_default_method is provided.
[Richard Levitte]
*) Add '-tls1' option to 'openssl ciphers', which was already
mentioned in the documentation but had not been implemented.
(This option is not yet really useful because even the additional
experimental TLS 1.0 ciphers are currently treated as SSL 3.0 ciphers.)
[Bodo Moeller]
*) Initial DSO code added into libcrypto for letting OpenSSL (and
OpenSSL-based applications) load shared libraries and bind to
them in a portable way.
[Geoff Thorpe, with contributions from Richard Levitte]
Changes between 0.9.5 and 0.9.5a [1 Apr 2000]
*) Make sure _lrotl and _lrotr are only used with MSVC.
*) Use lock CRYPTO_LOCK_RAND correctly in ssleay_rand_status
(the default implementation of RAND_status).
*) Rename openssl x509 option '-crlext', which was added in 0.9.5,
to '-clrext' (= clear extensions), as intended and documented.
[Bodo Moeller; inconsistency pointed out by Michael Attili
<attili@amaxo.com>]
*) Fix for HMAC. It wasn't zeroing the rest of the block if the key length
was larger than the MD block size.
[Steve Henson, pointed out by Yost William <YostW@tce.com>]
*) Modernise PKCS12_parse() so it uses STACK_OF(X509) for its ca argument
fix a leak when the ca argument was passed as NULL. Stop X509_PUBKEY_set()
using the passed key: if the passed key was a private key the result
of X509_print(), for example, would be to print out all the private key
components.
[Steve Henson]
*) des_quad_cksum() byte order bug fix.
[Ulf Möller, using the problem description in krb4-0.9.7, where
the solution is attributed to Derrick J Brashear <shadow@DEMENTIA.ORG>]
*) Fix so V_ASN1_APP_CHOOSE works again: however its use is strongly
discouraged.
[Steve Henson, pointed out by Brian Korver <briank@cs.stanford.edu>]
*) For easily testing in shell scripts whether some command
'openssl XXX' exists, the new pseudo-command 'openssl no-XXX'
returns with exit code 0 iff no command of the given name is available.
'no-XXX' is printed in this case, 'XXX' otherwise. In both cases,
the output goes to stdout and nothing is printed to stderr.
Additional arguments are always ignored.
Since for each cipher there is a command of the same name,
the 'no-cipher' compilation switches can be tested this way.
('openssl no-XXX' is not able to detect pseudo-commands such
as 'quit', 'list-XXX-commands', or 'no-XXX' itself.)
[Bodo Moeller]
*) Update test suite so that 'make test' succeeds in 'no-rsa' configuration.
[Bodo Moeller]
*) For SSL_[CTX_]set_tmp_dh, don't create a DH key if SSL_OP_SINGLE_DH_USE
is set; it will be thrown away anyway because each handshake creates
its own key.
ssl_cert_dup, which is used by SSL_new, now copies DH keys in addition
to parameters -- in previous versions (since OpenSSL 0.9.3) the
'default key' from SSL_CTX_set_tmp_dh would always be lost, meaning
you effectively got SSL_OP_SINGLE_DH_USE when using this macro.
[Bodo Moeller]
*) New s_client option -ign_eof: EOF at stdin is ignored, and
'Q' and 'R' lose their special meanings (quit/renegotiate).
This is part of what -quiet does; unlike -quiet, -ign_eof
does not suppress any output.
[Richard Levitte]
*) Add compatibility options to the purpose and trust code. The
purpose X509_PURPOSE_ANY is "any purpose" which automatically
accepts a certificate or CA, this was the previous behaviour,
with all the associated security issues.
X509_TRUST_COMPAT is the old trust behaviour: only and
automatically trust self signed roots in certificate store. A
new trust setting X509_TRUST_DEFAULT is used to specify that
a purpose has no associated trust setting and it should instead
use the value in the default purpose.
[Steve Henson]
*) Fix the PKCS#8 DSA private key code so it decodes keys again
and fix a memory leak.
[Steve Henson]
*) In util/mkerr.pl (which implements 'make errors'), preserve
reason strings from the previous version of the .c file, as
the default to have only downcase letters (and digits) in
automatically generated reasons codes is not always appropriate.
[Bodo Moeller]
*) In ERR_load_ERR_strings(), build an ERR_LIB_SYS error reason table
using strerror. Previously, ERR_reason_error_string() returned
library names as reason strings for SYSerr; but SYSerr is a special
case where small numbers are errno values, not library numbers.
[Bodo Moeller]
*) Add '-dsaparam' option to 'openssl dhparam' application. This
converts DSA parameters into DH parameters. (When creating parameters,
DSA_generate_parameters is used.)
[Bodo Moeller]
*) Include 'length' (recommended exponent length) in C code generated
by 'openssl dhparam -C'.
[Bodo Moeller]
*) The second argument to set_label in perlasm was already being used
so couldn't be used as a "file scope" flag. Moved to third argument
which was free.
[Steve Henson]
*) In PEM_ASN1_write_bio and some other functions, use RAND_pseudo_bytes
instead of RAND_bytes for encryption IVs and salts.
[Bodo Moeller]
*) Include RAND_status() into RAND_METHOD instead of implementing
it only for md_rand.c Otherwise replacing the PRNG by calling
RAND_set_rand_method would be impossible.
[Bodo Moeller]
*) Don't let DSA_generate_key() enter an infinite loop if the random
number generation fails.
[Bodo Moeller]
*) New 'rand' application for creating pseudo-random output.
[Bodo Moeller]
*) Added configuration support for Linux/IA64
[Rolf Haberrecker <rolf@suse.de>]
*) Assembler module support for Mingw32.
[Ulf Möller]
*) Shared library support for HPUX (in shlib/).
[Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE> and Anonymous]
*) Shared library support for Solaris gcc.
[Lutz Behnke <behnke@trustcenter.de>]
Changes between 0.9.4 and 0.9.5 [28 Feb 2000]
*) PKCS7_encrypt() was adding text MIME headers twice because they
were added manually and by SMIME_crlf_copy().
[Steve Henson]
*) In bntest.c don't call BN_rand with zero bits argument.
[Steve Henson, pointed out by Andrew W. Gray <agray@iconsinc.com>]
*) BN_mul bugfix: In bn_mul_part_recursion() only the a>a[n] && b>b[n]
case was implemented. This caused BN_div_recp() to fail occasionally.
[Ulf Möller]
*) Add an optional second argument to the set_label() in the perl
assembly language builder. If this argument exists and is set
to 1 it signals that the assembler should use a symbol whose
scope is the entire file, not just the current function. This
is needed with MASM which uses the format label:: for this scope.
[Steve Henson, pointed out by Peter Runestig <peter@runestig.com>]
*) Change the ASN1 types so they are typedefs by default. Before
almost all types were #define'd to ASN1_STRING which was causing
STACK_OF() problems: you couldn't declare STACK_OF(ASN1_UTF8STRING)
for example.
[Steve Henson]
*) Change names of new functions to the new get1/get0 naming
convention: After 'get1', the caller owns a reference count
and has to call ..._free; 'get0' returns a pointer to some
data structure without incrementing reference counters.
(Some of the existing 'get' functions increment a reference
counter, some don't.)
Similarly, 'set1' and 'add1' functions increase reference
counters or duplicate objects.
[Steve Henson]
*) Allow for the possibility of temp RSA key generation failure:
the code used to assume it always worked and crashed on failure.
[Steve Henson]
*) Fix potential buffer overrun problem in BIO_printf().
[Ulf Möller, using public domain code by Patrick Powell; problem
pointed out by David Sacerdote <das33@cornell.edu>]
*) Support EGD <http://www.lothar.com/tech/crypto/>. New functions
RAND_egd() and RAND_status(). In the command line application,
the EGD socket can be specified like a seed file using RANDFILE
or -rand.
[Ulf Möller]
*) Allow the string CERTIFICATE to be tolerated in PKCS#7 structures.
Some CAs (e.g. Verisign) distribute certificates in this form.
[Steve Henson]
*) Remove the SSL_ALLOW_ADH compile option and set the default cipher
list to exclude them. This means that no special compilation option
is needed to use anonymous DH: it just needs to be included in the
cipher list.
[Steve Henson]
*) Change the EVP_MD_CTX_type macro so its meaning consistent with
EVP_MD_type. The old functionality is available in a new macro called
EVP_MD_md(). Change code that uses it and update docs.
[Steve Henson]
*) ..._ctrl functions now have corresponding ..._callback_ctrl functions
where the 'void *' argument is replaced by a function pointer argument.
Previously 'void *' was abused to point to functions, which works on
many platforms, but is not correct. As these functions are usually
called by macros defined in OpenSSL header files, most source code
should work without changes.
[Richard Levitte]
*) <openssl/opensslconf.h> (which is created by Configure) now contains
sections with information on -D... compiler switches used for
compiling the library so that applications can see them. To enable
one of these sections, a pre-processor symbol OPENSSL_..._DEFINES
must be defined. E.g.,
#define OPENSSL_ALGORITHM_DEFINES
#include <openssl/opensslconf.h>
defines all pertinent NO_<algo> symbols, such as NO_IDEA, NO_RSA, etc.
[Richard Levitte, Ulf and Bodo Möller]
*) Bugfix: Tolerate fragmentation and interleaving in the SSL 3/TLS
record layer.
[Bodo Moeller]
*) Change the 'other' type in certificate aux info to a STACK_OF
X509_ALGOR. Although not an AlgorithmIdentifier as such it has
the required ASN1 format: arbitrary types determined by an OID.
[Steve Henson]
*) Add some PEM_write_X509_REQ_NEW() functions and a command line
argument to 'req'. This is not because the function is newer or
better than others it just uses the work 'NEW' in the certificate
request header lines. Some software needs this.
[Steve Henson]
*) Reorganise password command line arguments: now passwords can be
obtained from various sources. Delete the PEM_cb function and make
it the default behaviour: i.e. if the callback is NULL and the
usrdata argument is not NULL interpret it as a null terminated pass
phrase. If usrdata and the callback are NULL then the pass phrase
is prompted for as usual.
[Steve Henson]
*) Add support for the Compaq Atalla crypto accelerator. If it is installed,
the support is automatically enabled. The resulting binaries will
autodetect the card and use it if present.
[Ben Laurie and Compaq Inc.]
*) Work around for Netscape hang bug. This sends certificate request
and server done in one record. Since this is perfectly legal in the
SSL/TLS protocol it isn't a "bug" option and is on by default. See
the bugs/SSLv3 entry for more info.
[Steve Henson]
*) HP-UX tune-up: new unified configs, HP C compiler bug workaround.
[Andy Polyakov]
*) Add -rand argument to smime and pkcs12 applications and read/write
of seed file.
[Steve Henson]
*) New 'passwd' tool for crypt(3) and apr1 password hashes.
[Bodo Moeller]
*) Add command line password options to the remaining applications.
[Steve Henson]
*) Bug fix for BN_div_recp() for numerators with an even number of
bits.
[Ulf Möller]
*) More tests in bntest.c, and changed test_bn output.
[Ulf Möller]
*) ./config recognizes MacOS X now.
[Andy Polyakov]
*) Bug fix for BN_div() when the first words of num and divisor are
equal (it gave wrong results if (rem=(n1-q*d0)&BN_MASK2) < d0).
[Ulf Möller]
*) Add support for various broken PKCS#8 formats, and command line
options to produce them.
[Steve Henson]
*) New functions BN_CTX_start(), BN_CTX_get() and BT_CTX_end() to
get temporary BIGNUMs from a BN_CTX.
[Ulf Möller]
*) Correct return values in BN_mod_exp_mont() and BN_mod_exp2_mont()
for p == 0.
[Ulf Möller]
*) Change the SSLeay_add_all_*() functions to OpenSSL_add_all_*() and
include a #define from the old name to the new. The original intent
was that statically linked binaries could for example just call
SSLeay_add_all_ciphers() to just add ciphers to the table and not
link with digests. This never worked because SSLeay_add_all_digests()
and SSLeay_add_all_ciphers() were in the same source file so calling
one would link with the other. They are now in separate source files.
[Steve Henson]
*) Add a new -notext option to 'ca' and a -pubkey option to 'spkac'.
[Steve Henson]
*) Use a less unusual form of the Miller-Rabin primality test (it used
a binary algorithm for exponentiation integrated into the Miller-Rabin
loop, our standard modexp algorithms are faster).
[Bodo Moeller]
*) Support for the EBCDIC character set completed.
[Martin Kraemer <Martin.Kraemer@Mch.SNI.De>]
*) Source code cleanups: use const where appropriate, eliminate casts,
use void * instead of char * in lhash.
[Ulf Möller]
*) Bugfix: ssl3_send_server_key_exchange was not restartable
(the state was not changed to SSL3_ST_SW_KEY_EXCH_B, and because of
this the server could overwrite ephemeral keys that the client
has already seen).
[Bodo Moeller]
*) Turn DSA_is_prime into a macro that calls BN_is_prime,
using 50 iterations of the Rabin-Miller test.
DSA_generate_parameters now uses BN_is_prime_fasttest (with 50
iterations of the Rabin-Miller test as required by the appendix
to FIPS PUB 186[-1]) instead of DSA_is_prime.
As BN_is_prime_fasttest includes trial division, DSA parameter
generation becomes much faster.
This implies a change for the callback functions in DSA_is_prime
and DSA_generate_parameters: The callback function is called once
for each positive witness in the Rabin-Miller test, not just
occasionally in the inner loop; and the parameters to the
callback function now provide an iteration count for the outer
loop rather than for the current invocation of the inner loop.
DSA_generate_parameters additionally can call the callback
function with an 'iteration count' of -1, meaning that a
candidate has passed the trial division test (when q is generated
from an application-provided seed, trial division is skipped).
[Bodo Moeller]
*) New function BN_is_prime_fasttest that optionally does trial
division before starting the Rabin-Miller test and has
an additional BN_CTX * argument (whereas BN_is_prime always
has to allocate at least one BN_CTX).
'callback(1, -1, cb_arg)' is called when a number has passed the
trial division stage.
[Bodo Moeller]
*) Fix for bug in CRL encoding. The validity dates weren't being handled
as ASN1_TIME.
[Steve Henson]
*) New -pkcs12 option to CA.pl script to write out a PKCS#12 file.
[Steve Henson]
*) New function BN_pseudo_rand().
[Ulf Möller]
*) Clean up BN_mod_mul_montgomery(): replace the broken (and unreadable)
bignum version of BN_from_montgomery() with the working code from
SSLeay 0.9.0 (the word based version is faster anyway), and clean up
the comments.
[Ulf Möller]
*) Avoid a race condition in s2_clnt.c (function get_server_hello) that
made it impossible to use the same SSL_SESSION data structure in
SSL2 clients in multiple threads.
[Bodo Moeller]
*) The return value of RAND_load_file() no longer counts bytes obtained
by stat(). RAND_load_file(..., -1) is new and uses the complete file
to seed the PRNG (previously an explicit byte count was required).
[Ulf Möller, Bodo Möller]
*) Clean up CRYPTO_EX_DATA functions, some of these didn't have prototypes
used (char *) instead of (void *) and had casts all over the place.
[Steve Henson]
*) Make BN_generate_prime() return NULL on error if ret!=NULL.
[Ulf Möller]
*) Retain source code compatibility for BN_prime_checks macro:
BN_is_prime(..., BN_prime_checks, ...) now uses
BN_prime_checks_for_size to determine the appropriate number of
Rabin-Miller iterations.
[Ulf Möller]
*) Diffie-Hellman uses "safe" primes: DH_check() return code renamed to
DH_CHECK_P_NOT_SAFE_PRIME.
(Check if this is true? OpenPGP calls them "strong".)
[Ulf Möller]
*) Merge the functionality of "dh" and "gendh" programs into a new program
"dhparam". The old programs are retained for now but will handle DH keys
(instead of parameters) in future.
[Steve Henson]
*) Make the ciphers, s_server and s_client programs check the return values
when a new cipher list is set.
[Steve Henson]
*) Enhance the SSL/TLS cipher mechanism to correctly handle the TLS 56bit
ciphers. Before when the 56bit ciphers were enabled the sorting was
wrong.
The syntax for the cipher sorting has been extended to support sorting by
cipher-strength (using the strength_bits hard coded in the tables).
The new command is "@STRENGTH" (see also doc/apps/ciphers.pod).
Fix a bug in the cipher-command parser: when supplying a cipher command
string with an "undefined" symbol (neither command nor alphanumeric
[A-Za-z0-9], ssl_set_cipher_list used to hang in an endless loop. Now
an error is flagged.
Due to the strength-sorting extension, the code of the
ssl_create_cipher_list() function was completely rearranged. I hope that
the readability was also increased :-)
[Lutz Jaenicke <Lutz.Jaenicke@aet.TU-Cottbus.DE>]
*) Minor change to 'x509' utility. The -CAcreateserial option now uses 1
for the first serial number and places 2 in the serial number file. This
avoids problems when the root CA is created with serial number zero and
the first user certificate has the same issuer name and serial number
as the root CA.
[Steve Henson]
*) Fixes to X509_ATTRIBUTE utilities, change the 'req' program so it uses
the new code. Add documentation for this stuff.
[Steve Henson]
*) Changes to X509_ATTRIBUTE utilities. These have been renamed from
X509_*() to X509at_*() on the grounds that they don't handle X509
structures and behave in an analogous way to the X509v3 functions:
they shouldn't be called directly but wrapper functions should be used
instead.
So we also now have some wrapper functions that call the X509at functions
when passed certificate requests. (TO DO: similar things can be done with
PKCS#7 signed and unsigned attributes, PKCS#12 attributes and a few other
things. Some of these need some d2i or i2d and print functionality
because they handle more complex structures.)
[Steve Henson]
*) Add missing #ifndefs that caused missing symbols when building libssl
as a shared library without RSA. Use #ifndef NO_SSL2 instead of
NO_RSA in ssl/s2*.c.
[Kris Kennaway <kris@hub.freebsd.org>, modified by Ulf Möller]
*) Precautions against using the PRNG uninitialized: RAND_bytes() now
has a return value which indicates the quality of the random data
(1 = ok, 0 = not seeded). Also an error is recorded on the thread's
error queue. New function RAND_pseudo_bytes() generates output that is
guaranteed to be unique but not unpredictable. RAND_add is like
RAND_seed, but takes an extra argument for an entropy estimate
(RAND_seed always assumes full entropy).
[Ulf Möller]
*) Do more iterations of Rabin-Miller probable prime test (specifically,
3 for 1024-bit primes, 6 for 512-bit primes, 12 for 256-bit primes
instead of only 2 for all lengths; see BN_prime_checks_for_size definition
in crypto/bn/bn_prime.c for the complete table). This guarantees a
false-positive rate of at most 2^-80 for random input.
[Bodo Moeller]
*) Rewrite ssl3_read_n (ssl/s3_pkt.c) avoiding a couple of bugs.
[Bodo Moeller]
*) New function X509_CTX_rget_chain() (renamed to X509_CTX_get1_chain
in the 0.9.5 release), this returns the chain
from an X509_CTX structure with a dup of the stack and all
the X509 reference counts upped: so the stack will exist
after X509_CTX_cleanup() has been called. Modify pkcs12.c
to use this.
Also make SSL_SESSION_print() print out the verify return
code.
[Steve Henson]
*) Add manpage for the pkcs12 command. Also change the default
behaviour so MAC iteration counts are used unless the new
-nomaciter option is used. This improves file security and
only older versions of MSIE (4.0 for example) need it.
[Steve Henson]
*) Honor the no-xxx Configure options when creating .DEF files.
[Ulf Möller]
*) Add PKCS#10 attributes to field table: challengePassword,
unstructuredName and unstructuredAddress. These are taken from
draft PKCS#9 v2.0 but are compatible with v1.2 provided no
international characters are used.
More changes to X509_ATTRIBUTE code: allow the setting of types
based on strings. Remove the 'loc' parameter when adding
attributes because these will be a SET OF encoding which is sorted
in ASN1 order.
[Steve Henson]
*) Initial changes to the 'req' utility to allow request generation
automation. This will allow an application to just generate a template
file containing all the field values and have req construct the
request.
Initial support for X509_ATTRIBUTE handling. Stacks of these are
used all over the place including certificate requests and PKCS#7
structures. They are currently handled manually where necessary with
some primitive wrappers for PKCS#7. The new functions behave in a
manner analogous to the X509 extension functions: they allow
attributes to be looked up by NID and added.
Later something similar to the X509V3 code would be desirable to
automatically handle the encoding, decoding and printing of the
more complex types. The string types like challengePassword can
be handled by the string table functions.
Also modified the multi byte string table handling. Now there is
a 'global mask' which masks out certain types. The table itself
can use the flag STABLE_NO_MASK to ignore the mask setting: this
is useful when for example there is only one permissible type
(as in countryName) and using the mask might result in no valid
types at all.
[Steve Henson]
*) Clean up 'Finished' handling, and add functions SSL_get_finished and
SSL_get_peer_finished to allow applications to obtain the latest
Finished messages sent to the peer or expected from the peer,
respectively. (SSL_get_peer_finished is usually the Finished message
actually received from the peer, otherwise the protocol will be aborted.)
As the Finished message are message digests of the complete handshake
(with a total of 192 bits for TLS 1.0 and more for SSL 3.0), they can
be used for external authentication procedures when the authentication
provided by SSL/TLS is not desired or is not enough.
[Bodo Moeller]
*) Enhanced support for Alpha Linux is added. Now ./config checks if
the host supports BWX extension and if Compaq C is present on the
$PATH. Just exploiting of the BWX extension results in 20-30%
performance kick for some algorithms, e.g. DES and RC4 to mention
a couple. Compaq C in turn generates ~20% faster code for MD5 and
SHA1.
[Andy Polyakov]
*) Add support for MS "fast SGC". This is arguably a violation of the
SSL3/TLS protocol. Netscape SGC does two handshakes: the first with
weak crypto and after checking the certificate is SGC a second one
with strong crypto. MS SGC stops the first handshake after receiving
the server certificate message and sends a second client hello. Since
a server will typically do all the time consuming operations before
expecting any further messages from the client (server key exchange
is the most expensive) there is little difference between the two.
To get OpenSSL to support MS SGC we have to permit a second client
hello message after we have sent server done. In addition we have to
reset the MAC if we do get this second client hello.
[Steve Henson]
*) Add a function 'd2i_AutoPrivateKey()' this will automatically decide
if a DER encoded private key is RSA or DSA traditional format. Changed
d2i_PrivateKey_bio() to use it. This is only needed for the "traditional"
format DER encoded private key. Newer code should use PKCS#8 format which
has the key type encoded in the ASN1 structure. Added DER private key
support to pkcs8 application.
[Steve Henson]
*) SSL 3/TLS 1 servers now don't request certificates when an anonymous
ciphersuites has been selected (as required by the SSL 3/TLS 1
specifications). Exception: When SSL_VERIFY_FAIL_IF_NO_PEER_CERT
is set, we interpret this as a request to violate the specification
(the worst that can happen is a handshake failure, and 'correct'
behaviour would result in a handshake failure anyway).
[Bodo Moeller]
*) In SSL_CTX_add_session, take into account that there might be multiple
SSL_SESSION structures with the same session ID (e.g. when two threads
concurrently obtain them from an external cache).
The internal cache can handle only one SSL_SESSION with a given ID,
so if there's a conflict, we now throw out the old one to achieve
consistency.
[Bodo Moeller]
*) Add OIDs for idea and blowfish in CBC mode. This will allow both
to be used in PKCS#5 v2.0 and S/MIME. Also add checking to
some routines that use cipher OIDs: some ciphers do not have OIDs
defined and so they cannot be used for S/MIME and PKCS#5 v2.0 for
example.
[Steve Henson]
*) Simplify the trust setting structure and code. Now we just have
two sequences of OIDs for trusted and rejected settings. These will
typically have values the same as the extended key usage extension
and any application specific purposes.
The trust checking code now has a default behaviour: it will just
check for an object with the same NID as the passed id. Functions can
be provided to override either the default behaviour or the behaviour
for a given id. SSL client, server and email already have functions
in place for compatibility: they check the NID and also return "trusted"
if the certificate is self signed.
[Steve Henson]
*) Add d2i,i2d bio/fp functions for PrivateKey: these convert the
traditional format into an EVP_PKEY structure.
[Steve Henson]
*) Add a password callback function PEM_cb() which either prompts for
a password if usr_data is NULL or otherwise assumes it is a null
terminated password. Allow passwords to be passed on command line
environment or config files in a few more utilities.
[Steve Henson]
*) Add a bunch of DER and PEM functions to handle PKCS#8 format private
keys. Add some short names for PKCS#8 PBE algorithms and allow them
to be specified on the command line for the pkcs8 and pkcs12 utilities.
Update documentation.
[Steve Henson]
*) Support for ASN1 "NULL" type. This could be handled before by using
ASN1_TYPE but there wasn't any function that would try to read a NULL
and produce an error if it couldn't. For compatibility we also have
ASN1_NULL_new() and ASN1_NULL_free() functions but these are faked and
don't allocate anything because they don't need to.
[Steve Henson]
*) Initial support for MacOS is now provided. Examine INSTALL.MacOS
for details.
[Andy Polyakov, Roy Woods <roy@centicsystems.ca>]
*) Rebuild of the memory allocation routines used by OpenSSL code and
possibly others as well. The purpose is to make an interface that
provide hooks so anyone can build a separate set of allocation and
deallocation routines to be used by OpenSSL, for example memory
pool implementations, or something else, which was previously hard
since Malloc(), Realloc() and Free() were defined as macros having
the values malloc, realloc and free, respectively (except for Win32
compilations). The same is provided for memory debugging code.
OpenSSL already comes with functionality to find memory leaks, but
this gives people a chance to debug other memory problems.
With these changes, a new set of functions and macros have appeared:
CRYPTO_set_mem_debug_functions() [F]
CRYPTO_get_mem_debug_functions() [F]
CRYPTO_dbg_set_options() [F]
CRYPTO_dbg_get_options() [F]
CRYPTO_malloc_debug_init() [M]
The memory debug functions are NULL by default, unless the library
is compiled with CRYPTO_MDEBUG or friends is defined. If someone
wants to debug memory anyway, CRYPTO_malloc_debug_init() (which
gives the standard debugging functions that come with OpenSSL) or
CRYPTO_set_mem_debug_functions() (tells OpenSSL to use functions
provided by the library user) must be used. When the standard
debugging functions are used, CRYPTO_dbg_set_options can be used to
request additional information:
CRYPTO_dbg_set_options(V_CYRPTO_MDEBUG_xxx) corresponds to setting
the CRYPTO_MDEBUG_xxx macro when compiling the library.
Also, things like CRYPTO_set_mem_functions will always give the
expected result (the new set of functions is used for allocation
and deallocation) at all times, regardless of platform and compiler
options.
To finish it up, some functions that were never use in any other
way than through macros have a new API and new semantic:
CRYPTO_dbg_malloc()
CRYPTO_dbg_realloc()
CRYPTO_dbg_free()
All macros of value have retained their old syntax.
[Richard Levitte and Bodo Moeller]
*) Some S/MIME fixes. The OID for SMIMECapabilities was wrong, the
ordering of SMIMECapabilities wasn't in "strength order" and there
was a missing NULL in the AlgorithmIdentifier for the SHA1 signature
algorithm.
[Steve Henson]
*) Some ASN1 types with illegal zero length encoding (INTEGER,
ENUMERATED and OBJECT IDENTIFIER) choked the ASN1 routines.
[Frans Heymans <fheymans@isaserver.be>, modified by Steve Henson]
*) Merge in my S/MIME library for OpenSSL. This provides a simple
S/MIME API on top of the PKCS#7 code, a MIME parser (with enough
functionality to handle multipart/signed properly) and a utility
called 'smime' to call all this stuff. This is based on code I
originally wrote for Celo who have kindly allowed it to be
included in OpenSSL.
[Steve Henson]
*) Add variants des_set_key_checked and des_set_key_unchecked of
des_set_key (aka des_key_sched). Global variable des_check_key
decides which of these is called by des_set_key; this way
des_check_key behaves as it always did, but applications and
the library itself, which was buggy for des_check_key == 1,
have a cleaner way to pick the version they need.
[Bodo Moeller]
*) New function PKCS12_newpass() which changes the password of a
PKCS12 structure.
[Steve Henson]
*) Modify X509_TRUST and X509_PURPOSE so it also uses a static and
dynamic mix. In both cases the ids can be used as an index into the
table. Also modified the X509_TRUST_add() and X509_PURPOSE_add()
functions so they accept a list of the field values and the
application doesn't need to directly manipulate the X509_TRUST
structure.
[Steve Henson]
*) Modify the ASN1_STRING_TABLE stuff so it also uses bsearch and doesn't
need initialising.
[Steve Henson]
*) Modify the way the V3 extension code looks up extensions. This now
works in a similar way to the object code: we have some "standard"
extensions in a static table which is searched with OBJ_bsearch()
and the application can add dynamic ones if needed. The file
crypto/x509v3/ext_dat.h now has the info: this file needs to be
updated whenever a new extension is added to the core code and kept
in ext_nid order. There is a simple program 'tabtest.c' which checks
this. New extensions are not added too often so this file can readily
be maintained manually.
There are two big advantages in doing things this way. The extensions
can be looked up immediately and no longer need to be "added" using
X509V3_add_standard_extensions(): this function now does nothing.
[Side note: I get *lots* of email saying the extension code doesn't
work because people forget to call this function]
Also no dynamic allocation is done unless new extensions are added:
so if we don't add custom extensions there is no need to call
X509V3_EXT_cleanup().
[Steve Henson]
*) Modify enc utility's salting as follows: make salting the default. Add a
magic header, so unsalted files fail gracefully instead of just decrypting
to garbage. This is because not salting is a big security hole, so people
should be discouraged from doing it.
[Ben Laurie]
*) Fixes and enhancements to the 'x509' utility. It allowed a message
digest to be passed on the command line but it only used this
parameter when signing a certificate. Modified so all relevant
operations are affected by the digest parameter including the
-fingerprint and -x509toreq options. Also -x509toreq choked if a
DSA key was used because it didn't fix the digest.
[Steve Henson]
*) Initial certificate chain verify code. Currently tests the untrusted
certificates for consistency with the verify purpose (which is set
when the X509_STORE_CTX structure is set up) and checks the pathlength.
There is a NO_CHAIN_VERIFY compilation option to keep the old behaviour:
this is because it will reject chains with invalid extensions whereas
every previous version of OpenSSL and SSLeay made no checks at all.
Trust code: checks the root CA for the relevant trust settings. Trust
settings have an initial value consistent with the verify purpose: e.g.
if the verify purpose is for SSL client use it expects the CA to be
trusted for SSL client use. However the default value can be changed to
permit custom trust settings: one example of this would be to only trust
certificates from a specific "secure" set of CAs.
Also added X509_STORE_CTX_new() and X509_STORE_CTX_free() functions
which should be used for version portability: especially since the
verify structure is likely to change more often now.
SSL integration. Add purpose and trust to SSL_CTX and SSL and functions
to set them. If not set then assume SSL clients will verify SSL servers
and vice versa.
Two new options to the verify program: -untrusted allows a set of
untrusted certificates to be passed in and -purpose which sets the
intended purpose of the certificate. If a purpose is set then the
new chain verify code is used to check extension consistency.
[Steve Henson]
*) Support for the authority information access extension.
[Steve Henson]
*) Modify RSA and DSA PEM read routines to transparently handle
PKCS#8 format private keys. New *_PUBKEY_* functions that handle
public keys in a format compatible with certificate
SubjectPublicKeyInfo structures. Unfortunately there were already
functions called *_PublicKey_* which used various odd formats so
these are retained for compatibility: however the DSA variants were
never in a public release so they have been deleted. Changed dsa/rsa
utilities to handle the new format: note no releases ever handled public
keys so we should be OK.
The primary motivation for this change is to avoid the same fiasco
that dogs private keys: there are several incompatible private key
formats some of which are standard and some OpenSSL specific and
require various evil hacks to allow partial transparent handling and
even then it doesn't work with DER formats. Given the option anything
other than PKCS#8 should be dumped: but the other formats have to
stay in the name of compatibility.
With public keys and the benefit of hindsight one standard format
is used which works with EVP_PKEY, RSA or DSA structures: though
it clearly returns an error if you try to read the wrong kind of key.
Added a -pubkey option to the 'x509' utility to output the public key.
Also rename the EVP_PKEY_get_*() to EVP_PKEY_rget_*()
(renamed to EVP_PKEY_get1_*() in the OpenSSL 0.9.5 release) and add
EVP_PKEY_rset_*() functions (renamed to EVP_PKEY_set1_*())
that do the same as the EVP_PKEY_assign_*() except they up the
reference count of the added key (they don't "swallow" the
supplied key).
[Steve Henson]
*) Fixes to crypto/x509/by_file.c the code to read in certificates and
CRLs would fail if the file contained no certificates or no CRLs:
added a new function to read in both types and return the number
read: this means that if none are read it will be an error. The
DER versions of the certificate and CRL reader would always fail
because it isn't possible to mix certificates and CRLs in DER format
without choking one or the other routine. Changed this to just read
a certificate: this is the best we can do. Also modified the code
in apps/verify.c to take notice of return codes: it was previously
attempting to read in certificates from NULL pointers and ignoring
any errors: this is one reason why the cert and CRL reader seemed
to work. It doesn't check return codes from the default certificate
routines: these may well fail if the certificates aren't installed.
[Steve Henson]
*) Code to support otherName option in GeneralName.
[Steve Henson]
*) First update to verify code. Change the verify utility
so it warns if it is passed a self signed certificate:
for consistency with the normal behaviour. X509_verify
has been modified to it will now verify a self signed
certificate if *exactly* the same certificate appears
in the store: it was previously impossible to trust a
single self signed certificate. This means that:
openssl verify ss.pem
now gives a warning about a self signed certificate but
openssl verify -CAfile ss.pem ss.pem
is OK.
[Steve Henson]
*) For servers, store verify_result in SSL_SESSION data structure
(and add it to external session representation).
This is needed when client certificate verifications fails,
but an application-provided verification callback (set by
SSL_CTX_set_cert_verify_callback) allows accepting the session
anyway (i.e. leaves x509_store_ctx->error != X509_V_OK
but returns 1): When the session is reused, we have to set
ssl->verify_result to the appropriate error code to avoid
security holes.
[Bodo Moeller, problem pointed out by Lutz Jaenicke]
*) Fix a bug in the new PKCS#7 code: it didn't consider the
case in PKCS7_dataInit() where the signed PKCS7 structure
didn't contain any existing data because it was being created.
[Po-Cheng Chen <pocheng@nst.com.tw>, slightly modified by Steve Henson]
*) Add a salt to the key derivation routines in enc.c. This
forms the first 8 bytes of the encrypted file. Also add a
-S option to allow a salt to be input on the command line.
[Steve Henson]
*) New function X509_cmp(). Oddly enough there wasn't a function
to compare two certificates. We do this by working out the SHA1
hash and comparing that. X509_cmp() will be needed by the trust
code.
[Steve Henson]
*) SSL_get1_session() is like SSL_get_session(), but increments
the reference count in the SSL_SESSION returned.
[Geoff Thorpe <geoff@eu.c2.net>]
*) Fix for 'req': it was adding a null to request attributes.
Also change the X509_LOOKUP and X509_INFO code to handle
certificate auxiliary information.
[Steve Henson]
*) Add support for 40 and 64 bit RC2 and RC4 algorithms: document
the 'enc' command.
[Steve Henson]
*) Add the possibility to add extra information to the memory leak
detecting output, to form tracebacks, showing from where each
allocation was originated: CRYPTO_push_info("constant string") adds
the string plus current file name and line number to a per-thread
stack, CRYPTO_pop_info() does the obvious, CRYPTO_remove_all_info()
is like calling CYRPTO_pop_info() until the stack is empty.
Also updated memory leak detection code to be multi-thread-safe.
[Richard Levitte]
*) Add options -text and -noout to pkcs7 utility and delete the
encryption options which never did anything. Update docs.
[Steve Henson]
*) Add options to some of the utilities to allow the pass phrase
to be included on either the command line (not recommended on
OSes like Unix) or read from the environment. Update the
manpages and fix a few bugs.
[Steve Henson]
*) Add a few manpages for some of the openssl commands.
[Steve Henson]
*) Fix the -revoke option in ca. It was freeing up memory twice,
leaking and not finding already revoked certificates.
[Steve Henson]
*) Extensive changes to support certificate auxiliary information.
This involves the use of X509_CERT_AUX structure and X509_AUX
functions. An X509_AUX function such as PEM_read_X509_AUX()
can still read in a certificate file in the usual way but it
will also read in any additional "auxiliary information". By
doing things this way a fair degree of compatibility can be
retained: existing certificates can have this information added
using the new 'x509' options.
Current auxiliary information includes an "alias" and some trust
settings. The trust settings will ultimately be used in enhanced
certificate chain verification routines: currently a certificate
can only be trusted if it is self signed and then it is trusted
for all purposes.
[Steve Henson]
*) Fix assembler for Alpha (tested only on DEC OSF not Linux or *BSD).
The problem was that one of the replacement routines had not been working
since SSLeay releases. For now the offending routine has been replaced
with non-optimised assembler. Even so, this now gives around 95%
performance improvement for 1024 bit RSA signs.
[Mark Cox]
*) Hack to fix PKCS#7 decryption when used with some unorthodox RC2
handling. Most clients have the effective key size in bits equal to
the key length in bits: so a 40 bit RC2 key uses a 40 bit (5 byte) key.
A few however don't do this and instead use the size of the decrypted key
to determine the RC2 key length and the AlgorithmIdentifier to determine
the effective key length. In this case the effective key length can still
be 40 bits but the key length can be 168 bits for example. This is fixed
by manually forcing an RC2 key into the EVP_PKEY structure because the
EVP code can't currently handle unusual RC2 key sizes: it always assumes
the key length and effective key length are equal.
[Steve Henson]
*) Add a bunch of functions that should simplify the creation of
X509_NAME structures. Now you should be able to do:
X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC, "Steve", -1, -1, 0);
and have it automatically work out the correct field type and fill in
the structures. The more adventurous can try:
X509_NAME_add_entry_by_txt(nm, field, MBSTRING_UTF8, str, -1, -1, 0);
and it will (hopefully) work out the correct multibyte encoding.
[Steve Henson]
*) Change the 'req' utility to use the new field handling and multibyte
copy routines. Before the DN field creation was handled in an ad hoc
way in req, ca, and x509 which was rather broken and didn't support
BMPStrings or UTF8Strings. Since some software doesn't implement
BMPStrings or UTF8Strings yet, they can be enabled using the config file
using the dirstring_type option. See the new comment in the default
openssl.cnf for more info.
[Steve Henson]
*) Make crypto/rand/md_rand.c more robust:
- Assure unique random numbers after fork().
- Make sure that concurrent threads access the global counter and
md serializably so that we never lose entropy in them
or use exactly the same state in multiple threads.
Access to the large state is not always serializable because
the additional locking could be a performance killer, and
md should be large enough anyway.
[Bodo Moeller]
*) New file apps/app_rand.c with commonly needed functionality
for handling the random seed file.
Use the random seed file in some applications that previously did not:
ca,
dsaparam -genkey (which also ignored its '-rand' option),
s_client,
s_server,
x509 (when signing).
Except on systems with /dev/urandom, it is crucial to have a random
seed file at least for key creation, DSA signing, and for DH exchanges;
for RSA signatures we could do without one.
gendh and gendsa (unlike genrsa) used to read only the first byte
of each file listed in the '-rand' option. The function as previously
found in genrsa is now in app_rand.c and is used by all programs
that support '-rand'.
[Bodo Moeller]
*) In RAND_write_file, use mode 0600 for creating files;
don't just chmod when it may be too late.
[Bodo Moeller]
*) Report an error from X509_STORE_load_locations
when X509_LOOKUP_load_file or X509_LOOKUP_add_dir failed.
[Bill Perry]
*) New function ASN1_mbstring_copy() this copies a string in either
ASCII, Unicode, Universal (4 bytes per character) or UTF8 format
into an ASN1_STRING type. A mask of permissible types is passed
and it chooses the "minimal" type to use or an error if not type
is suitable.
[Steve Henson]
*) Add function equivalents to the various macros in asn1.h. The old
macros are retained with an M_ prefix. Code inside the library can
use the M_ macros. External code (including the openssl utility)
should *NOT* in order to be "shared library friendly".
[Steve Henson]
*) Add various functions that can check a certificate's extensions
to see if it usable for various purposes such as SSL client,
server or S/MIME and CAs of these types. This is currently
VERY EXPERIMENTAL but will ultimately be used for certificate chain
verification. Also added a -purpose flag to x509 utility to
print out all the purposes.
[Steve Henson]
*) Add a CRYPTO_EX_DATA to X509 certificate structure and associated
functions.
[Steve Henson]
*) New X509V3_{X509,CRL,REVOKED}_get_d2i() functions. These will search
for, obtain and decode and extension and obtain its critical flag.
This allows all the necessary extension code to be handled in a
single function call.
[Steve Henson]
*) RC4 tune-up featuring 30-40% performance improvement on most RISC
platforms. See crypto/rc4/rc4_enc.c for further details.
[Andy Polyakov]
*) New -noout option to asn1parse. This causes no output to be produced
its main use is when combined with -strparse and -out to extract data
from a file (which may not be in ASN.1 format).
[Steve Henson]
*) Fix for pkcs12 program. It was hashing an invalid certificate pointer
when producing the local key id.
[Richard Levitte <levitte@stacken.kth.se>]
*) New option -dhparam in s_server. This allows a DH parameter file to be
stated explicitly. If it is not stated then it tries the first server
certificate file. The previous behaviour hard coded the filename
"server.pem".
[Steve Henson]
*) Add -pubin and -pubout options to the rsa and dsa commands. These allow
a public key to be input or output. For example:
openssl rsa -in key.pem -pubout -out pubkey.pem
Also added necessary DSA public key functions to handle this.
[Steve Henson]
*) Fix so PKCS7_dataVerify() doesn't crash if no certificates are contained
in the message. This was handled by allowing
X509_find_by_issuer_and_serial() to tolerate a NULL passed to it.
[Steve Henson, reported by Sampo Kellomaki <sampo@mail.neuronio.pt>]
*) Fix for bug in d2i_ASN1_bytes(): other ASN1 functions add an extra null
to the end of the strings whereas this didn't. This would cause problems
if strings read with d2i_ASN1_bytes() were later modified.
[Steve Henson, reported by Arne Ansper <arne@ats.cyber.ee>]
*) Fix for base64 decode bug. When a base64 bio reads only one line of
data and it contains EOF it will end up returning an error. This is
caused by input 46 bytes long. The cause is due to the way base64
BIOs find the start of base64 encoded data. They do this by trying a
trial decode on each line until they find one that works. When they
do a flag is set and it starts again knowing it can pass all the
data directly through the decoder. Unfortunately it doesn't reset
the context it uses. This means that if EOF is reached an attempt
is made to pass two EOFs through the context and this causes the
resulting error. This can also cause other problems as well. As is
usual with these problems it takes *ages* to find and the fix is
trivial: move one line.
[Steve Henson, reported by ian@uns.ns.ac.yu (Ivan Nejgebauer) ]
*) Ugly workaround to get s_client and s_server working under Windows. The
old code wouldn't work because it needed to select() on sockets and the
tty (for keypresses and to see if data could be written). Win32 only
supports select() on sockets so we select() with a 1s timeout on the
sockets and then see if any characters are waiting to be read, if none
are present then we retry, we also assume we can always write data to
the tty. This isn't nice because the code then blocks until we've
received a complete line of data and it is effectively polling the
keyboard at 1s intervals: however it's quite a bit better than not
working at all :-) A dedicated Windows application might handle this
with an event loop for example.
[Steve Henson]
*) Enhance RSA_METHOD structure. Now there are two extra methods, rsa_sign
and rsa_verify. When the RSA_FLAGS_SIGN_VER option is set these functions
will be called when RSA_sign() and RSA_verify() are used. This is useful
if rsa_pub_dec() and rsa_priv_enc() equivalents are not available.
For this to work properly RSA_public_decrypt() and RSA_private_encrypt()
should *not* be used: RSA_sign() and RSA_verify() must be used instead.
This necessitated the support of an extra signature type NID_md5_sha1
for SSL signatures and modifications to the SSL library to use it instead
of calling RSA_public_decrypt() and RSA_private_encrypt().
[Steve Henson]
*) Add new -verify -CAfile and -CApath options to the crl program, these
will lookup a CRL issuers certificate and verify the signature in a
similar way to the verify program. Tidy up the crl program so it
no longer accesses structures directly. Make the ASN1 CRL parsing a bit
less strict. It will now permit CRL extensions even if it is not
a V2 CRL: this will allow it to tolerate some broken CRLs.
[Steve Henson]
*) Initialize all non-automatic variables each time one of the openssl
sub-programs is started (this is necessary as they may be started
multiple times from the "OpenSSL>" prompt).
[Lennart Bang, Bodo Moeller]
*) Preliminary compilation option RSA_NULL which disables RSA crypto without
removing all other RSA functionality (this is what NO_RSA does). This
is so (for example) those in the US can disable those operations covered
by the RSA patent while allowing storage and parsing of RSA keys and RSA
key generation.
[Steve Henson]
*) Non-copying interface to BIO pairs.
(still largely untested)
[Bodo Moeller]
*) New function ANS1_tag2str() to convert an ASN1 tag to a descriptive
ASCII string. This was handled independently in various places before.
[Steve Henson]
*) New functions UTF8_getc() and UTF8_putc() that parse and generate
UTF8 strings a character at a time.
[Steve Henson]
*) Use client_version from client hello to select the protocol
(s23_srvr.c) and for RSA client key exchange verification
(s3_srvr.c), as required by the SSL 3.0/TLS 1.0 specifications.
[Bodo Moeller]
*) Add various utility functions to handle SPKACs, these were previously
handled by poking round in the structure internals. Added new function
NETSCAPE_SPKI_print() to print out SPKAC and a new utility 'spkac' to
print, verify and generate SPKACs. Based on an original idea from
Massimiliano Pala <madwolf@comune.modena.it> but extensively modified.
[Steve Henson]
*) RIPEMD160 is operational on all platforms and is back in 'make test'.
[Andy Polyakov]
*) Allow the config file extension section to be overwritten on the
command line. Based on an original idea from Massimiliano Pala
<madwolf@comune.modena.it>. The new option is called -extensions
and can be applied to ca, req and x509. Also -reqexts to override
the request extensions in req and -crlexts to override the crl extensions
in ca.
[Steve Henson]
*) Add new feature to the SPKAC handling in ca. Now you can include
the same field multiple times by preceding it by "XXXX." for example:
1.OU="Unit name 1"
2.OU="Unit name 2"
this is the same syntax as used in the req config file.
[Steve Henson]
*) Allow certificate extensions to be added to certificate requests. These
are specified in a 'req_extensions' option of the req section of the
config file. They can be printed out with the -text option to req but
are otherwise ignored at present.
[Steve Henson]
*) Fix a horrible bug in enc_read() in crypto/evp/bio_enc.c: if the first
data read consists of only the final block it would not decrypted because
EVP_CipherUpdate() would correctly report zero bytes had been decrypted.
A misplaced 'break' also meant the decrypted final block might not be
copied until the next read.
[Steve Henson]
*) Initial support for DH_METHOD. Again based on RSA_METHOD. Also added
a few extra parameters to the DH structure: these will be useful if
for example we want the value of 'q' or implement X9.42 DH.
[Steve Henson]
*) Initial support for DSA_METHOD. This is based on the RSA_METHOD and
provides hooks that allow the default DSA functions or functions on a
"per key" basis to be replaced. This allows hardware acceleration and
hardware key storage to be handled without major modification to the
library. Also added low level modexp hooks and CRYPTO_EX structure and
associated functions.
[Steve Henson]
*) Add a new flag to memory BIOs, BIO_FLAG_MEM_RDONLY. This marks the BIO
as "read only": it can't be written to and the buffer it points to will
not be freed. Reading from a read only BIO is much more efficient than
a normal memory BIO. This was added because there are several times when
an area of memory needs to be read from a BIO. The previous method was
to create a memory BIO and write the data to it, this results in two
copies of the data and an O(n^2) reading algorithm. There is a new
function BIO_new_mem_buf() which creates a read only memory BIO from
an area of memory. Also modified the PKCS#7 routines to use read only
memory BIOs.
[Steve Henson]
*) Bugfix: ssl23_get_client_hello did not work properly when called in
state SSL23_ST_SR_CLNT_HELLO_B, i.e. when the first 7 bytes of
a SSLv2-compatible client hello for SSLv3 or TLSv1 could be read,
but a retry condition occurred while trying to read the rest.
[Bodo Moeller]
*) The PKCS7_ENC_CONTENT_new() function was setting the content type as
NID_pkcs7_encrypted by default: this was wrong since this should almost
always be NID_pkcs7_data. Also modified the PKCS7_set_type() to handle
the encrypted data type: this is a more sensible place to put it and it
allows the PKCS#12 code to be tidied up that duplicated this
functionality.
[Steve Henson]
*) Changed obj_dat.pl script so it takes its input and output files on
the command line. This should avoid shell escape redirection problems
under Win32.
[Steve Henson]
*) Initial support for certificate extension requests, these are included
in things like Xenroll certificate requests. Included functions to allow
extensions to be obtained and added.
[Steve Henson]
*) -crlf option to s_client and s_server for sending newlines as
CRLF (as required by many protocols).
[Bodo Moeller]
Changes between 0.9.3a and 0.9.4 [09 Aug 1999]
*) Install libRSAglue.a when OpenSSL is built with RSAref.
[Ralf S. Engelschall]
*) A few more ``#ifndef NO_FP_API / #endif'' pairs for consistency.
[Andrija Antonijevic <TheAntony2@bigfoot.com>]
*) Fix -startdate and -enddate (which was missing) arguments to 'ca'
program.
[Steve Henson]
*) New function DSA_dup_DH, which duplicates DSA parameters/keys as
DH parameters/keys (q is lost during that conversion, but the resulting
DH parameters contain its length).
For 1024-bit p, DSA_generate_parameters followed by DSA_dup_DH is
much faster than DH_generate_parameters (which creates parameters
where p = 2*q + 1), and also the smaller q makes DH computations
much more efficient (160-bit exponentiation instead of 1024-bit
exponentiation); so this provides a convenient way to support DHE
ciphersuites in SSL/TLS servers (see ssl/ssltest.c). It is of
utter importance to use
SSL_CTX_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
or
SSL_set_options(s_ctx, SSL_OP_SINGLE_DH_USE);
when such DH parameters are used, because otherwise small subgroup
attacks may become possible!
[Bodo Moeller]
*) Avoid memory leak in i2d_DHparams.
[Bodo Moeller]
*) Allow the -k option to be used more than once in the enc program:
this allows the same encrypted message to be read by multiple recipients.
[Steve Henson]
*) New function OBJ_obj2txt(buf, buf_len, a, no_name), this converts
an ASN1_OBJECT to a text string. If the "no_name" parameter is set then
it will always use the numerical form of the OID, even if it has a short
or long name.
[Steve Henson]
*) Added an extra RSA flag: RSA_FLAG_EXT_PKEY. Previously the rsa_mod_exp
method only got called if p,q,dmp1,dmq1,iqmp components were present,
otherwise bn_mod_exp was called. In the case of hardware keys for example
no private key components need be present and it might store extra data
in the RSA structure, which cannot be accessed from bn_mod_exp.
By setting RSA_FLAG_EXT_PKEY rsa_mod_exp will always be called for
private key operations.
[Steve Henson]
*) Added support for SPARC Linux.
[Andy Polyakov]
*) pem_password_cb function type incompatibly changed from
typedef int pem_password_cb(char *buf, int size, int rwflag);
to
....(char *buf, int size, int rwflag, void *userdata);
so that applications can pass data to their callbacks:
The PEM[_ASN1]_{read,write}... functions and macros now take an
additional void * argument, which is just handed through whenever
the password callback is called.
[Damien Miller <dmiller@ilogic.com.au>; tiny changes by Bodo Moeller]
New function SSL_CTX_set_default_passwd_cb_userdata.
Compatibility note: As many C implementations push function arguments
onto the stack in reverse order, the new library version is likely to
interoperate with programs that have been compiled with the old
pem_password_cb definition (PEM_whatever takes some data that
happens to be on the stack as its last argument, and the callback
just ignores this garbage); but there is no guarantee whatsoever that
this will work.
*) The -DPLATFORM="\"$(PLATFORM)\"" definition and the similar -DCFLAGS=...
(both in crypto/Makefile.ssl for use by crypto/cversion.c) caused
problems not only on Windows, but also on some Unix platforms.
To avoid problematic command lines, these definitions are now in an
auto-generated file crypto/buildinf.h (created by crypto/Makefile.ssl
for standard "make" builds, by util/mk1mf.pl for "mk1mf" builds).
[Bodo Moeller]
*) MIPS III/IV assembler module is reimplemented.
[Andy Polyakov]
*) More DES library cleanups: remove references to srand/rand and
delete an unused file.
[Ulf Möller]
*) Add support for the free Netwide assembler (NASM) under Win32,
since not many people have MASM (ml) and it can be hard to obtain.
This is currently experimental but it seems to work OK and pass all
the tests. Check out INSTALL.W32 for info.
[Steve Henson]
*) Fix memory leaks in s3_clnt.c: All non-anonymous SSL3/TLS1 connections
without temporary keys kept an extra copy of the server key,
and connections with temporary keys did not free everything in case
of an error.
[Bodo Moeller]
*) New function RSA_check_key and new openssl rsa option -check
for verifying the consistency of RSA keys.
[Ulf Moeller, Bodo Moeller]
*) Various changes to make Win32 compile work:
1. Casts to avoid "loss of data" warnings in p5_crpt2.c
2. Change unsigned int to int in b_dump.c to avoid "signed/unsigned
comparison" warnings.
3. Add sk_<TYPE>_sort to DEF file generator and do make update.
[Steve Henson]
*) Add a debugging option to PKCS#5 v2 key generation function: when
you #define DEBUG_PKCS5V2 passwords, salts, iteration counts and
derived keys are printed to stderr.
[Steve Henson]
*) Copy the flags in ASN1_STRING_dup().
[Roman E. Pavlov <pre@mo.msk.ru>]
*) The x509 application mishandled signing requests containing DSA
keys when the signing key was also DSA and the parameters didn't match.
It was supposed to omit the parameters when they matched the signing key:
the verifying software was then supposed to automatically use the CA's
parameters if they were absent from the end user certificate.
Omitting parameters is no longer recommended. The test was also
the wrong way round! This was probably due to unusual behaviour in
EVP_cmp_parameters() which returns 1 if the parameters match.
This meant that parameters were omitted when they *didn't* match and
the certificate was useless. Certificates signed with 'ca' didn't have
this bug.
[Steve Henson, reported by Doug Erickson <Doug.Erickson@Part.NET>]
*) Memory leak checking (-DCRYPTO_MDEBUG) had some problems.
The interface is as follows:
Applications can use
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON) aka MemCheck_start(),
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF) aka MemCheck_stop();
"off" is now the default.
The library internally uses
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE) aka MemCheck_off(),
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE) aka MemCheck_on()
to disable memory-checking temporarily.
Some inconsistent states that previously were possible (and were
even the default) are now avoided.
-DCRYPTO_MDEBUG_TIME is new and additionally stores the current time
with each memory chunk allocated; this is occasionally more helpful
than just having a counter.
-DCRYPTO_MDEBUG_THREAD is also new and adds the thread ID.
-DCRYPTO_MDEBUG_ALL enables all of the above, plus any future
extensions.
[Bodo Moeller]
*) Introduce "mode" for SSL structures (with defaults in SSL_CTX),
which largely parallels "options", but is for changing API behaviour,
whereas "options" are about protocol behaviour.
Initial "mode" flags are:
SSL_MODE_ENABLE_PARTIAL_WRITE Allow SSL_write to report success when
a single record has been written.
SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER Don't insist that SSL_write
retries use the same buffer location.
(But all of the contents must be
copied!)
[Bodo Moeller]
*) Bugfix: SSL_set_options ignored its parameter, only SSL_CTX_set_options
worked.
*) Fix problems with no-hmac etc.
[Ulf Möller, pointed out by Brian Wellington <bwelling@tislabs.com>]
*) New functions RSA_get_default_method(), RSA_set_method() and
RSA_get_method(). These allows replacement of RSA_METHODs without having
to mess around with the internals of an RSA structure.
[Steve Henson]
*) Fix memory leaks in DSA_do_sign and DSA_is_prime.
Also really enable memory leak checks in openssl.c and in some
test programs.
[Chad C. Mulligan, Bodo Moeller]
*) Fix a bug in d2i_ASN1_INTEGER() and i2d_ASN1_INTEGER() which can mess
up the length of negative integers. This has now been simplified to just
store the length when it is first determined and use it later, rather
than trying to keep track of where data is copied and updating it to
point to the end.
[Steve Henson, reported by Brien Wheeler
<bwheeler@authentica-security.com>]
*) Add a new function PKCS7_signatureVerify. This allows the verification
of a PKCS#7 signature but with the signing certificate passed to the
function itself. This contrasts with PKCS7_dataVerify which assumes the
certificate is present in the PKCS#7 structure. This isn't always the
case: certificates can be omitted from a PKCS#7 structure and be
distributed by "out of band" means (such as a certificate database).
[Steve Henson]
*) Complete the PEM_* macros with DECLARE_PEM versions to replace the
function prototypes in pem.h, also change util/mkdef.pl to add the
necessary function names.
[Steve Henson]
*) mk1mf.pl (used by Windows builds) did not properly read the
options set by Configure in the top level Makefile, and Configure
was not even able to write more than one option correctly.
Fixed, now "no-idea no-rc5 -DCRYPTO_MDEBUG" etc. works as intended.
[Bodo Moeller]
*) New functions CONF_load_bio() and CONF_load_fp() to allow a config
file to be loaded from a BIO or FILE pointer. The BIO version will
for example allow memory BIOs to contain config info.
[Steve Henson]
*) New function "CRYPTO_num_locks" that returns CRYPTO_NUM_LOCKS.
Whoever hopes to achieve shared-library compatibility across versions
must use this, not the compile-time macro.
(Exercise 0.9.4: Which is the minimum library version required by
such programs?)
Note: All this applies only to multi-threaded programs, others don't
need locks.
[Bodo Moeller]
*) Add missing case to s3_clnt.c state machine -- one of the new SSL tests
through a BIO pair triggered the default case, i.e.
SSLerr(...,SSL_R_UNKNOWN_STATE).
[Bodo Moeller]
*) New "BIO pair" concept (crypto/bio/bss_bio.c) so that applications
can use the SSL library even if none of the specific BIOs is
appropriate.
[Bodo Moeller]
*) Fix a bug in i2d_DSAPublicKey() which meant it returned the wrong value
for the encoded length.
[Jeon KyoungHo <khjeon@sds.samsung.co.kr>]
*) Add initial documentation of the X509V3 functions.
[Steve Henson]
*) Add a new pair of functions PEM_write_PKCS8PrivateKey() and
PEM_write_bio_PKCS8PrivateKey() that are equivalent to
PEM_write_PrivateKey() and PEM_write_bio_PrivateKey() but use the more
secure PKCS#8 private key format with a high iteration count.
[Steve Henson]
*) Fix determination of Perl interpreter: A perl or perl5
_directory_ in $PATH was also accepted as the interpreter.
[Ralf S. Engelschall]
*) Fix demos/sign/sign.c: well there wasn't anything strictly speaking
wrong with it but it was very old and did things like calling
PEM_ASN1_read() directly and used MD5 for the hash not to mention some
unusual formatting.
[Steve Henson]
*) Fix demos/selfsign.c: it used obsolete and deleted functions, changed
to use the new extension code.
[Steve Henson]
*) Implement the PEM_read/PEM_write functions in crypto/pem/pem_all.c
with macros. This should make it easier to change their form, add extra
arguments etc. Fix a few PEM prototypes which didn't have cipher as a
constant.
[Steve Henson]
*) Add to configuration table a new entry that can specify an alternative
name for unistd.h (for pre-POSIX systems); we need this for NeXTstep,
according to Mark Crispin <MRC@Panda.COM>.
[Bodo Moeller]
#if 0
*) DES CBC did not update the IV. Weird.
[Ben Laurie]
#else
des_cbc_encrypt does not update the IV, but des_ncbc_encrypt does.
Changing the behaviour of the former might break existing programs --
where IV updating is needed, des_ncbc_encrypt can be used.
#endif
*) When bntest is run from "make test" it drives bc to check its
calculations, as well as internally checking them. If an internal check
fails, it needs to cause bc to give a non-zero result or make test carries
on without noticing the failure. Fixed.
[Ben Laurie]
*) DES library cleanups.
[Ulf Möller]
*) Add support for PKCS#5 v2.0 PBE algorithms. This will permit PKCS#8 to be
used with any cipher unlike PKCS#5 v1.5 which can at most handle 64 bit
ciphers. NOTE: although the key derivation function has been verified
against some published test vectors it has not been extensively tested
yet. Added a -v2 "cipher" option to pkcs8 application to allow the use
of v2.0.
[Steve Henson]
*) Instead of "mkdir -p", which is not fully portable, use new
Perl script "util/mkdir-p.pl".
[Bodo Moeller]
*) Rewrite the way password based encryption (PBE) is handled. It used to
assume that the ASN1 AlgorithmIdentifier parameter was a PBEParameter
structure. This was true for the PKCS#5 v1.5 and PKCS#12 PBE algorithms
but doesn't apply to PKCS#5 v2.0 where it can be something else. Now
the 'parameter' field of the AlgorithmIdentifier is passed to the
underlying key generation function so it must do its own ASN1 parsing.
This has also changed the EVP_PBE_CipherInit() function which now has a
'parameter' argument instead of literal salt and iteration count values
and the function EVP_PBE_ALGOR_CipherInit() has been deleted.
[Steve Henson]
*) Support for PKCS#5 v1.5 compatible password based encryption algorithms
and PKCS#8 functionality. New 'pkcs8' application linked to openssl.
Needed to change the PEM_STRING_EVP_PKEY value which was just "PRIVATE
KEY" because this clashed with PKCS#8 unencrypted string. Since this
value was just used as a "magic string" and not used directly its
value doesn't matter.
[Steve Henson]
*) Introduce some semblance of const correctness to BN. Shame C doesn't
support mutable.
[Ben Laurie]
*) "linux-sparc64" configuration (ultrapenguin).
[Ray Miller <ray.miller@oucs.ox.ac.uk>]
"linux-sparc" configuration.
[Christian Forster <fo@hawo.stw.uni-erlangen.de>]
*) config now generates no-xxx options for missing ciphers.
[Ulf Möller]
*) Support the EBCDIC character set (work in progress).
File ebcdic.c not yet included because it has a different license.
[Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>]
*) Support BS2000/OSD-POSIX.
[Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>]
*) Make callbacks for key generation use void * instead of char *.
[Ben Laurie]
*) Make S/MIME samples compile (not yet tested).
[Ben Laurie]
*) Additional typesafe stacks.
[Ben Laurie]
*) New configuration variants "bsdi-elf-gcc" (BSD/OS 4.x).
[Bodo Moeller]
Changes between 0.9.3 and 0.9.3a [29 May 1999]
*) New configuration variant "sco5-gcc".
*) Updated some demos.
[Sean O Riordain, Wade Scholine]
*) Add missing BIO_free at exit of pkcs12 application.
[Wu Zhigang]
*) Fix memory leak in conf.c.
[Steve Henson]
*) Updates for Win32 to assembler version of MD5.
[Steve Henson]
*) Set #! path to perl in apps/der_chop to where we found it
instead of using a fixed path.
[Bodo Moeller]
*) SHA library changes for irix64-mips4-cc.
[Andy Polyakov]
*) Improvements for VMS support.
[Richard Levitte]
Changes between 0.9.2b and 0.9.3 [24 May 1999]
*) Bignum library bug fix. IRIX 6 passes "make test" now!
This also avoids the problems with SC4.2 and unpatched SC5.
[Andy Polyakov <appro@fy.chalmers.se>]
*) New functions sk_num, sk_value and sk_set to replace the previous macros.
These are required because of the typesafe stack would otherwise break
existing code. If old code used a structure member which used to be STACK
and is now STACK_OF (for example cert in a PKCS7_SIGNED structure) with
sk_num or sk_value it would produce an error because the num, data members
are not present in STACK_OF. Now it just produces a warning. sk_set
replaces the old method of assigning a value to sk_value
(e.g. sk_value(x, i) = y) which the library used in a few cases. Any code
that does this will no longer work (and should use sk_set instead) but
this could be regarded as a "questionable" behaviour anyway.
[Steve Henson]
*) Fix most of the other PKCS#7 bugs. The "experimental" code can now
correctly handle encrypted S/MIME data.
[Steve Henson]
*) Change type of various DES function arguments from des_cblock
(which means, in function argument declarations, pointer to char)
to des_cblock * (meaning pointer to array with 8 char elements),
which allows the compiler to do more typechecking; it was like
that back in SSLeay, but with lots of ugly casts.
Introduce new type const_des_cblock.
[Bodo Moeller]
*) Reorganise the PKCS#7 library and get rid of some of the more obvious
problems: find RecipientInfo structure that matches recipient certificate
and initialise the ASN1 structures properly based on passed cipher.
[Steve Henson]
*) Belatedly make the BN tests actually check the results.
[Ben Laurie]
*) Fix the encoding and decoding of negative ASN1 INTEGERS and conversion
to and from BNs: it was completely broken. New compilation option
NEG_PUBKEY_BUG to allow for some broken certificates that encode public
key elements as negative integers.
[Steve Henson]
*) Reorganize and speed up MD5.
[Andy Polyakov <appro@fy.chalmers.se>]
*) VMS support.
[Richard Levitte <richard@levitte.org>]
*) New option -out to asn1parse to allow the parsed structure to be
output to a file. This is most useful when combined with the -strparse
option to examine the output of things like OCTET STRINGS.
[Steve Henson]
*) Make SSL library a little more fool-proof by not requiring any longer
that SSL_set_{accept,connect}_state be called before
SSL_{accept,connect} may be used (SSL_set_..._state is omitted
in many applications because usually everything *appeared* to work as
intended anyway -- now it really works as intended).
[Bodo Moeller]
*) Move openssl.cnf out of lib/.
[Ulf Möller]
*) Fix various things to let OpenSSL even pass ``egcc -pipe -O2 -Wall
-Wshadow -Wpointer-arith -Wcast-align -Wmissing-prototypes
-Wmissing-declarations -Wnested-externs -Winline'' with EGCS 1.1.2+
[Ralf S. Engelschall]
*) Various fixes to the EVP and PKCS#7 code. It may now be able to
handle PKCS#7 enveloped data properly.
[Sebastian Akerman <sak@parallelconsulting.com>, modified by Steve]
*) Create a duplicate of the SSL_CTX's CERT in SSL_new instead of
copying pointers. The cert_st handling is changed by this in
various ways (and thus what used to be known as ctx->default_cert
is now called ctx->cert, since we don't resort to s->ctx->[default_]cert
any longer when s->cert does not give us what we need).
ssl_cert_instantiate becomes obsolete by this change.
As soon as we've got the new code right (possibly it already is?),
we have solved a couple of bugs of the earlier code where s->cert
was used as if it could not have been shared with other SSL structures.
Note that using the SSL API in certain dirty ways now will result
in different behaviour than observed with earlier library versions:
Changing settings for an SSL_CTX *ctx after having done s = SSL_new(ctx)
does not influence s as it used to.
In order to clean up things more thoroughly, inside SSL_SESSION
we don't use CERT any longer, but a new structure SESS_CERT
that holds per-session data (if available); currently, this is
the peer's certificate chain and, for clients, the server's certificate
and temporary key. CERT holds only those values that can have
meaningful defaults in an SSL_CTX.
[Bodo Moeller]
*) New function X509V3_EXT_i2d() to create an X509_EXTENSION structure
from the internal representation. Various PKCS#7 fixes: remove some
evil casts and set the enc_dig_alg field properly based on the signing
key type.
[Steve Henson]
*) Allow PKCS#12 password to be set from the command line or the
environment. Let 'ca' get its config file name from the environment
variables "OPENSSL_CONF" or "SSLEAY_CONF" (for consistency with 'req'
and 'x509').
[Steve Henson]
*) Allow certificate policies extension to use an IA5STRING for the
organization field. This is contrary to the PKIX definition but
VeriSign uses it and IE5 only recognises this form. Document 'x509'
extension option.
[Steve Henson]
*) Add PEDANTIC compiler flag to allow compilation with gcc -pedantic,
without disallowing inline assembler and the like for non-pedantic builds.
[Ben Laurie]
*) Support Borland C++ builder.
[Janez Jere <jj@void.si>, modified by Ulf Möller]
*) Support Mingw32.
[Ulf Möller]
*) SHA-1 cleanups and performance enhancements.
[Andy Polyakov <appro@fy.chalmers.se>]
*) Sparc v8plus assembler for the bignum library.
[Andy Polyakov <appro@fy.chalmers.se>]
*) Accept any -xxx and +xxx compiler options in Configure.
[Ulf Möller]
*) Update HPUX configuration.
[Anonymous]
*) Add missing sk_<type>_unshift() function to safestack.h
[Ralf S. Engelschall]
*) New function SSL_CTX_use_certificate_chain_file that sets the
"extra_cert"s in addition to the certificate. (This makes sense
only for "PEM" format files, as chains as a whole are not
DER-encoded.)
[Bodo Moeller]
*) Support verify_depth from the SSL API.
x509_vfy.c had what can be considered an off-by-one-error:
Its depth (which was not part of the external interface)
was actually counting the number of certificates in a chain;
now it really counts the depth.
[Bodo Moeller]
*) Bugfix in crypto/x509/x509_cmp.c: The SSLerr macro was used
instead of X509err, which often resulted in confusing error
messages since the error codes are not globally unique
(e.g. an alleged error in ssl3_accept when a certificate
didn't match the private key).
*) New function SSL_CTX_set_session_id_context that allows to set a default
value (so that you don't need SSL_set_session_id_context for each
connection using the SSL_CTX).
[Bodo Moeller]
*) OAEP decoding bug fix.
[Ulf Möller]
*) Support INSTALL_PREFIX for package builders, as proposed by
David Harris.
[Bodo Moeller]
*) New Configure options "threads" and "no-threads". For systems
where the proper compiler options are known (currently Solaris
and Linux), "threads" is the default.
[Bodo Moeller]
*) New script util/mklink.pl as a faster substitute for util/mklink.sh.
[Bodo Moeller]
*) Install various scripts to $(OPENSSLDIR)/misc, not to
$(INSTALLTOP)/bin -- they shouldn't clutter directories
such as /usr/local/bin.
[Bodo Moeller]
*) "make linux-shared" to build shared libraries.
[Niels Poppe <niels@netbox.org>]
*) New Configure option no-<cipher> (rsa, idea, rc5, ...).
[Ulf Möller]
*) Add the PKCS#12 API documentation to openssl.txt. Preliminary support for
extension adding in x509 utility.
[Steve Henson]
*) Remove NOPROTO sections and error code comments.
[Ulf Möller]
*) Partial rewrite of the DEF file generator to now parse the ANSI
prototypes.
[Steve Henson]
*) New Configure options --prefix=DIR and --openssldir=DIR.
[Ulf Möller]
*) Complete rewrite of the error code script(s). It is all now handled
by one script at the top level which handles error code gathering,
header rewriting and C source file generation. It should be much better
than the old method: it now uses a modified version of Ulf's parser to
read the ANSI prototypes in all header files (thus the old K&R definitions
aren't needed for error creation any more) and do a better job of
translating function codes into names. The old 'ASN1 error code imbedded
in a comment' is no longer necessary and it doesn't use .err files which
have now been deleted. Also the error code call doesn't have to appear all
on one line (which resulted in some large lines...).
[Steve Henson]
*) Change #include filenames from <foo.h> to <openssl/foo.h>.
[Bodo Moeller]
*) Change behaviour of ssl2_read when facing length-0 packets: Don't return
0 (which usually indicates a closed connection), but continue reading.
[Bodo Moeller]
*) Fix some race conditions.
[Bodo Moeller]
*) Add support for CRL distribution points extension. Add Certificate
Policies and CRL distribution points documentation.
[Steve Henson]
*) Move the autogenerated header file parts to crypto/opensslconf.h.
[Ulf Möller]
*) Fix new 56-bit DES export ciphersuites: they were using 7 bytes instead of
8 of keying material. Merlin has also confirmed interop with this fix
between OpenSSL and Baltimore C/SSL 2.0 and J/SSL 2.0.
[Merlin Hughes <merlin@baltimore.ie>]
*) Fix lots of warnings.
[Richard Levitte <levitte@stacken.kth.se>]
*) In add_cert_dir() in crypto/x509/by_dir.c, break out of the loop if
the directory spec didn't end with a LIST_SEPARATOR_CHAR.
[Richard Levitte <levitte@stacken.kth.se>]
*) Fix problems with sizeof(long) == 8.
[Andy Polyakov <appro@fy.chalmers.se>]
*) Change functions to ANSI C.
[Ulf Möller]
*) Fix typos in error codes.
[Martin Kraemer <Martin.Kraemer@MchP.Siemens.De>, Ulf Möller]
*) Remove defunct assembler files from Configure.
[Ulf Möller]
*) SPARC v8 assembler BIGNUM implementation.
[Andy Polyakov <appro@fy.chalmers.se>]
*) Support for Certificate Policies extension: both print and set.
Various additions to support the r2i method this uses.
[Steve Henson]
*) A lot of constification, and fix a bug in X509_NAME_oneline() that could
return a const string when you are expecting an allocated buffer.
[Ben Laurie]
*) Add support for ASN1 types UTF8String and VISIBLESTRING, also the CHOICE
types DirectoryString and DisplayText.
[Steve Henson]
*) Add code to allow r2i extensions to access the configuration database,
add an LHASH database driver and add several ctx helper functions.
[Steve Henson]
*) Fix an evil bug in bn_expand2() which caused various BN functions to
fail when they extended the size of a BIGNUM.
[Steve Henson]
*) Various utility functions to handle SXNet extension. Modify mkdef.pl to
support typesafe stack.
[Steve Henson]
*) Fix typo in SSL_[gs]et_options().
[Nils Frostberg <nils@medcom.se>]
*) Delete various functions and files that belonged to the (now obsolete)
old X509V3 handling code.
[Steve Henson]
*) New Configure option "rsaref".
[Ulf Möller]
*) Don't auto-generate pem.h.
[Bodo Moeller]
*) Introduce type-safe ASN.1 SETs.
[Ben Laurie]
*) Convert various additional casted stacks to type-safe STACK_OF() variants.
[Ben Laurie, Ralf S. Engelschall, Steve Henson]
*) Introduce type-safe STACKs. This will almost certainly break lots of code
that links with OpenSSL (well at least cause lots of warnings), but fear
not: the conversion is trivial, and it eliminates loads of evil casts. A
few STACKed things have been converted already. Feel free to convert more.
In the fullness of time, I'll do away with the STACK type altogether.
[Ben Laurie]
*) Add `openssl ca -revoke <certfile>' facility which revokes a certificate
specified in <certfile> by updating the entry in the index.txt file.
This way one no longer has to edit the index.txt file manually for
revoking a certificate. The -revoke option does the gory details now.
[Massimiliano Pala <madwolf@openca.org>, Ralf S. Engelschall]
*) Fix `openssl crl -noout -text' combination where `-noout' killed the
`-text' option at all and this way the `-noout -text' combination was
inconsistent in `openssl crl' with the friends in `openssl x509|rsa|dsa'.
[Ralf S. Engelschall]
*) Make sure a corresponding plain text error message exists for the
X509_V_ERR_CERT_REVOKED/23 error number which can occur when a
verify callback function determined that a certificate was revoked.
[Ralf S. Engelschall]
*) Bugfix: In test/testenc, don't test "openssl <cipher>" for
ciphers that were excluded, e.g. by -DNO_IDEA. Also, test
all available ciphers including rc5, which was forgotten until now.
In order to let the testing shell script know which algorithms
are available, a new (up to now undocumented) command
"openssl list-cipher-commands" is used.
[Bodo Moeller]
*) Bugfix: s_client occasionally would sleep in select() when
it should have checked SSL_pending() first.
[Bodo Moeller]
*) New functions DSA_do_sign and DSA_do_verify to provide access to
the raw DSA values prior to ASN.1 encoding.
[Ulf Möller]
*) Tweaks to Configure
[Niels Poppe <niels@netbox.org>]
*) Add support for PKCS#5 v2.0 ASN1 PBES2 structures. No other support,
yet...
[Steve Henson]
*) New variables $(RANLIB) and $(PERL) in the Makefiles.
[Ulf Möller]
*) New config option to avoid instructions that are illegal on the 80386.
The default code is faster, but requires at least a 486.
[Ulf Möller]
*) Got rid of old SSL2_CLIENT_VERSION (inconsistently used) and
SSL2_SERVER_VERSION (not used at all) macros, which are now the
same as SSL2_VERSION anyway.
[Bodo Moeller]
*) New "-showcerts" option for s_client.
[Bodo Moeller]
*) Still more PKCS#12 integration. Add pkcs12 application to openssl
application. Various cleanups and fixes.
[Steve Henson]
*) More PKCS#12 integration. Add new pkcs12 directory with Makefile.ssl and
modify error routines to work internally. Add error codes and PBE init
to library startup routines.
[Steve Henson]
*) Further PKCS#12 integration. Added password based encryption, PKCS#8 and
packing functions to asn1 and evp. Changed function names and error
codes along the way.
[Steve Henson]
*) PKCS12 integration: and so it begins... First of several patches to
slowly integrate PKCS#12 functionality into OpenSSL. Add PKCS#12
objects to objects.h
[Steve Henson]
*) Add a new 'indent' option to some X509V3 extension code. Initial ASN1
and display support for Thawte strong extranet extension.
[Steve Henson]
*) Add LinuxPPC support.
[Jeff Dubrule <igor@pobox.org>]
*) Get rid of redundant BN file bn_mulw.c, and rename bn_div64 to
bn_div_words in alpha.s.
[Hannes Reinecke <H.Reinecke@hw.ac.uk> and Ben Laurie]
*) Make sure the RSA OAEP test is skipped under -DRSAref because
OAEP isn't supported when OpenSSL is built with RSAref.
[Ulf Moeller <ulf@fitug.de>]
*) Move definitions of IS_SET/IS_SEQUENCE inside crypto/asn1/asn1.h
so they no longer are missing under -DNOPROTO.
[Soren S. Jorvang <soren@t.dk>]
Changes between 0.9.1c and 0.9.2b [22 Mar 1999]
*) Make SSL_get_peer_cert_chain() work in servers. Unfortunately, it still
doesn't work when the session is reused. Coming soon!
[Ben Laurie]
*) Fix a security hole, that allows sessions to be reused in the wrong
context thus bypassing client cert protection! All software that uses
client certs and session caches in multiple contexts NEEDS PATCHING to
allow session reuse! A fuller solution is in the works.
[Ben Laurie, problem pointed out by Holger Reif, Bodo Moeller (and ???)]
*) Some more source tree cleanups (removed obsolete files
crypto/bf/asm/bf586.pl, test/test.txt and crypto/sha/asm/f.s; changed
permission on "config" script to be executable) and a fix for the INSTALL
document.
[Ulf Moeller <ulf@fitug.de>]
*) Remove some legacy and erroneous uses of malloc, free instead of
Malloc, Free.
[Lennart Bang <lob@netstream.se>, with minor changes by Steve]
*) Make rsa_oaep_test return non-zero on error.
[Ulf Moeller <ulf@fitug.de>]
*) Add support for native Solaris shared libraries. Configure
solaris-sparc-sc4-pic, make, then run shlib/solaris-sc4.sh. It'd be nice
if someone would make that last step automatic.
[Matthias Loepfe <Matthias.Loepfe@AdNovum.CH>]
*) ctx_size was not built with the right compiler during "make links". Fixed.
[Ben Laurie]
*) Change the meaning of 'ALL' in the cipher list. It now means "everything
except NULL ciphers". This means the default cipher list will no longer
enable NULL ciphers. They need to be specifically enabled e.g. with
the string "DEFAULT:eNULL".
[Steve Henson]
*) Fix to RSA private encryption routines: if p < q then it would
occasionally produce an invalid result. This will only happen with
externally generated keys because OpenSSL (and SSLeay) ensure p > q.
[Steve Henson]
*) Be less restrictive and allow also `perl util/perlpath.pl
/path/to/bin/perl' in addition to `perl util/perlpath.pl /path/to/bin',
because this way one can also use an interpreter named `perl5' (which is
usually the name of Perl 5.xxx on platforms where an Perl 4.x is still
installed as `perl').
[Matthias Loepfe <Matthias.Loepfe@adnovum.ch>]
*) Let util/clean-depend.pl work also with older Perl 5.00x versions.
[Matthias Loepfe <Matthias.Loepfe@adnovum.ch>]
*) Fix Makefile.org so CC,CFLAG etc are passed to 'make links' add
advapi32.lib to Win32 build and change the pem test comparison
to fc.exe (thanks to Ulrich Kroener <kroneru@yahoo.com> for the
suggestion). Fix misplaced ASNI prototypes and declarations in evp.h
and crypto/des/ede_cbcm_enc.c.
[Steve Henson]
*) DES quad checksum was broken on big-endian architectures. Fixed.
[Ben Laurie]
*) Comment out two functions in bio.h that aren't implemented. Fix up the
Win32 test batch file so it (might) work again. The Win32 test batch file
is horrible: I feel ill....
[Steve Henson]
*) Move various #ifdefs around so NO_SYSLOG, NO_DIRENT etc are now selected
in e_os.h. Audit of header files to check ANSI and non ANSI
sections: 10 functions were absent from non ANSI section and not exported
from Windows DLLs. Fixed up libeay.num for new functions.
[Steve Henson]
*) Make `openssl version' output lines consistent.
[Ralf S. Engelschall]
*) Fix Win32 symbol export lists for BIO functions: Added
BIO_get_ex_new_index, BIO_get_ex_num, BIO_get_ex_data and BIO_set_ex_data
to ms/libeay{16,32}.def.
[Ralf S. Engelschall]
*) Second round of fixing the OpenSSL perl/ stuff. It now at least compiled
fine under Unix and passes some trivial tests I've now added. But the
whole stuff is horribly incomplete, so a README.1ST with a disclaimer was
added to make sure no one expects that this stuff really works in the
OpenSSL 0.9.2 release. Additionally I've started to clean the XS sources
up and fixed a few little bugs and inconsistencies in OpenSSL.{pm,xs} and
openssl_bio.xs.
[Ralf S. Engelschall]
*) Fix the generation of two part addresses in perl.
[Kenji Miyake <kenji@miyake.org>, integrated by Ben Laurie]
*) Add config entry for Linux on MIPS.
[John Tobey <jtobey@channel1.com>]
*) Make links whenever Configure is run, unless we are on Windoze.
[Ben Laurie]
*) Permit extensions to be added to CRLs using crl_section in openssl.cnf.
Currently only issuerAltName and AuthorityKeyIdentifier make any sense
in CRLs.
[Steve Henson]
*) Add a useful kludge to allow package maintainers to specify compiler and
other platforms details on the command line without having to patch the
Configure script everytime: One now can use ``perl Configure
<id>:<details>'', i.e. platform ids are allowed to have details appended
to them (separated by colons). This is treated as there would be a static
pre-configured entry in Configure's %table under key <id> with value
<details> and ``perl Configure <id>'' is called. So, when you want to
perform a quick test-compile under FreeBSD 3.1 with pgcc and without
assembler stuff you can use ``perl Configure "FreeBSD-elf:pgcc:-O6:::"''
now, which overrides the FreeBSD-elf entry on-the-fly.
[Ralf S. Engelschall]
*) Disable new TLS1 ciphersuites by default: they aren't official yet.
[Ben Laurie]
*) Allow DSO flags like -fpic, -fPIC, -KPIC etc. to be specified
on the `perl Configure ...' command line. This way one can compile
OpenSSL libraries with Position Independent Code (PIC) which is needed
for linking it into DSOs.
[Ralf S. Engelschall]
*) Remarkably, export ciphers were totally broken and no-one had noticed!
Fixed.
[Ben Laurie]
*) Cleaned up the LICENSE document: The official contact for any license
questions now is the OpenSSL core team under openssl-core@openssl.org.
And add a paragraph about the dual-license situation to make sure people
recognize that _BOTH_ the OpenSSL license _AND_ the SSLeay license apply
to the OpenSSL toolkit.
[Ralf S. Engelschall]
*) General source tree makefile cleanups: Made `making xxx in yyy...'
display consistent in the source tree and replaced `/bin/rm' by `rm'.
Additionally cleaned up the `make links' target: Remove unnecessary
semicolons, subsequent redundant removes, inline point.sh into mklink.sh
to speed processing and no longer clutter the display with confusing
stuff. Instead only the actually done links are displayed.
[Ralf S. Engelschall]
*) Permit null encryption ciphersuites, used for authentication only. It used
to be necessary to set the preprocessor define SSL_ALLOW_ENULL to do this.
It is now necessary to set SSL_FORBID_ENULL to prevent the use of null
encryption.
[Ben Laurie]
*) Add a bunch of fixes to the PKCS#7 stuff. It used to sometimes reorder
signed attributes when verifying signatures (this would break them),
the detached data encoding was wrong and public keys obtained using
X509_get_pubkey() weren't freed.
[Steve Henson]
*) Add text documentation for the BUFFER functions. Also added a work around
to a Win95 console bug. This was triggered by the password read stuff: the
last character typed gets carried over to the next fread(). If you were
generating a new cert request using 'req' for example then the last
character of the passphrase would be CR which would then enter the first
field as blank.
[Steve Henson]
*) Added the new `Includes OpenSSL Cryptography Software' button as
doc/openssl_button.{gif,html} which is similar in style to the old SSLeay
button and can be used by applications based on OpenSSL to show the
relationship to the OpenSSL project.
[Ralf S. Engelschall]
*) Remove confusing variables in function signatures in files
ssl/ssl_lib.c and ssl/ssl.h.
[Lennart Bong <lob@kulthea.stacken.kth.se>]
*) Don't install bss_file.c under PREFIX/include/
[Lennart Bong <lob@kulthea.stacken.kth.se>]
*) Get the Win32 compile working again. Modify mkdef.pl so it can handle
functions that return function pointers and has support for NT specific
stuff. Fix mk1mf.pl and VC-32.pl to support NT differences also. Various
#ifdef WIN32 and WINNTs sprinkled about the place and some changes from
unsigned to signed types: this was killing the Win32 compile.
[Steve Henson]
*) Add new certificate file to stack functions,
SSL_add_dir_cert_subjects_to_stack() and
SSL_add_file_cert_subjects_to_stack(). These largely supplant
SSL_load_client_CA_file(), and can be used to add multiple certs easily
to a stack (usually this is then handed to SSL_CTX_set_client_CA_list()).
This means that Apache-SSL and similar packages don't have to mess around
to add as many CAs as they want to the preferred list.
[Ben Laurie]
*) Experiment with doxygen documentation. Currently only partially applied to
ssl/ssl_lib.c.
See http://www.stack.nl/~dimitri/doxygen/index.html, and run doxygen with
openssl.doxy as the configuration file.
[Ben Laurie]
*) Get rid of remaining C++-style comments which strict C compilers hate.
[Ralf S. Engelschall, pointed out by Carlos Amengual]
*) Changed BN_RECURSION in bn_mont.c to BN_RECURSION_MONT so it is not
compiled in by default: it has problems with large keys.
[Steve Henson]
*) Add a bunch of SSL_xxx() functions for configuring the temporary RSA and
DH private keys and/or callback functions which directly correspond to
their SSL_CTX_xxx() counterparts but work on a per-connection basis. This
is needed for applications which have to configure certificates on a
per-connection basis (e.g. Apache+mod_ssl) instead of a per-context basis
(e.g. s_server).
For the RSA certificate situation is makes no difference, but
for the DSA certificate situation this fixes the "no shared cipher"
problem where the OpenSSL cipher selection procedure failed because the
temporary keys were not overtaken from the context and the API provided
no way to reconfigure them.
The new functions now let applications reconfigure the stuff and they
are in detail: SSL_need_tmp_RSA, SSL_set_tmp_rsa, SSL_set_tmp_dh,
SSL_set_tmp_rsa_callback and SSL_set_tmp_dh_callback. Additionally a new
non-public-API function ssl_cert_instantiate() is used as a helper
function and also to reduce code redundancy inside ssl_rsa.c.
[Ralf S. Engelschall]
*) Move s_server -dcert and -dkey options out of the undocumented feature
area because they are useful for the DSA situation and should be
recognized by the users.
[Ralf S. Engelschall]
*) Fix the cipher decision scheme for export ciphers: the export bits are
*not* within SSL_MKEY_MASK or SSL_AUTH_MASK, they are within
SSL_EXP_MASK. So, the original variable has to be used instead of the
already masked variable.
[Richard Levitte <levitte@stacken.kth.se>]
*) Fix 'port' variable from `int' to `unsigned int' in crypto/bio/b_sock.c
[Richard Levitte <levitte@stacken.kth.se>]
*) Change type of another md_len variable in pk7_doit.c:PKCS7_dataFinal()
from `int' to `unsigned int' because it's a length and initialized by
EVP_DigestFinal() which expects an `unsigned int *'.
[Richard Levitte <levitte@stacken.kth.se>]
*) Don't hard-code path to Perl interpreter on shebang line of Configure
script. Instead use the usual Shell->Perl transition trick.
[Ralf S. Engelschall]
*) Make `openssl x509 -noout -modulus' functional also for DSA certificates
(in addition to RSA certificates) to match the behaviour of `openssl dsa
-noout -modulus' as it's already the case for `openssl rsa -noout
-modulus'. For RSA the -modulus is the real "modulus" while for DSA
currently the public key is printed (a decision which was already done by
`openssl dsa -modulus' in the past) which serves a similar purpose.
Additionally the NO_RSA no longer completely removes the whole -modulus
option; it now only avoids using the RSA stuff. Same applies to NO_DSA
now, too.
[Ralf S. Engelschall]
*) Add Arne Ansper's reliable BIO - this is an encrypted, block-digested
BIO. See the source (crypto/evp/bio_ok.c) for more info.
[Arne Ansper <arne@ats.cyber.ee>]
*) Dump the old yucky req code that tried (and failed) to allow raw OIDs
to be added. Now both 'req' and 'ca' can use new objects defined in the
config file.
[Steve Henson]
*) Add cool BIO that does syslog (or event log on NT).
[Arne Ansper <arne@ats.cyber.ee>, integrated by Ben Laurie]
*) Add support for new TLS ciphersuites, TLS_RSA_EXPORT56_WITH_RC4_56_MD5,
TLS_RSA_EXPORT56_WITH_RC2_CBC_56_MD5 and
TLS_RSA_EXPORT56_WITH_DES_CBC_SHA, as specified in "56-bit Export Cipher
Suites For TLS", draft-ietf-tls-56-bit-ciphersuites-00.txt.
[Ben Laurie]
*) Add preliminary config info for new extension code.
[Steve Henson]
*) Make RSA_NO_PADDING really use no padding.
[Ulf Moeller <ulf@fitug.de>]
*) Generate errors when private/public key check is done.
[Ben Laurie]
*) Overhaul for 'crl' utility. New function X509_CRL_print. Partial support
for some CRL extensions and new objects added.
[Steve Henson]
*) Really fix the ASN1 IMPLICIT bug this time... Partial support for private
key usage extension and fuller support for authority key id.
[Steve Henson]
*) Add OAEP encryption for the OpenSSL crypto library. OAEP is the improved
padding method for RSA, which is recommended for new applications in PKCS
#1 v2.0 (RFC 2437, October 1998).
OAEP (Optimal Asymmetric Encryption Padding) has better theoretical
foundations than the ad-hoc padding used in PKCS #1 v1.5. It is secure
against Bleichbacher's attack on RSA.
[Ulf Moeller <ulf@fitug.de>, reformatted, corrected and integrated by
Ben Laurie]
*) Updates to the new SSL compression code
[Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)]
*) Fix so that the version number in the master secret, when passed
via RSA, checks that if TLS was proposed, but we roll back to SSLv3
(because the server will not accept higher), that the version number
is 0x03,0x01, not 0x03,0x00
[Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)]
*) Run extensive memory leak checks on SSL apps. Fixed *lots* of memory
leaks in ssl/ relating to new X509_get_pubkey() behaviour. Also fixes
in apps/ and an unrelated leak in crypto/dsa/dsa_vrf.c
[Steve Henson]
*) Support for RAW extensions where an arbitrary extension can be
created by including its DER encoding. See apps/openssl.cnf for
an example.
[Steve Henson]
*) Make sure latest Perl versions don't interpret some generated C array
code as Perl array code in the crypto/err/err_genc.pl script.
[Lars Weber <3weber@informatik.uni-hamburg.de>]
*) Modify ms/do_ms.bat to not generate assembly language makefiles since
not many people have the assembler. Various Win32 compilation fixes and
update to the INSTALL.W32 file with (hopefully) more accurate Win32
build instructions.
[Steve Henson]
*) Modify configure script 'Configure' to automatically create crypto/date.h
file under Win32 and also build pem.h from pem.org. New script
util/mkfiles.pl to create the MINFO file on environments that can't do a
'make files': perl util/mkfiles.pl >MINFO should work.
[Steve Henson]
*) Major rework of DES function declarations, in the pursuit of correctness
and purity. As a result, many evil casts evaporated, and some weirdness,
too. You may find this causes warnings in your code. Zapping your evil
casts will probably fix them. Mostly.
[Ben Laurie]
*) Fix for a typo in asn1.h. Bug fix to object creation script
obj_dat.pl. It considered a zero in an object definition to mean
"end of object": none of the objects in objects.h have any zeros
so it wasn't spotted.
[Steve Henson, reported by Erwann ABALEA <eabalea@certplus.com>]
*) Add support for Triple DES Cipher Block Chaining with Output Feedback
Masking (CBCM). In the absence of test vectors, the best I have been able
to do is check that the decrypt undoes the encrypt, so far. Send me test
vectors if you have them.
[Ben Laurie]
*) Correct calculation of key length for export ciphers (too much space was
allocated for null ciphers). This has not been tested!
[Ben Laurie]
*) Modifications to the mkdef.pl for Win32 DEF file creation. The usage
message is now correct (it understands "crypto" and "ssl" on its
command line). There is also now an "update" option. This will update
the util/ssleay.num and util/libeay.num files with any new functions.
If you do a:
perl util/mkdef.pl crypto ssl update
it will update them.
[Steve Henson]
*) Overhauled the Perl interface (perl/*):
- ported BN stuff to OpenSSL's different BN library
- made the perl/ source tree CVS-aware
- renamed the package from SSLeay to OpenSSL (the files still contain
their history because I've copied them in the repository)
- removed obsolete files (the test scripts will be replaced
by better Test::Harness variants in the future)
[Ralf S. Engelschall]
*) First cut for a very conservative source tree cleanup:
1. merge various obsolete readme texts into doc/ssleay.txt
where we collect the old documents and readme texts.
2. remove the first part of files where I'm already sure that we no
longer need them because of three reasons: either they are just temporary
files which were left by Eric or they are preserved original files where
I've verified that the diff is also available in the CVS via "cvs diff
-rSSLeay_0_8_1b" or they were renamed (as it was definitely the case for
the crypto/md/ stuff).
[Ralf S. Engelschall]
*) More extension code. Incomplete support for subject and issuer alt
name, issuer and authority key id. Change the i2v function parameters
and add an extra 'crl' parameter in the X509V3_CTX structure: guess
what that's for :-) Fix to ASN1 macro which messed up
IMPLICIT tag and add f_enum.c which adds a2i, i2a for ENUMERATED.
[Steve Henson]
*) Preliminary support for ENUMERATED type. This is largely copied from the
INTEGER code.
[Steve Henson]
*) Add new function, EVP_MD_CTX_copy() to replace frequent use of memcpy.
[Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)]
*) Make sure `make rehash' target really finds the `openssl' program.
[Ralf S. Engelschall, Matthias Loepfe <Matthias.Loepfe@adnovum.ch>]
*) Squeeze another 7% of speed out of MD5 assembler, at least on a P2. I'd
like to hear about it if this slows down other processors.
[Ben Laurie]
*) Add CygWin32 platform information to Configure script.
[Alan Batie <batie@aahz.jf.intel.com>]
*) Fixed ms/32all.bat script: `no_asm' -> `no-asm'
[Rainer W. Gerling <gerling@mpg-gv.mpg.de>]
*) New program nseq to manipulate netscape certificate sequences
[Steve Henson]
*) Modify crl2pkcs7 so it supports multiple -certfile arguments. Fix a
few typos.
[Steve Henson]
*) Fixes to BN code. Previously the default was to define BN_RECURSION
but the BN code had some problems that would cause failures when
doing certificate verification and some other functions.
[Eric A. Young, (from changes to C2Net SSLeay, integrated by Mark Cox)]
*) Add ASN1 and PEM code to support netscape certificate sequences.
[Steve Henson]
*) Add ASN1 and PEM code to support netscape certificate sequences.
[Steve Henson]
*) Add several PKIX and private extended key usage OIDs.
[Steve Henson]
*) Modify the 'ca' program to handle the new extension code. Modify
openssl.cnf for new extension format, add comments.
[Steve Henson]
*) More X509 V3 changes. Fix typo in v3_bitstr.c. Add support to 'req'
and add a sample to openssl.cnf so req -x509 now adds appropriate
CA extensions.
[Steve Henson]
*) Continued X509 V3 changes. Add to other makefiles, integrate with the
error code, add initial support to X509_print() and x509 application.
[Steve Henson]
*) Takes a deep breath and start adding X509 V3 extension support code. Add
files in crypto/x509v3. Move original stuff to crypto/x509v3/old. All this
stuff is currently isolated and isn't even compiled yet.
[Steve Henson]
*) Continuing patches for GeneralizedTime. Fix up certificate and CRL
ASN1 to use ASN1_TIME and modify print routines to use ASN1_TIME_print.
Removed the versions check from X509 routines when loading extensions:
this allows certain broken certificates that don't set the version
properly to be processed.
[Steve Henson]
*) Deal with irritating shit to do with dependencies, in YAAHW (Yet Another
Ad Hoc Way) - Makefile.ssls now all contain local dependencies, which
can still be regenerated with "make depend".
[Ben Laurie]
*) Spelling mistake in C version of CAST-128.
[Ben Laurie, reported by Jeremy Hylton <jeremy@cnri.reston.va.us>]
*) Changes to the error generation code. The perl script err-code.pl
now reads in the old error codes and retains the old numbers, only
adding new ones if necessary. It also only changes the .err files if new
codes are added. The makefiles have been modified to only insert errors
when needed (to avoid needlessly modifying header files). This is done
by only inserting errors if the .err file is newer than the auto generated
C file. To rebuild all the error codes from scratch (the old behaviour)
either modify crypto/Makefile.ssl to pass the -regen flag to err_code.pl
or delete all the .err files.
[Steve Henson]
*) CAST-128 was incorrectly implemented for short keys. The C version has
been fixed, but is untested. The assembler versions are also fixed, but
new assembler HAS NOT BEEN GENERATED FOR WIN32 - the Makefile needs fixing
to regenerate it if needed.
[Ben Laurie, reported (with fix for C version) by Jun-ichiro itojun
Hagino <itojun@kame.net>]
*) File was opened incorrectly in randfile.c.
[Ulf Möller <ulf@fitug.de>]
*) Beginning of support for GeneralizedTime. d2i, i2d, check and print
functions. Also ASN1_TIME suite which is a CHOICE of UTCTime or
GeneralizedTime. ASN1_TIME is the proper type used in certificates et
al: it's just almost always a UTCTime. Note this patch adds new error
codes so do a "make errors" if there are problems.
[Steve Henson]
*) Correct Linux 1 recognition in config.
[Ulf Möller <ulf@fitug.de>]
*) Remove pointless MD5 hash when using DSA keys in ca.
[Anonymous <nobody@replay.com>]
*) Generate an error if given an empty string as a cert directory. Also
generate an error if handed NULL (previously returned 0 to indicate an
error, but didn't set one).
[Ben Laurie, reported by Anonymous <nobody@replay.com>]
*) Add prototypes to SSL methods. Make SSL_write's buffer const, at last.
[Ben Laurie]
*) Fix the dummy function BN_ref_mod_exp() in rsaref.c to have the correct
parameters. This was causing a warning which killed off the Win32 compile.
[Steve Henson]
*) Remove C++ style comments from crypto/bn/bn_local.h.
[Neil Costigan <neil.costigan@celocom.com>]
*) The function OBJ_txt2nid was broken. It was supposed to return a nid
based on a text string, looking up short and long names and finally
"dot" format. The "dot" format stuff didn't work. Added new function
OBJ_txt2obj to do the same but return an ASN1_OBJECT and rewrote
OBJ_txt2nid to use it. OBJ_txt2obj can also return objects even if the
OID is not part of the table.
[Steve Henson]
*) Add prototypes to X509 lookup/verify methods, fixing a bug in
X509_LOOKUP_by_alias().
[Ben Laurie]
*) Sort openssl functions by name.
[Ben Laurie]
*) Get the gendsa program working (hopefully) and add it to app list. Remove
encryption from sample DSA keys (in case anyone is interested the password
was "1234").
[Steve Henson]
*) Make _all_ *_free functions accept a NULL pointer.
[Frans Heymans <fheymans@isaserver.be>]
*) If a DH key is generated in s3_srvr.c, don't blow it by trying to use
NULL pointers.
[Anonymous <nobody@replay.com>]
*) s_server should send the CAfile as acceptable CAs, not its own cert.
[Bodo Moeller <3moeller@informatik.uni-hamburg.de>]
*) Don't blow it for numeric -newkey arguments to apps/req.
[Bodo Moeller <3moeller@informatik.uni-hamburg.de>]
*) Temp key "for export" tests were wrong in s3_srvr.c.
[Anonymous <nobody@replay.com>]
*) Add prototype for temp key callback functions
SSL_CTX_set_tmp_{rsa,dh}_callback().
[Ben Laurie]
*) Make DH_free() tolerate being passed a NULL pointer (like RSA_free() and
DSA_free()). Make X509_PUBKEY_set() check for errors in d2i_PublicKey().
[Steve Henson]
*) X509_name_add_entry() freed the wrong thing after an error.
[Arne Ansper <arne@ats.cyber.ee>]
*) rsa_eay.c would attempt to free a NULL context.
[Arne Ansper <arne@ats.cyber.ee>]
*) BIO_s_socket() had a broken should_retry() on Windoze.
[Arne Ansper <arne@ats.cyber.ee>]
*) BIO_f_buffer() didn't pass on BIO_CTRL_FLUSH.
[Arne Ansper <arne@ats.cyber.ee>]
*) Make sure the already existing X509_STORE->depth variable is initialized
in X509_STORE_new(), but document the fact that this variable is still
unused in the certificate verification process.
[Ralf S. Engelschall]
*) Fix the various library and apps files to free up pkeys obtained from
X509_PUBKEY_get() et al. Also allow x509.c to handle netscape extensions.
[Steve Henson]
*) Fix reference counting in X509_PUBKEY_get(). This makes
demos/maurice/example2.c work, amongst others, probably.
[Steve Henson and Ben Laurie]
*) First cut of a cleanup for apps/. First the `ssleay' program is now named
`openssl' and second, the shortcut symlinks for the `openssl <command>'
are no longer created. This way we have a single and consistent command
line interface `openssl <command>', similar to `cvs <command>'.
[Ralf S. Engelschall, Paul Sutton and Ben Laurie]
*) ca.c: move test for DSA keys inside #ifndef NO_DSA. Make pubkey
BIT STRING wrapper always have zero unused bits.
[Steve Henson]
*) Add CA.pl, perl version of CA.sh, add extended key usage OID.
[Steve Henson]
*) Make the top-level INSTALL documentation easier to understand.
[Paul Sutton]
*) Makefiles updated to exit if an error occurs in a sub-directory
make (including if user presses ^C) [Paul Sutton]
*) Make Montgomery context stuff explicit in RSA data structure.
[Ben Laurie]
*) Fix build order of pem and err to allow for generated pem.h.
[Ben Laurie]
*) Fix renumbering bug in X509_NAME_delete_entry().
[Ben Laurie]
*) Enhanced the err-ins.pl script so it makes the error library number
global and can add a library name. This is needed for external ASN1 and
other error libraries.
[Steve Henson]
*) Fixed sk_insert which never worked properly.
[Steve Henson]
*) Fix ASN1 macros so they can handle indefinite length constructed
EXPLICIT tags. Some non standard certificates use these: they can now
be read in.
[Steve Henson]
*) Merged the various old/obsolete SSLeay documentation files (doc/xxx.doc)
into a single doc/ssleay.txt bundle. This way the information is still
preserved but no longer messes up this directory. Now it's new room for
the new set of documentation files.
[Ralf S. Engelschall]
*) SETs were incorrectly DER encoded. This was a major pain, because they
shared code with SEQUENCEs, which aren't coded the same. This means that
almost everything to do with SETs or SEQUENCEs has either changed name or
number of arguments.
[Ben Laurie, based on a partial fix by GP Jayan <gp@nsj.co.jp>]
*) Fix test data to work with the above.
[Ben Laurie]
*) Fix the RSA header declarations that hid a bug I fixed in 0.9.0b but
was already fixed by Eric for 0.9.1 it seems.
[Ben Laurie - pointed out by Ulf Möller <ulf@fitug.de>]
*) Autodetect FreeBSD3.
[Ben Laurie]
*) Fix various bugs in Configure. This affects the following platforms:
nextstep
ncr-scde
unixware-2.0
unixware-2.0-pentium
sco5-cc.
[Ben Laurie]
*) Eliminate generated files from CVS. Reorder tests to regenerate files
before they are needed.
[Ben Laurie]
*) Generate Makefile.ssl from Makefile.org (to keep CVS happy).
[Ben Laurie]
Changes between 0.9.1b and 0.9.1c [23-Dec-1998]
*) Added OPENSSL_VERSION_NUMBER to crypto/crypto.h and
changed SSLeay to OpenSSL in version strings.
[Ralf S. Engelschall]
*) Some fixups to the top-level documents.
[Paul Sutton]
*) Fixed the nasty bug where rsaref.h was not found under compile-time
because the symlink to include/ was missing.
[Ralf S. Engelschall]
*) Incorporated the popular no-RSA/DSA-only patches
which allow to compile a RSA-free SSLeay.
[Andrew Cooke / Interrader Ldt., Ralf S. Engelschall]
*) Fixed nasty rehash problem under `make -f Makefile.ssl links'
when "ssleay" is still not found.
[Ralf S. Engelschall]
*) Added more platforms to Configure: Cray T3E, HPUX 11,
[Ralf S. Engelschall, Beckmann <beckman@acl.lanl.gov>]
*) Updated the README file.
[Ralf S. Engelschall]
*) Added various .cvsignore files in the CVS repository subdirs
to make a "cvs update" really silent.
[Ralf S. Engelschall]
*) Recompiled the error-definition header files and added
missing symbols to the Win32 linker tables.
[Ralf S. Engelschall]
*) Cleaned up the top-level documents;
o new files: CHANGES and LICENSE
o merged VERSION, HISTORY* and README* files a CHANGES.SSLeay
o merged COPYRIGHT into LICENSE
o removed obsolete TODO file
o renamed MICROSOFT to INSTALL.W32
[Ralf S. Engelschall]
*) Removed dummy files from the 0.9.1b source tree:
crypto/asn1/x crypto/bio/cd crypto/bio/fg crypto/bio/grep crypto/bio/vi
crypto/bn/asm/......add.c crypto/bn/asm/a.out crypto/dsa/f crypto/md5/f
crypto/pem/gmon.out crypto/perlasm/f crypto/pkcs7/build crypto/rsa/f
crypto/sha/asm/f crypto/threads/f ms/zzz ssl/f ssl/f.mak test/f
util/f.mak util/pl/f util/pl/f.mak crypto/bf/bf_locl.old apps/f
[Ralf S. Engelschall]
*) Added various platform portability fixes.
[Mark J. Cox]
*) The Genesis of the OpenSSL rpject:
We start with the latest (unreleased) SSLeay version 0.9.1b which Eric A.
Young and Tim J. Hudson created while they were working for C2Net until
summer 1998.
[The OpenSSL Project]
Changes between 0.9.0b and 0.9.1b [not released]
*) Updated a few CA certificates under certs/
[Eric A. Young]
*) Changed some BIGNUM api stuff.
[Eric A. Young]
*) Various platform ports: OpenBSD, Ultrix, IRIX 64bit, NetBSD,
DGUX x86, Linux Alpha, etc.
[Eric A. Young]
*) New COMP library [crypto/comp/] for SSL Record Layer Compression:
RLE (dummy implemented) and ZLIB (really implemented when ZLIB is
available).
[Eric A. Young]
*) Add -strparse option to asn1pars program which parses nested
binary structures
[Dr Stephen Henson <shenson@bigfoot.com>]
*) Added "oid_file" to ssleay.cnf for "ca" and "req" programs.
[Eric A. Young]
*) DSA fix for "ca" program.
[Eric A. Young]
*) Added "-genkey" option to "dsaparam" program.
[Eric A. Young]
*) Added RIPE MD160 (rmd160) message digest.
[Eric A. Young]
*) Added -a (all) option to "ssleay version" command.
[Eric A. Young]
*) Added PLATFORM define which is the id given to Configure.
[Eric A. Young]
*) Added MemCheck_XXXX functions to crypto/mem.c for memory checking.
[Eric A. Young]
*) Extended the ASN.1 parser routines.
[Eric A. Young]
*) Extended BIO routines to support REUSEADDR, seek, tell, etc.
[Eric A. Young]
*) Added a BN_CTX to the BN library.
[Eric A. Young]
*) Fixed the weak key values in DES library
[Eric A. Young]
*) Changed API in EVP library for cipher aliases.
[Eric A. Young]
*) Added support for RC2/64bit cipher.
[Eric A. Young]
*) Converted the lhash library to the crypto/mem.c functions.
[Eric A. Young]
*) Added more recognized ASN.1 object ids.
[Eric A. Young]
*) Added more RSA padding checks for SSL/TLS.
[Eric A. Young]
*) Added BIO proxy/filter functionality.
[Eric A. Young]
*) Added extra_certs to SSL_CTX which can be used
send extra CA certificates to the client in the CA cert chain sending
process. It can be configured with SSL_CTX_add_extra_chain_cert().
[Eric A. Young]
*) Now Fortezza is denied in the authentication phase because
this is key exchange mechanism is not supported by SSLeay at all.
[Eric A. Young]
*) Additional PKCS1 checks.
[Eric A. Young]
*) Support the string "TLSv1" for all TLS v1 ciphers.
[Eric A. Young]
*) Added function SSL_get_ex_data_X509_STORE_CTX_idx() which gives the
ex_data index of the SSL context in the X509_STORE_CTX ex_data.
[Eric A. Young]
*) Fixed a few memory leaks.
[Eric A. Young]
*) Fixed various code and comment typos.
[Eric A. Young]
*) A minor bug in ssl/s3_clnt.c where there would always be 4 0
bytes sent in the client random.
[Edward Bishop <ebishop@spyglass.com>]
diff --git a/Configure b/Configure
index 608012225cc9..254b04c95d95 100755
--- a/Configure
+++ b/Configure
@@ -1,3519 +1,3522 @@
#! /usr/bin/env perl
# -*- mode: perl; -*-
# Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
## Configure -- OpenSSL source tree configuration script
use 5.10.0;
use strict;
use Config;
use FindBin;
use lib "$FindBin::Bin/util/perl";
use File::Basename;
use File::Spec::Functions qw/:DEFAULT abs2rel rel2abs/;
use File::Path qw/mkpath/;
use OpenSSL::Glob;
# see INSTALL for instructions.
my $orig_death_handler = $SIG{__DIE__};
$SIG{__DIE__} = \&death_handler;
-my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-dso] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n";
+my $usage="Usage: Configure [no-<cipher> ...] [enable-<cipher> ...] [-Dxxx] [-lxxx] [-Lxxx] [-fxxx] [-Kxxx] [no-hw-xxx|no-hw] [[no-]threads] [[no-]shared] [[no-]zlib|zlib-dynamic] [no-asm] [no-egd] [sctp] [386] [--prefix=DIR] [--openssldir=OPENSSLDIR] [--with-xxx[=vvv]] [--config=FILE] os/compiler[:flags]\n";
# Options:
#
# --config add the given configuration file, which will be read after
# any "Configurations*" files that are found in the same
# directory as this script.
# --prefix prefix for the OpenSSL installation, which includes the
# directories bin, lib, include, share/man, share/doc/openssl
# This becomes the value of INSTALLTOP in Makefile
# (Default: /usr/local)
# --openssldir OpenSSL data area, such as openssl.cnf, certificates and keys.
# If it's a relative directory, it will be added on the directory
# given with --prefix.
# This becomes the value of OPENSSLDIR in Makefile and in C.
# (Default: PREFIX/ssl)
#
# --cross-compile-prefix Add specified prefix to binutils components.
#
# --api One of 0.9.8, 1.0.0 or 1.1.0. Do not compile support for
# interfaces deprecated as of the specified OpenSSL version.
#
# no-hw-xxx do not compile support for specific crypto hardware.
# Generic OpenSSL-style methods relating to this support
# are always compiled but return NULL if the hardware
# support isn't compiled.
# no-hw do not compile support for any crypto hardware.
# [no-]threads [don't] try to create a library that is suitable for
# multithreaded applications (default is "threads" if we
# know how to do it)
-# [no-]shared [don't] try to create shared libraries when supported.
+# [no-]shared [don't] try to create shared libraries when supported.
# [no-]pic [don't] try to build position independent code when supported.
# If disabled, it also disables shared and dynamic-engine.
# no-asm do not use assembler
-# no-dso do not compile in any native shared-library methods. This
-# will ensure that all methods just return NULL.
# no-egd do not compile support for the entropy-gathering daemon APIs
# [no-]zlib [don't] compile support for zlib compression.
-# zlib-dynamic Like "zlib", but the zlib library is expected to be a shared
-# library and will be loaded in run-time by the OpenSSL library.
+# zlib-dynamic Like "zlib", but the zlib library is expected to be a shared
+# library and will be loaded in run-time by the OpenSSL library.
# sctp include SCTP support
# enable-weak-ssl-ciphers
# Enable weak ciphers that are disabled by default.
# 386 generate 80386 code in assembly modules
# no-sse2 disables IA-32 SSE2 code in assembly modules, the above
# mentioned '386' option implies this one
# no-<cipher> build without specified algorithm (rsa, idea, rc5, ...)
# -<xxx> +<xxx> compiler options are passed through
# -static while -static is also a pass-through compiler option (and
# as such is limited to environments where it's actually
# meaningful), it triggers a number configuration options,
-# namely no-dso, no-pic, no-shared and no-threads. It is
+# namely no-pic, no-shared and no-threads. It is
# argued that the only reason to produce statically linked
# binaries (and in context it means executables linked with
# -static flag, and not just executables linked with static
# libcrypto.a) is to eliminate dependency on specific run-time,
# a.k.a. libc version. The mentioned config options are meant
# to achieve just that. Unfortunately on Linux it's impossible
# to eliminate the dependency completely for openssl executable
# because of getaddrinfo and gethostbyname calls, which can
# invoke dynamically loadable library facility anyway to meet
# the lookup requests. For this reason on Linux statically
# linked openssl executable has rather debugging value than
# production quality.
#
# DEBUG_SAFESTACK use type-safe stacks to enforce type-safety on stack items
-# provided to stack calls. Generates unique stack functions for
-# each possible stack type.
-# BN_LLONG use the type 'long long' in crypto/bn/bn.h
-# RC4_CHAR use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
+# provided to stack calls. Generates unique stack functions for
+# each possible stack type.
+# BN_LLONG use the type 'long long' in crypto/bn/bn.h
+# RC4_CHAR use 'char' instead of 'int' for RC4_INT in crypto/rc4/rc4.h
# Following are set automatically by this script
#
-# MD5_ASM use some extra md5 assembler,
-# SHA1_ASM use some extra sha1 assembler, must define L_ENDIAN for x86
-# RMD160_ASM use some extra ripemd160 assembler,
-# SHA256_ASM sha256_block is implemented in assembler
-# SHA512_ASM sha512_block is implemented in assembler
-# AES_ASM AES_[en|de]crypt is implemented in assembler
+# MD5_ASM use some extra md5 assembler,
+# SHA1_ASM use some extra sha1 assembler, must define L_ENDIAN for x86
+# RMD160_ASM use some extra ripemd160 assembler,
+# SHA256_ASM sha256_block is implemented in assembler
+# SHA512_ASM sha512_block is implemented in assembler
+# AES_ASM AES_[en|de]crypt is implemented in assembler
-# Minimum warning options... any contributions to OpenSSL should at least get
-# past these.
+# Minimum warning options... any contributions to OpenSSL should at least
+# get past these. Note that we only use these with C compilers, not with
+# C++ compilers.
# DEBUG_UNUSED enables __owur (warn unused result) checks.
# -DPEDANTIC complements -pedantic and is meant to mask code that
# is not strictly standard-compliant and/or implementation-specific,
# e.g. inline assembly, disregards to alignment requirements, such
# that -pedantic would complain about. Incidentally -DPEDANTIC has
# to be used even in sanitized builds, because sanitizer too is
# supposed to and does take notice of non-standard behaviour. Then
# -pedantic with pre-C9x compiler would also complain about 'long
# long' not being supported. As 64-bit algorithms are common now,
# it grew impossible to resolve this without sizeable additional
# code, so we just tell compiler to be pedantic about everything
# but 'long long' type.
-my $gcc_devteam_warn = "-DDEBUG_UNUSED"
- . " -DPEDANTIC -pedantic -Wno-long-long"
- . " -Wall"
- . " -Wextra"
- . " -Wno-unused-parameter"
- . " -Wno-missing-field-initializers"
- . " -Wswitch"
- . " -Wsign-compare"
- . " -Wmissing-prototypes"
- . " -Wstrict-prototypes"
- . " -Wshadow"
- . " -Wformat"
- . " -Wtype-limits"
- . " -Wundef"
- . " -Werror"
- ;
+my @gcc_devteam_warn = qw(
+ -DDEBUG_UNUSED
+ -DPEDANTIC -pedantic -Wno-long-long
+ -Wall
+ -Wextra
+ -Wno-unused-parameter
+ -Wno-missing-field-initializers
+ -Wswitch
+ -Wsign-compare
+ -Wshadow
+ -Wformat
+ -Wtype-limits
+ -Wundef
+ -Werror
+ -Wmissing-prototypes
+ -Wstrict-prototypes
+);
# These are used in addition to $gcc_devteam_warn when the compiler is clang.
# TODO(openssl-team): fix problems and investigate if (at least) the
# following warnings can also be enabled:
# -Wcast-align
# -Wunreachable-code -- no, too ugly/compiler-specific
# -Wlanguage-extension-token -- no, we use asm()
# -Wunused-macros -- no, too tricky for BN and _XOPEN_SOURCE etc
# -Wextended-offsetof -- no, needed in CMS ASN1 code
-# -Wunused-function -- no, it forces header use of safestack et al
-# DEFINE macros
-my $clang_devteam_warn = ""
- . " -Wswitch-default"
- . " -Wno-parentheses-equality"
- . " -Wno-language-extension-token"
- . " -Wno-extended-offsetof"
- . " -Wconditional-uninitialized"
- . " -Wincompatible-pointer-types-discards-qualifiers"
- . " -Wmissing-variable-declarations"
- . " -Wno-unknown-warning-option"
- . " -Wno-unused-function"
- ;
+my @clang_devteam_warn = qw(
+ -Wswitch-default
+ -Wno-parentheses-equality
+ -Wno-language-extension-token
+ -Wno-extended-offsetof
+ -Wconditional-uninitialized
+ -Wincompatible-pointer-types-discards-qualifiers
+ -Wno-unknown-warning-option
+ -Wmissing-variable-declarations
+);
# This adds backtrace information to the memory leak info. Is only used
# when crypto-mdebug-backtrace is enabled.
my $memleak_devteam_backtrace = "-rdynamic";
my $strict_warnings = 0;
# As for $BSDthreads. Idea is to maintain "collective" set of flags,
# which would cover all BSD flavors. -pthread applies to them all,
# but is treated differently. OpenBSD expands is as -D_POSIX_THREAD
# -lc_r, which is sufficient. FreeBSD 4.x expands it as -lc_r,
# which has to be accompanied by explicit -D_THREAD_SAFE and
# sometimes -D_REENTRANT. FreeBSD 5.x expands it as -lc_r, which
# seems to be sufficient?
our $BSDthreads="-pthread -D_THREAD_SAFE -D_REENTRANT";
#
# API compatibility name to version number mapping.
#
my $maxapi = "1.1.0"; # API for "no-deprecated" builds
my $apitable = {
"1.1.0" => "0x10100000L",
"1.0.0" => "0x10000000L",
"0.9.8" => "0x00908000L",
};
our %table = ();
our %config = ();
our %withargs = ();
our $now_printing; # set to current entry's name in print_table_entry
# (todo: right thing would be to encapsulate name
# into %target [class] and make print_table_entry
# a method)
# Forward declarations ###############################################
# read_config(filename)
#
# Reads a configuration file and populates %table with the contents
# (which the configuration file places in %targets).
sub read_config;
# resolve_config(target)
#
# Resolves all the late evaluations, inheritances and so on for the
# chosen target and any target it inherits from.
sub resolve_config;
# Information collection #############################################
# Unified build supports separate build dir
my $srcdir = catdir(absolutedir(dirname($0))); # catdir ensures local syntax
my $blddir = catdir(absolutedir(".")); # catdir ensures local syntax
my $dofile = abs2rel(catfile($srcdir, "util/dofile.pl"));
my $local_config_envname = 'OPENSSL_LOCAL_CONFIG_DIR';
$config{sourcedir} = abs2rel($srcdir);
$config{builddir} = abs2rel($blddir);
# Collect reconfiguration information if needed
my @argvcopy=@ARGV;
if (grep /^reconf(igure)?$/, @argvcopy) {
die "reconfiguring with other arguments present isn't supported"
if scalar @argvcopy > 1;
if (-f "./configdata.pm") {
- my $file = "./configdata.pm";
- unless (my $return = do $file) {
- die "couldn't parse $file: $@" if $@;
+ my $file = "./configdata.pm";
+ unless (my $return = do $file) {
+ die "couldn't parse $file: $@" if $@;
die "couldn't do $file: $!" unless defined $return;
die "couldn't run $file" unless $return;
- }
+ }
- @argvcopy = defined($configdata::config{perlargv}) ?
- @{$configdata::config{perlargv}} : ();
- die "Incorrect data to reconfigure, please do a normal configuration\n"
- if (grep(/^reconf/,@argvcopy));
- $config{perlenv} = $configdata::config{perlenv} // {};
+ @argvcopy = defined($configdata::config{perlargv}) ?
+ @{$configdata::config{perlargv}} : ();
+ die "Incorrect data to reconfigure, please do a normal configuration\n"
+ if (grep(/^reconf/,@argvcopy));
+ $config{perlenv} = $configdata::config{perlenv} // {};
} else {
- die "Insufficient data to reconfigure, please do a normal configuration\n";
+ die "Insufficient data to reconfigure, please do a normal configuration\n";
}
}
$config{perlargv} = [ @argvcopy ];
# Collect version numbers
$config{version} = "unknown";
$config{version_num} = "unknown";
$config{shlib_version_number} = "unknown";
$config{shlib_version_history} = "unknown";
collect_information(
collect_from_file(catfile($srcdir,'include/openssl/opensslv.h')),
qr/OPENSSL.VERSION.TEXT.*OpenSSL (\S+) / => sub { $config{version} = $1; },
- qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/ => sub { $config{version_num}=$1 },
- qr/SHLIB_VERSION_NUMBER *"([^"]+)"/ => sub { $config{shlib_version_number}=$1 },
+ qr/OPENSSL.VERSION.NUMBER.*(0x\S+)/ => sub { $config{version_num}=$1 },
+ qr/SHLIB_VERSION_NUMBER *"([^"]+)"/ => sub { $config{shlib_version_number}=$1 },
qr/SHLIB_VERSION_HISTORY *"([^"]*)"/ => sub { $config{shlib_version_history}=$1 }
);
if ($config{shlib_version_history} ne "") { $config{shlib_version_history} .= ":"; }
($config{major}, $config{minor})
= ($config{version} =~ /^([0-9]+)\.([0-9\.]+)/);
($config{shlib_major}, $config{shlib_minor})
= ($config{shlib_version_number} =~ /^([0-9]+)\.([0-9\.]+)/);
die "erroneous version information in opensslv.h: ",
"$config{major}, $config{minor}, $config{shlib_major}, $config{shlib_minor}\n"
if ($config{major} eq "" || $config{minor} eq ""
- || $config{shlib_major} eq "" || $config{shlib_minor} eq "");
+ || $config{shlib_major} eq "" || $config{shlib_minor} eq "");
# Collect target configurations
my $pattern = catfile(dirname($0), "Configurations", "*.conf");
foreach (sort glob($pattern)) {
&read_config($_);
}
if (defined env($local_config_envname)) {
if ($^O eq 'VMS') {
# VMS environment variables are logical names,
# which can be used as is
$pattern = $local_config_envname . ':' . '*.conf';
} else {
$pattern = catfile(env($local_config_envname), '*.conf');
}
foreach (sort glob($pattern)) {
&read_config($_);
}
}
# Save away perl command information
$config{perl_cmd} = $^X;
$config{perl_version} = $Config{version};
$config{perl_archname} = $Config{archname};
$config{prefix}="";
$config{openssldir}="";
$config{processor}="";
$config{libdir}="";
my $auto_threads=1; # enable threads automatically? true by default
my $default_ranlib;
# Top level directories to build
$config{dirs} = [ "crypto", "ssl", "engines", "apps", "test", "util", "tools", "fuzz" ];
# crypto/ subdirectories to build
$config{sdirs} = [
"objects",
"md2", "md4", "md5", "sha", "mdc2", "hmac", "ripemd", "whrlpool", "poly1305", "blake2", "siphash", "sm3",
"des", "aes", "rc2", "rc4", "rc5", "idea", "aria", "bf", "cast", "camellia", "seed", "sm4", "chacha", "modes",
"bn", "ec", "rsa", "dsa", "dh", "sm2", "dso", "engine",
"buffer", "bio", "stack", "lhash", "rand", "err",
"evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui",
"cms", "ts", "srp", "cmac", "ct", "async", "kdf", "store"
];
# test/ subdirectories to build
$config{tdirs} = [ "ossl_shim" ];
# Known TLS and DTLS protocols
my @tls = qw(ssl3 tls1 tls1_1 tls1_2 tls1_3);
my @dtls = qw(dtls1 dtls1_2);
# Explicitly known options that are possible to disable. They can
# be regexps, and will be used like this: /^no-${option}$/
# For developers: keep it sorted alphabetically
my @disablables = (
"afalgeng",
"aria",
"asan",
"asm",
"async",
"autoalginit",
"autoerrinit",
"autoload-config",
"bf",
"blake2",
+ "buildtest-c\\+\\+",
"camellia",
"capieng",
"cast",
"chacha",
"cmac",
"cms",
"comp",
"crypto-mdebug",
"crypto-mdebug-backtrace",
"ct",
"deprecated",
"des",
"devcryptoeng",
"dgram",
"dh",
"dsa",
- "dso",
"dtls",
"dynamic-engine",
"ec",
"ec2m",
"ecdh",
"ecdsa",
"ec_nistp_64_gcc_128",
"egd",
"engine",
"err",
"external-tests",
"filenames",
"fuzz-libfuzzer",
"fuzz-afl",
"gost",
"heartbeats",
"hw(-.+)?",
"idea",
"makedepend",
"md2",
"md4",
"mdc2",
"msan",
"multiblock",
"nextprotoneg",
"pinshared",
"ocb",
"ocsp",
"pic",
"poly1305",
"posix-io",
"psk",
"rc2",
"rc4",
"rc5",
"rdrand",
"rfc3779",
"rmd160",
"scrypt",
"sctp",
"seed",
"shared",
"siphash",
"sm2",
"sm3",
"sm4",
"sock",
"srp",
"srtp",
"sse2",
"ssl",
"ssl-trace",
"static-engine",
"stdio",
"tests",
"threads",
"tls",
"ts",
"ubsan",
"ui-console",
"unit-test",
"whirlpool",
"weak-ssl-ciphers",
"zlib",
"zlib-dynamic",
);
foreach my $proto ((@tls, @dtls))
- {
- push(@disablables, $proto);
- push(@disablables, "$proto-method") unless $proto eq "tls1_3";
- }
+ {
+ push(@disablables, $proto);
+ push(@disablables, "$proto-method") unless $proto eq "tls1_3";
+ }
my %deprecated_disablables = (
"ssl2" => undef,
"buf-freelists" => undef,
"ripemd" => "rmd160",
"ui" => "ui-console",
+ "dso" => "", # Empty string means we're silent about it
);
# All of the following are disabled by default:
our %disabled = ( # "what" => "comment"
- "asan" => "default",
- "crypto-mdebug" => "default",
- "crypto-mdebug-backtrace" => "default",
- "devcryptoeng" => "default",
- "ec_nistp_64_gcc_128" => "default",
- "egd" => "default",
- "external-tests" => "default",
- "fuzz-libfuzzer" => "default",
- "fuzz-afl" => "default",
- "heartbeats" => "default",
- "md2" => "default",
+ "asan" => "default",
+ "buildtest-c++" => "default",
+ "crypto-mdebug" => "default",
+ "crypto-mdebug-backtrace" => "default",
+ "devcryptoeng" => "default",
+ "ec_nistp_64_gcc_128" => "default",
+ "egd" => "default",
+ "external-tests" => "default",
+ "fuzz-libfuzzer" => "default",
+ "fuzz-afl" => "default",
+ "heartbeats" => "default",
+ "md2" => "default",
"msan" => "default",
- "rc5" => "default",
- "sctp" => "default",
- "ssl-trace" => "default",
- "ssl3" => "default",
- "ssl3-method" => "default",
- "ubsan" => "default",
- "unit-test" => "default",
- "weak-ssl-ciphers" => "default",
- "zlib" => "default",
- "zlib-dynamic" => "default",
- );
+ "rc5" => "default",
+ "sctp" => "default",
+ "ssl-trace" => "default",
+ "ssl3" => "default",
+ "ssl3-method" => "default",
+ "ubsan" => "default",
+ "unit-test" => "default",
+ "weak-ssl-ciphers" => "default",
+ "zlib" => "default",
+ "zlib-dynamic" => "default",
+ );
# Note: => pair form used for aesthetics, not to truly make a hash table
my @disable_cascades = (
- # "what" => [ "cascade", ... ]
+ # "what" => [ "cascade", ... ]
sub { $config{processor} eq "386" }
- => [ "sse2" ],
- "ssl" => [ "ssl3" ],
- "ssl3-method" => [ "ssl3" ],
- "zlib" => [ "zlib-dynamic" ],
- "des" => [ "mdc2" ],
- "ec" => [ "ecdsa", "ecdh" ],
-
- "dgram" => [ "dtls", "sctp" ],
- "sock" => [ "dgram" ],
- "dtls" => [ @dtls ],
+ => [ "sse2" ],
+ "ssl" => [ "ssl3" ],
+ "ssl3-method" => [ "ssl3" ],
+ "zlib" => [ "zlib-dynamic" ],
+ "des" => [ "mdc2" ],
+ "ec" => [ "ecdsa", "ecdh" ],
+
+ "dgram" => [ "dtls", "sctp" ],
+ "sock" => [ "dgram" ],
+ "dtls" => [ @dtls ],
sub { 0 == scalar grep { !$disabled{$_} } @dtls }
- => [ "dtls" ],
+ => [ "dtls" ],
- "tls" => [ @tls ],
+ "tls" => [ @tls ],
sub { 0 == scalar grep { !$disabled{$_} } @tls }
- => [ "tls" ],
+ => [ "tls" ],
"crypto-mdebug" => [ "crypto-mdebug-backtrace" ],
- # Without DSO, we can't load dynamic engines, so don't build them dynamic
- "dso" => [ "dynamic-engine" ],
-
# Without position independent code, there can be no shared libraries or DSOs
"pic" => [ "shared" ],
"shared" => [ "dynamic-engine" ],
"engine" => [ "afalgeng", "devcryptoeng" ],
# no-autoalginit is only useful when building non-shared
"autoalginit" => [ "shared", "apps" ],
"stdio" => [ "apps", "capieng", "egd" ],
"apps" => [ "tests" ],
"tests" => [ "external-tests" ],
"comp" => [ "zlib" ],
"ec" => [ "tls1_3", "sm2" ],
"sm3" => [ "sm2" ],
sub { !$disabled{"unit-test"} } => [ "heartbeats" ],
sub { !$disabled{"msan"} } => [ "asm" ],
);
# Avoid protocol support holes. Also disable all versions below N, if version
# N is disabled while N+1 is enabled.
#
my @list = (reverse @tls);
while ((my $first, my $second) = (shift @list, shift @list)) {
last unless @list;
push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
- => [ @list ] );
+ => [ @list ] );
unshift @list, $second;
}
my @list = (reverse @dtls);
while ((my $first, my $second) = (shift @list, shift @list)) {
last unless @list;
push @disable_cascades, ( sub { !$disabled{$first} && $disabled{$second} }
- => [ @list ] );
+ => [ @list ] );
unshift @list, $second;
}
# Explicit "no-..." options will be collected in %disabled along with the defaults.
# To remove something from %disabled, use "enable-foo".
# For symmetry, "disable-foo" is a synonym for "no-foo".
&usage if ($#ARGV < 0);
# For the "make variables" CINCLUDES and CDEFINES, we support lists with
# platform specific list separators. Users from those platforms should
# recognise those separators from how you set up the PATH to find executables.
# The default is the Unix like separator, :, but as an exception, we also
# support the space as separator.
my $list_separator_re =
{ VMS => qr/(?<!\^),/,
MSWin32 => qr/(?<!\\);/ } -> {$^O} // qr/(?<!\\)[:\s]/;
# All the "make variables" we support
# Some get pre-populated for the sake of backward compatibility
# (we supported those before the change to "make variable" support.
my %user = (
AR => env('AR'),
ARFLAGS => [],
AS => undef,
ASFLAGS => [],
CC => env('CC'),
- CFLAGS => [],
+ CFLAGS => [ env('CFLAGS') || () ],
CXX => env('CXX'),
- CXXFLAGS => [],
+ CXXFLAGS => [ env('CXXFLAGS') || () ],
CPP => undef,
- CPPFLAGS => [], # -D, -I, -Wp,
+ CPPFLAGS => [ env('CPPFLAGS') || () ], # -D, -I, -Wp,
CPPDEFINES => [], # Alternative for -D
CPPINCLUDES => [], # Alternative for -I
CROSS_COMPILE => env('CROSS_COMPILE'),
HASHBANGPERL=> env('HASHBANGPERL') || env('PERL'),
LD => undef,
- LDFLAGS => [], # -L, -Wl,
- LDLIBS => [], # -l
+ LDFLAGS => [ env('LDFLAGS') || () ], # -L, -Wl,
+ LDLIBS => [ env('LDLIBS') || () ], # -l
MT => undef,
MTFLAGS => [],
PERL => env('PERL') || ($^O ne "VMS" ? $^X : "perl"),
RANLIB => env('RANLIB'),
RC => env('RC') || env('WINDRES'),
- RCFLAGS => [],
+ RCFLAGS => [ env('RCFLAGS') || () ],
RM => undef,
);
# Info about what "make variables" may be prefixed with the cross compiler
# prefix. This should NEVER mention any such variable with a list for value.
my @user_crossable = qw ( AR AS CC CXX CPP LD MT RANLIB RC );
# The same but for flags given as Configure options. These are *additional*
# input, as opposed to the VAR=string option that override the corresponding
# config target attributes
my %useradd = (
CPPDEFINES => [],
CPPINCLUDES => [],
CPPFLAGS => [],
CFLAGS => [],
CXXFLAGS => [],
LDFLAGS => [],
LDLIBS => [],
+ RCFLAGS => [],
);
my %user_synonyms = (
HASHBANGPERL=> 'PERL',
RC => 'WINDRES',
);
# Some target attributes have been renamed, this is the translation table
my %target_attr_translate =(
ar => 'AR',
as => 'AS',
cc => 'CC',
cxx => 'CXX',
cpp => 'CPP',
hashbangperl => 'HASHBANGPERL',
ld => 'LD',
mt => 'MT',
ranlib => 'RANLIB',
rc => 'RC',
rm => 'RM',
);
# Initialisers coming from 'config' scripts
$config{defines} = [ split(/$list_separator_re/, env('__CNF_CPPDEFINES')) ];
$config{includes} = [ split(/$list_separator_re/, env('__CNF_CPPINCLUDES')) ];
$config{cppflags} = [ env('__CNF_CPPFLAGS') || () ];
$config{cflags} = [ env('__CNF_CFLAGS') || () ];
$config{cxxflags} = [ env('__CNF_CXXFLAGS') || () ];
$config{lflags} = [ env('__CNF_LDFLAGS') || () ];
$config{ex_libs} = [ env('__CNF_LDLIBS') || () ];
$config{openssl_api_defines}=[];
$config{openssl_algorithm_defines}=[];
$config{openssl_thread_defines}=[];
$config{openssl_sys_defines}=[];
$config{openssl_other_defines}=[];
$config{options}="";
$config{build_type} = "release";
my $target="";
my %cmdvars = (); # Stores FOO='blah' type arguments
my %unsupported_options = ();
my %deprecated_options = ();
# If you change this, update apps/version.c
my @known_seed_sources = qw(getrandom devrandom os egd none rdcpu librandom);
my @seed_sources = ();
while (@argvcopy)
- {
- $_ = shift @argvcopy;
-
- # Support env variable assignments among the options
- if (m|^(\w+)=(.+)?$|)
- {
- $cmdvars{$1} = $2;
- # Every time a variable is given as a configuration argument,
- # it acts as a reset if the variable.
- if (exists $user{$1})
- {
- $user{$1} = ref $user{$1} eq "ARRAY" ? [] : undef;
- }
- #if (exists $useradd{$1})
- # {
- # $useradd{$1} = [];
- # }
- next;
- }
-
- # VMS is a case insensitive environment, and depending on settings
- # out of our control, we may receive options uppercased. Let's
- # downcase at least the part before any equal sign.
- if ($^O eq "VMS")
- {
- s/^([^=]*)/lc($1)/e;
- }
-
- # some people just can't read the instructions, clang people have to...
- s/^-no-(?!integrated-as)/no-/;
-
- # rewrite some options in "enable-..." form
- s /^-?-?shared$/enable-shared/;
- s /^sctp$/enable-sctp/;
- s /^threads$/enable-threads/;
- s /^zlib$/enable-zlib/;
- s /^zlib-dynamic$/enable-zlib-dynamic/;
+ {
+ $_ = shift @argvcopy;
+
+ # Support env variable assignments among the options
+ if (m|^(\w+)=(.+)?$|)
+ {
+ $cmdvars{$1} = $2;
+ # Every time a variable is given as a configuration argument,
+ # it acts as a reset if the variable.
+ if (exists $user{$1})
+ {
+ $user{$1} = ref $user{$1} eq "ARRAY" ? [] : undef;
+ }
+ #if (exists $useradd{$1})
+ # {
+ # $useradd{$1} = [];
+ # }
+ next;
+ }
+
+ # VMS is a case insensitive environment, and depending on settings
+ # out of our control, we may receive options uppercased. Let's
+ # downcase at least the part before any equal sign.
+ if ($^O eq "VMS")
+ {
+ s/^([^=]*)/lc($1)/e;
+ }
+
+ # some people just can't read the instructions, clang people have to...
+ s/^-no-(?!integrated-as)/no-/;
+
+ # rewrite some options in "enable-..." form
+ s /^-?-?shared$/enable-shared/;
+ s /^sctp$/enable-sctp/;
+ s /^threads$/enable-threads/;
+ s /^zlib$/enable-zlib/;
+ s /^zlib-dynamic$/enable-zlib-dynamic/;
if (/^(no|disable|enable)-(.+)$/)
{
my $word = $2;
if (!exists $deprecated_disablables{$word}
&& !grep { $word =~ /^${_}$/ } @disablables)
{
$unsupported_options{$_} = 1;
next;
}
}
if (/^no-(.+)$/ || /^disable-(.+)$/)
{
foreach my $proto ((@tls, @dtls))
{
if ($1 eq "$proto-method")
{
$disabled{"$proto"} = "option($proto-method)";
last;
}
}
if ($1 eq "dtls")
{
foreach my $proto (@dtls)
{
$disabled{$proto} = "option(dtls)";
}
$disabled{"dtls"} = "option(dtls)";
}
elsif ($1 eq "ssl")
{
# Last one of its kind
$disabled{"ssl3"} = "option(ssl)";
}
elsif ($1 eq "tls")
{
# XXX: Tests will fail if all SSL/TLS
# protocols are disabled.
foreach my $proto (@tls)
{
$disabled{$proto} = "option(tls)";
}
}
elsif ($1 eq "static-engine")
{
delete $disabled{"dynamic-engine"};
}
elsif ($1 eq "dynamic-engine")
{
$disabled{"dynamic-engine"} = "option";
}
elsif (exists $deprecated_disablables{$1})
{
- $deprecated_options{$_} = 1;
- if (defined $deprecated_disablables{$1})
+ if ($deprecated_disablables{$1} ne "")
{
- $disabled{$deprecated_disablables{$1}} = "option";
+ $deprecated_options{$_} = 1;
+ if (defined $deprecated_disablables{$1})
+ {
+ $disabled{$deprecated_disablables{$1}} = "option";
+ }
}
}
else
{
$disabled{$1} = "option";
}
- # No longer an automatic choice
- $auto_threads = 0 if ($1 eq "threads");
- }
- elsif (/^enable-(.+)$/)
- {
+ # No longer an automatic choice
+ $auto_threads = 0 if ($1 eq "threads");
+ }
+ elsif (/^enable-(.+)$/)
+ {
if ($1 eq "static-engine")
{
$disabled{"dynamic-engine"} = "option";
}
elsif ($1 eq "dynamic-engine")
{
delete $disabled{"dynamic-engine"};
}
elsif ($1 eq "zlib-dynamic")
{
delete $disabled{"zlib"};
}
- my $algo = $1;
- delete $disabled{$algo};
-
- # No longer an automatic choice
- $auto_threads = 0 if ($1 eq "threads");
- }
- elsif (/^--strict-warnings$/)
- {
- $strict_warnings = 1;
- }
- elsif (/^--debug$/)
- {
- $config{build_type} = "debug";
- }
- elsif (/^--release$/)
- {
- $config{build_type} = "release";
- }
- elsif (/^386$/)
- { $config{processor}=386; }
- elsif (/^fips$/)
- {
- die "FIPS mode not supported\n";
- }
- elsif (/^rsaref$/)
- {
- # No RSAref support any more since it's not needed.
- # The check for the option is there so scripts aren't
- # broken
- }
- elsif (/^nofipscanistercheck$/)
- {
- die "FIPS mode not supported\n";
- }
- elsif (/^[-+]/)
- {
- if (/^--prefix=(.*)$/)
- {
- $config{prefix}=$1;
- die "Directory given with --prefix MUST be absolute\n"
- unless file_name_is_absolute($config{prefix});
- }
- elsif (/^--api=(.*)$/)
- {
- $config{api}=$1;
- }
- elsif (/^--libdir=(.*)$/)
- {
- $config{libdir}=$1;
- }
- elsif (/^--openssldir=(.*)$/)
- {
- $config{openssldir}=$1;
- }
- elsif (/^--with-zlib-lib=(.*)$/)
- {
- $withargs{zlib_lib}=$1;
- }
- elsif (/^--with-zlib-include=(.*)$/)
- {
- $withargs{zlib_include}=$1;
- }
- elsif (/^--with-fuzzer-lib=(.*)$/)
- {
- $withargs{fuzzer_lib}=$1;
- }
- elsif (/^--with-fuzzer-include=(.*)$/)
- {
- $withargs{fuzzer_include}=$1;
- }
- elsif (/^--with-rand-seed=(.*)$/)
- {
- foreach my $x (split(m|,|, $1))
- {
- die "Unknown --with-rand-seed choice $x\n"
- if ! grep { $x eq $_ } @known_seed_sources;
- push @seed_sources, $x;
- }
+ my $algo = $1;
+ delete $disabled{$algo};
+
+ # No longer an automatic choice
+ $auto_threads = 0 if ($1 eq "threads");
+ }
+ elsif (/^--strict-warnings$/)
+ {
+ # Pretend that our strict flags is a C flag, and replace it
+ # with the proper flags later on
+ push @{$useradd{CFLAGS}}, '--ossl-strict-warnings';
+ $strict_warnings=1;
+ }
+ elsif (/^--debug$/)
+ {
+ $config{build_type} = "debug";
+ }
+ elsif (/^--release$/)
+ {
+ $config{build_type} = "release";
+ }
+ elsif (/^386$/)
+ { $config{processor}=386; }
+ elsif (/^fips$/)
+ {
+ die "FIPS mode not supported\n";
+ }
+ elsif (/^rsaref$/)
+ {
+ # No RSAref support any more since it's not needed.
+ # The check for the option is there so scripts aren't
+ # broken
+ }
+ elsif (/^nofipscanistercheck$/)
+ {
+ die "FIPS mode not supported\n";
+ }
+ elsif (/^[-+]/)
+ {
+ if (/^--prefix=(.*)$/)
+ {
+ $config{prefix}=$1;
+ die "Directory given with --prefix MUST be absolute\n"
+ unless file_name_is_absolute($config{prefix});
}
- elsif (/^--cross-compile-prefix=(.*)$/)
- {
- $user{CROSS_COMPILE}=$1;
- }
- elsif (/^--config=(.*)$/)
- {
- read_config $1;
- }
- elsif (/^-l(.*)$/)
- {
- push @{$useradd{LDLIBS}}, $_;
- }
- elsif (/^-framework$/)
- {
- push @{$useradd{LDLIBS}}, $_, shift(@argvcopy);
- }
- elsif (/^-L(.*)$/ or /^-Wl,/)
- {
- push @{$useradd{LDFLAGS}}, $_;
- }
- elsif (/^-rpath$/ or /^-R$/)
- # -rpath is the OSF1 rpath flag
- # -R is the old Solaris rpath flag
- {
- my $rpath = shift(@argvcopy) || "";
- $rpath .= " " if $rpath ne "";
- push @{$useradd{LDFLAGS}}, $_, $rpath;
- }
- elsif (/^-static$/)
- {
- push @{$useradd{LDFLAGS}}, $_;
- $disabled{"dso"} = "forced";
- $disabled{"pic"} = "forced";
- $disabled{"shared"} = "forced";
- $disabled{"threads"} = "forced";
- }
- elsif (/^-D(.*)$/)
- {
- push @{$useradd{CPPDEFINES}}, $1;
- }
- elsif (/^-I(.*)$/)
- {
- push @{$useradd{CPPINCLUDES}}, $1;
- }
- elsif (/^-Wp,$/)
- {
- push @{$useradd{CPPFLAGS}}, $1;
- }
- else # common if (/^[-+]/), just pass down...
- {
- $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
- push @{$useradd{CFLAGS}}, $_;
- push @{$useradd{CXXFLAGS}}, $_;
- }
- }
- else
- {
- die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
- $target=$_;
- }
- unless ($_ eq $target || /^no-/ || /^disable-/)
- {
- # "no-..." follows later after implied deactivations
- # have been derived. (Don't take this too seriously,
- # we really only write OPTIONS to the Makefile out of
- # nostalgia.)
-
- if ($config{options} eq "")
- { $config{options} = $_; }
- else
- { $config{options} .= " ".$_; }
- }
- }
+ elsif (/^--api=(.*)$/)
+ {
+ $config{api}=$1;
+ }
+ elsif (/^--libdir=(.*)$/)
+ {
+ $config{libdir}=$1;
+ }
+ elsif (/^--openssldir=(.*)$/)
+ {
+ $config{openssldir}=$1;
+ }
+ elsif (/^--with-zlib-lib=(.*)$/)
+ {
+ $withargs{zlib_lib}=$1;
+ }
+ elsif (/^--with-zlib-include=(.*)$/)
+ {
+ $withargs{zlib_include}=$1;
+ }
+ elsif (/^--with-fuzzer-lib=(.*)$/)
+ {
+ $withargs{fuzzer_lib}=$1;
+ }
+ elsif (/^--with-fuzzer-include=(.*)$/)
+ {
+ $withargs{fuzzer_include}=$1;
+ }
+ elsif (/^--with-rand-seed=(.*)$/)
+ {
+ foreach my $x (split(m|,|, $1))
+ {
+ die "Unknown --with-rand-seed choice $x\n"
+ if ! grep { $x eq $_ } @known_seed_sources;
+ push @seed_sources, $x;
+ }
+ }
+ elsif (/^--cross-compile-prefix=(.*)$/)
+ {
+ $user{CROSS_COMPILE}=$1;
+ }
+ elsif (/^--config=(.*)$/)
+ {
+ read_config $1;
+ }
+ elsif (/^-l(.*)$/)
+ {
+ push @{$useradd{LDLIBS}}, $_;
+ }
+ elsif (/^-framework$/)
+ {
+ push @{$useradd{LDLIBS}}, $_, shift(@argvcopy);
+ }
+ elsif (/^-L(.*)$/ or /^-Wl,/)
+ {
+ push @{$useradd{LDFLAGS}}, $_;
+ }
+ elsif (/^-rpath$/ or /^-R$/)
+ # -rpath is the OSF1 rpath flag
+ # -R is the old Solaris rpath flag
+ {
+ my $rpath = shift(@argvcopy) || "";
+ $rpath .= " " if $rpath ne "";
+ push @{$useradd{LDFLAGS}}, $_, $rpath;
+ }
+ elsif (/^-static$/)
+ {
+ push @{$useradd{LDFLAGS}}, $_;
+ }
+ elsif (/^-D(.*)$/)
+ {
+ push @{$useradd{CPPDEFINES}}, $1;
+ }
+ elsif (/^-I(.*)$/)
+ {
+ push @{$useradd{CPPINCLUDES}}, $1;
+ }
+ elsif (/^-Wp,$/)
+ {
+ push @{$useradd{CPPFLAGS}}, $1;
+ }
+ else # common if (/^[-+]/), just pass down...
+ {
+ $_ =~ s/%([0-9a-f]{1,2})/chr(hex($1))/gei;
+ push @{$useradd{CFLAGS}}, $_;
+ push @{$useradd{CXXFLAGS}}, $_;
+ }
+ }
+ else
+ {
+ die "target already defined - $target (offending arg: $_)\n" if ($target ne "");
+ $target=$_;
+ }
+ unless ($_ eq $target || /^no-/ || /^disable-/)
+ {
+ # "no-..." follows later after implied deactivations
+ # have been derived. (Don't take this too seriously,
+ # we really only write OPTIONS to the Makefile out of
+ # nostalgia.)
+
+ if ($config{options} eq "")
+ { $config{options} = $_; }
+ else
+ { $config{options} .= " ".$_; }
+ }
+ }
if (defined($config{api}) && !exists $apitable->{$config{api}}) {
- die "***** Unsupported api compatibility level: $config{api}\n",
+ die "***** Unsupported api compatibility level: $config{api}\n",
}
if (keys %deprecated_options)
- {
- warn "***** Deprecated options: ",
- join(", ", keys %deprecated_options), "\n";
- }
+ {
+ warn "***** Deprecated options: ",
+ join(", ", keys %deprecated_options), "\n";
+ }
if (keys %unsupported_options)
- {
- die "***** Unsupported options: ",
- join(", ", keys %unsupported_options), "\n";
- }
+ {
+ die "***** Unsupported options: ",
+ join(", ", keys %unsupported_options), "\n";
+ }
# If any %useradd entry has been set, we must check that the "make
# variables" haven't been set. We start by checking of any %useradd entry
# is set.
if (grep { scalar @$_ > 0 } values %useradd) {
# Hash of env / make variables names. The possible values are:
# 1 - "make vars"
# 2 - %useradd entry set
# 3 - both set
my %detected_vars =
map { my $v = 0;
$v += 1 if $cmdvars{$_};
$v += 2 if @{$useradd{$_}};
$_ => $v }
keys %useradd;
# If any of the corresponding "make variables" is set, we error
if (grep { $_ & 1 } values %detected_vars) {
my $names = join(', ', grep { $detected_vars{$_} > 0 }
sort keys %detected_vars);
die <<"_____";
***** Mixing make variables and additional compiler/linker flags as
***** configure command line option is not permitted.
***** Affected make variables: $names
_____
}
}
# Check through all supported command line variables to see if any of them
# were set, and canonicalise the values we got. If no compiler or linker
# flag or anything else that affects %useradd was set, we also check the
# environment for values.
my $anyuseradd =
grep { defined $_ && (ref $_ ne 'ARRAY' || @$_) } values %useradd;
foreach (keys %user) {
my $value = $cmdvars{$_};
$value //= env($_) unless $anyuseradd;
$value //=
defined $user_synonyms{$_} ? $cmdvars{$user_synonyms{$_}} : undef;
$value //= defined $user_synonyms{$_} ? env($user_synonyms{$_}) : undef
unless $anyuseradd;
if (defined $value) {
if (ref $user{$_} eq 'ARRAY') {
$user{$_} = [ split /$list_separator_re/, $value ];
} elsif (!defined $user{$_}) {
$user{$_} = $value;
}
}
}
if (grep { /-rpath\b/ } ($user{LDFLAGS} ? @{$user{LDFLAGS}} : ())
&& !$disabled{shared}
&& !($disabled{asan} && $disabled{msan} && $disabled{ubsan})) {
die "***** Cannot simultaneously use -rpath, shared libraries, and\n",
- "***** any of asan, msan or ubsan\n";
+ "***** any of asan, msan or ubsan\n";
}
-my @tocheckfor = (keys %disabled);
-while (@tocheckfor) {
- my %new_tocheckfor = ();
- my @cascade_copy = (@disable_cascades);
- while (@cascade_copy) {
- my ($test, $descendents) = (shift @cascade_copy, shift @cascade_copy);
- if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
- foreach(grep { !defined($disabled{$_}) } @$descendents) {
- $new_tocheckfor{$_} = 1; $disabled{$_} = "forced";
- }
- }
+sub disable {
+ my $disable_type = shift;
+
+ for (@_) {
+ $disabled{$_} = $disable_type;
+ }
+
+ my @tocheckfor = (@_ ? @_ : keys %disabled);
+ while (@tocheckfor) {
+ my %new_tocheckfor = ();
+ my @cascade_copy = (@disable_cascades);
+ while (@cascade_copy) {
+ my ($test, $descendents) =
+ (shift @cascade_copy, shift @cascade_copy);
+ if (ref($test) eq "CODE" ? $test->() : defined($disabled{$test})) {
+ foreach (grep { !defined($disabled{$_}) } @$descendents) {
+ $new_tocheckfor{$_} = 1; $disabled{$_} = "cascade";
+ }
+ }
+ }
+ @tocheckfor = (keys %new_tocheckfor);
}
- @tocheckfor = (keys %new_tocheckfor);
}
+disable(); # First cascade run
our $die = sub { die @_; };
if ($target eq "TABLE") {
local $die = sub { warn @_; };
foreach (sort keys %table) {
- print_table_entry($_, "TABLE");
+ print_table_entry($_, "TABLE");
}
exit 0;
}
if ($target eq "LIST") {
foreach (sort keys %table) {
- print $_,"\n" unless $table{$_}->{template};
+ print $_,"\n" unless $table{$_}->{template};
}
exit 0;
}
if ($target eq "HASH") {
local $die = sub { warn @_; };
print "%table = (\n";
foreach (sort keys %table) {
- print_table_entry($_, "HASH");
+ print_table_entry($_, "HASH");
}
exit 0;
}
print "Configuring OpenSSL version $config{version} ($config{version_num}) ";
print "for $target\n";
if (scalar(@seed_sources) == 0) {
print "Using os-specific seed configuration\n";
push @seed_sources, 'os';
}
if (scalar(grep { $_ eq 'none' } @seed_sources) > 0) {
die "Cannot seed with none and anything else" if scalar(@seed_sources) > 1;
warn <<_____ if scalar(@seed_sources) == 1;
============================== WARNING ===============================
You have selected the --with-rand-seed=none option, which effectively
disables automatic reseeding of the OpenSSL random generator.
All operations depending on the random generator such as creating keys
will not work unless the random generator is seeded manually by the
application.
Please read the 'Note on random number generation' section in the
INSTALL instructions and the RAND_DRBG(7) manual page for more details.
============================== WARNING ===============================
_____
}
push @{$config{openssl_other_defines}},
map { (my $x = $_) =~ tr|[\-a-z]|[_A-Z]|; "OPENSSL_RAND_SEED_$x" }
- @seed_sources;
+ @seed_sources;
# Backward compatibility?
if ($target =~ m/^CygWin32(-.*)$/) {
$target = "Cygwin".$1;
}
# Support for legacy targets having a name starting with 'debug-'
my ($d, $t) = $target =~ m/^(debug-)?(.*)$/;
if ($d) {
$config{build_type} = "debug";
# If we do not find debug-foo in the table, the target is set to foo.
if (!$table{$target}) {
- $target = $t;
+ $target = $t;
}
}
&usage if !$table{$target} || $table{$target}->{template};
$config{target} = $target;
my %target = resolve_config($target);
foreach (keys %target_attr_translate) {
$target{$target_attr_translate{$_}} = $target{$_}
if $target{$_};
delete $target{$_};
}
%target = ( %{$table{DEFAULTS}}, %target );
-# Make the flags to build DSOs the same as for shared libraries unless they
-# are already defined
-$target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
-$target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
-$target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
-{
- my $shared_info_pl =
- catfile(dirname($0), "Configurations", "shared-info.pl");
- my %shared_info = read_eval_file($shared_info_pl);
- push @{$target{_conf_fname_int}}, $shared_info_pl;
- my $si = $target{shared_target};
- while (ref $si ne "HASH") {
- last if ! defined $si;
- if (ref $si eq "CODE") {
- $si = $si->();
- } else {
- $si = $shared_info{$si};
- }
- }
-
- # Some of the 'shared_target' values don't have any entried in
- # %shared_info. That's perfectly fine, AS LONG AS the build file
- # template knows how to handle this. That is currently the case for
- # Windows and VMS.
- if (defined $si) {
- # Just as above, copy certain shared_* attributes to the corresponding
- # module_ attribute unless the latter is already defined
- $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
- $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
- $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
- foreach (sort keys %$si) {
- $target{$_} = defined $target{$_}
- ? add($si->{$_})->($target{$_})
- : $si->{$_};
- }
- }
-}
-
my %conf_files = map { $_ => 1 } (@{$target{_conf_fname_int}});
$config{conf_files} = [ sort keys %conf_files ];
+# Using sub disable within these loops may prove fragile, so we run
+# a cascade afterwards
foreach my $feature (@{$target{disable}}) {
if (exists $deprecated_disablables{$feature}) {
warn "***** config $target disables deprecated feature $feature\n";
} elsif (!grep { $feature eq $_ } @disablables) {
die "***** config $target disables unknown feature $feature\n";
}
$disabled{$feature} = 'config';
}
foreach my $feature (@{$target{enable}}) {
if ("default" eq ($disabled{$feature} // "")) {
if (exists $deprecated_disablables{$feature}) {
warn "***** config $target enables deprecated feature $feature\n";
} elsif (!grep { $feature eq $_ } @disablables) {
die "***** config $target enables unknown feature $feature\n";
}
delete $disabled{$feature};
}
}
+disable(); # Run a cascade now
$target{CXXFLAGS}//=$target{CFLAGS} if $target{CXX};
$target{cxxflags}//=$target{cflags} if $target{CXX};
$target{exe_extension}="";
$target{exe_extension}=".exe" if ($config{target} eq "DJGPP"
|| $config{target} =~ /^(?:Cygwin|mingw)/);
$target{exe_extension}=".pm" if ($config{target} =~ /vos/);
($target{shared_extension_simple}=$target{shared_extension})
=~ s|\.\$\(SHLIB_VERSION_NUMBER\)||
unless defined($target{shared_extension_simple});
$target{dso_extension}//=$target{shared_extension_simple};
($target{shared_import_extension}=$target{shared_extension_simple}.".a")
if ($config{target} =~ /^(?:Cygwin|mingw)/);
# Fill %config with values from %user, and in case those are undefined or
# empty, use values from %target (acting as a default).
foreach (keys %user) {
my $ref_type = ref $user{$_};
# Temporary function. Takes an intended ref type (empty string or "ARRAY")
# and a value that's to be coerced into that type.
my $mkvalue = sub {
my $type = shift;
my $value = shift;
my $undef_p = shift;
die "Too many arguments for \$mkvalue" if @_;
while (ref $value eq 'CODE') {
$value = $value->();
}
if ($type eq 'ARRAY') {
return undef unless defined $value;
return undef if ref $value ne 'ARRAY' && !$value;
return undef if ref $value eq 'ARRAY' && !@$value;
return [ $value ] unless ref $value eq 'ARRAY';
}
return undef unless $value;
return $value;
};
$config{$_} =
$mkvalue->($ref_type, $user{$_})
|| $mkvalue->($ref_type, $target{$_});
delete $config{$_} unless defined $config{$_};
}
+# Finish up %config by appending things the user gave us on the command line
+# apart from "make variables"
+foreach (keys %useradd) {
+ # The must all be lists, so we assert that here
+ die "internal error: \$useradd{$_} isn't an ARRAY\n"
+ unless ref $useradd{$_} eq 'ARRAY';
+
+ if (defined $config{$_}) {
+ push @{$config{$_}}, @{$useradd{$_}};
+ } else {
+ $config{$_} = [ @{$useradd{$_}} ];
+ }
+}
+# At this point, we can forget everything about %user and %useradd,
+# because it's now all been merged into the corresponding $config entry
+
# Allow overriding the build file name
$config{build_file} = env('BUILDFILE') || $target{build_file} || "Makefile";
my %disabled_info = (); # For configdata.pm
foreach my $what (sort keys %disabled) {
$config{options} .= " no-$what";
- if (!grep { $what eq $_ } ( 'dso', 'threads', 'shared', 'pic',
+ if (!grep { $what eq $_ } ( 'buildtest-c++', 'threads', 'shared', 'pic',
'dynamic-engine', 'makedepend',
'zlib-dynamic', 'zlib', 'sse2' )) {
(my $WHAT = uc $what) =~ s|-|_|g;
# Fix up C macro end names
$WHAT = "RMD160" if $what eq "ripemd";
# fix-up crypto/directory name(s)
$what = "ripemd" if $what eq "rmd160";
$what = "whrlpool" if $what eq "whirlpool";
my $macro = $disabled_info{$what}->{macro} = "OPENSSL_NO_$WHAT";
if ((grep { $what eq $_ } @{$config{sdirs}})
&& $what ne 'async' && $what ne 'err') {
@{$config{sdirs}} = grep { $what ne $_} @{$config{sdirs}};
$disabled_info{$what}->{skipped} = [ catdir('crypto', $what) ];
if ($what ne 'engine') {
push @{$config{openssl_algorithm_defines}}, $macro;
} else {
@{$config{dirs}} = grep !/^engines$/, @{$config{dirs}};
push @{$disabled_info{engine}->{skipped}}, catdir('engines');
push @{$config{openssl_other_defines}}, $macro;
}
} else {
push @{$config{openssl_other_defines}}, $macro;
}
}
}
# Make sure build_scheme is consistent.
$target{build_scheme} = [ $target{build_scheme} ]
if ref($target{build_scheme}) ne "ARRAY";
my ($builder, $builder_platform, @builder_opts) =
@{$target{build_scheme}};
foreach my $checker (($builder_platform."-".$target{build_file}."-checker.pm",
$builder_platform."-checker.pm")) {
my $checker_path = catfile($srcdir, "Configurations", $checker);
if (-f $checker_path) {
my $fn = $ENV{CONFIGURE_CHECKER_WARN}
? sub { warn $@; } : sub { die $@; };
if (! do $checker_path) {
if ($@) {
$fn->($@);
} elsif ($!) {
$fn->($!);
} else {
$fn->("The detected tools didn't match the platform\n");
}
}
last;
}
}
push @{$config{defines}}, "NDEBUG" if $config{build_type} eq "release";
if ($target =~ /^mingw/ && `$config{CC} --target-help 2>&1` =~ m/-mno-cygwin/m)
- {
- push @{$config{cflags}}, "-mno-cygwin";
- push @{$config{cxxflags}}, "-mno-cygwin" if $config{CXX};
- push @{$config{shared_ldflag}}, "-mno-cygwin";
- }
+ {
+ push @{$config{cflags}}, "-mno-cygwin";
+ push @{$config{cxxflags}}, "-mno-cygwin" if $config{CXX};
+ push @{$config{shared_ldflag}}, "-mno-cygwin";
+ }
if ($target =~ /linux.*-mips/ && !$disabled{asm}
- && !grep { $_ !~ /-m(ips|arch=)/ } (@{$user{CFLAGS}},
- @{$useradd{CFLAGS}})) {
- # minimally required architecture flags for assembly modules
- my $value;
- $value = '-mips2' if ($target =~ /mips32/);
- $value = '-mips3' if ($target =~ /mips64/);
- unshift @{$config{cflags}}, $value;
- unshift @{$config{cxxflags}}, $value if $config{CXX};
+ && !grep { $_ !~ /-m(ips|arch=)/ } (@{$config{CFLAGS}})) {
+ # minimally required architecture flags for assembly modules
+ my $value;
+ $value = '-mips2' if ($target =~ /mips32/);
+ $value = '-mips3' if ($target =~ /mips64/);
+ unshift @{$config{cflags}}, $value;
+ unshift @{$config{cxxflags}}, $value if $config{CXX};
}
# If threads aren't disabled, check how possible they are
unless ($disabled{threads}) {
if ($auto_threads) {
# Enabled by default, disable it forcibly if unavailable
if ($target{thread_scheme} eq "(unknown)") {
- $disabled{threads} = "unavailable";
+ disable("unavailable", 'threads');
}
} else {
# The user chose to enable threads explicitly, let's see
# if there's a chance that's possible
if ($target{thread_scheme} eq "(unknown)") {
# If the user asked for "threads" and we don't have internal
# knowledge how to do it, [s]he is expected to provide any
# system-dependent compiler options that are necessary. We
# can't truly check that the given options are correct, but
# we expect the user to know what [s]He is doing.
- if (!@{$user{CFLAGS}} && !@{$useradd{CFLAGS}}
- && !@{$user{CPPDEFINES}} && !@{$useradd{CPPDEFINES}}) {
+ if (!@{$config{CFLAGS}} && !@{$config{CPPDEFINES}}) {
die "You asked for multi-threading support, but didn't\n"
,"provide any system-specific compiler options\n";
}
}
}
}
# If threads still aren't disabled, add a C macro to ensure the source
# code knows about it. Any other flag is taken care of by the configs.
unless($disabled{threads}) {
push @{$config{openssl_thread_defines}}, "OPENSSL_THREADS";
}
# With "deprecated" disable all deprecated features.
if (defined($disabled{"deprecated"})) {
$config{api} = $maxapi;
}
my $no_shared_warn=0;
if ($target{shared_target} eq "")
- {
- $no_shared_warn = 1
- if (!$disabled{shared} || !$disabled{"dynamic-engine"});
- $disabled{shared} = "no-shared-target";
- $disabled{pic} = $disabled{shared} = $disabled{"dynamic-engine"} =
- "no-shared-target";
- }
+ {
+ $no_shared_warn = 1
+ if (!$disabled{shared} || !$disabled{"dynamic-engine"});
+ disable('no-shared-target', 'pic');
+ }
if ($disabled{"dynamic-engine"}) {
push @{$config{openssl_other_defines}}, "OPENSSL_NO_DYNAMIC_ENGINE";
$config{dynamic_engines} = 0;
} else {
push @{$config{openssl_other_defines}}, "OPENSSL_NO_STATIC_ENGINE";
$config{dynamic_engines} = 1;
}
unless ($disabled{asan}) {
push @{$config{cflags}}, "-fsanitize=address";
- push @{$config{cxxflags}}, "-fsanitize=address" if $config{CXX};
}
unless ($disabled{ubsan}) {
# -DPEDANTIC or -fnosanitize=alignment may also be required on some
# platforms.
push @{$config{cflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all";
- push @{$config{cxxflags}}, "-fsanitize=undefined", "-fno-sanitize-recover=all"
- if $config{CXX};
}
unless ($disabled{msan}) {
push @{$config{cflags}}, "-fsanitize=memory";
- push @{$config{cxxflags}}, "-fsanitize=memory" if $config{CXX};
}
unless ($disabled{"fuzz-libfuzzer"} && $disabled{"fuzz-afl"}
&& $disabled{asan} && $disabled{ubsan} && $disabled{msan}) {
push @{$config{cflags}}, "-fno-omit-frame-pointer", "-g";
push @{$config{cxxflags}}, "-fno-omit-frame-pointer", "-g" if $config{CXX};
}
#
# Platform fix-ups
#
# This saves the build files from having to check
if ($disabled{pic})
- {
- foreach (qw(shared_cflag shared_cxxflag shared_cppflag
- shared_defines shared_includes shared_ldflag
- module_cflags module_cxxflags module_cppflags
- module_defines module_includes module_lflags))
- {
- delete $config{$_};
- $target{$_} = "";
- }
- }
+ {
+ foreach (qw(shared_cflag shared_cxxflag shared_cppflag
+ shared_defines shared_includes shared_ldflag
+ module_cflags module_cxxflags module_cppflags
+ module_defines module_includes module_lflags))
+ {
+ delete $config{$_};
+ $target{$_} = "";
+ }
+ }
else
- {
- push @{$config{lib_defines}}, "OPENSSL_PIC";
- }
+ {
+ push @{$config{lib_defines}}, "OPENSSL_PIC";
+ }
if ($target{sys_id} ne "")
- {
- push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
- }
+ {
+ push @{$config{openssl_sys_defines}}, "OPENSSL_SYS_$target{sys_id}";
+ }
unless ($disabled{asm}) {
$target{cpuid_asm_src}=$table{DEFAULTS}->{cpuid_asm_src} if ($config{processor} eq "386");
push @{$config{lib_defines}}, "OPENSSL_CPUID_OBJ" if ($target{cpuid_asm_src} ne "mem_clr.c");
$target{bn_asm_src} =~ s/\w+-gf2m.c// if (defined($disabled{ec2m}));
# bn-586 is the only one implementing bn_*_part_words
push @{$config{lib_defines}}, "OPENSSL_BN_ASM_PART_WORDS" if ($target{bn_asm_src} =~ /bn-586/);
push @{$config{lib_defines}}, "OPENSSL_IA32_SSE2" if (!$disabled{sse2} && $target{bn_asm_src} =~ /86/);
push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT" if ($target{bn_asm_src} =~ /-mont/);
push @{$config{lib_defines}}, "OPENSSL_BN_ASM_MONT5" if ($target{bn_asm_src} =~ /-mont5/);
push @{$config{lib_defines}}, "OPENSSL_BN_ASM_GF2m" if ($target{bn_asm_src} =~ /-gf2m/);
push @{$config{lib_defines}}, "BN_DIV3W" if ($target{bn_asm_src} =~ /-div3w/);
if ($target{sha1_asm_src}) {
- push @{$config{lib_defines}}, "SHA1_ASM" if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
- push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
- push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
+ push @{$config{lib_defines}}, "SHA1_ASM" if ($target{sha1_asm_src} =~ /sx86/ || $target{sha1_asm_src} =~ /sha1/);
+ push @{$config{lib_defines}}, "SHA256_ASM" if ($target{sha1_asm_src} =~ /sha256/);
+ push @{$config{lib_defines}}, "SHA512_ASM" if ($target{sha1_asm_src} =~ /sha512/);
}
if ($target{keccak1600_asm_src} ne $table{DEFAULTS}->{keccak1600_asm_src}) {
- push @{$config{lib_defines}}, "KECCAK1600_ASM";
+ push @{$config{lib_defines}}, "KECCAK1600_ASM";
}
if ($target{rc4_asm_src} ne $table{DEFAULTS}->{rc4_asm_src}) {
- push @{$config{lib_defines}}, "RC4_ASM";
+ push @{$config{lib_defines}}, "RC4_ASM";
}
if ($target{md5_asm_src}) {
- push @{$config{lib_defines}}, "MD5_ASM";
+ push @{$config{lib_defines}}, "MD5_ASM";
}
$target{cast_asm_src}=$table{DEFAULTS}->{cast_asm_src} unless $disabled{pic}; # CAST assembler is not PIC
if ($target{rmd160_asm_src}) {
- push @{$config{lib_defines}}, "RMD160_ASM";
+ push @{$config{lib_defines}}, "RMD160_ASM";
}
if ($target{aes_asm_src}) {
- push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
- # aes-ctr.fake is not a real file, only indication that assembler
- # module implements AES_ctr32_encrypt...
- push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
- # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
- push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
- $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2});
- push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
- push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
+ push @{$config{lib_defines}}, "AES_ASM" if ($target{aes_asm_src} =~ m/\baes-/);;
+ # aes-ctr.fake is not a real file, only indication that assembler
+ # module implements AES_ctr32_encrypt...
+ push @{$config{lib_defines}}, "AES_CTR_ASM" if ($target{aes_asm_src} =~ s/\s*aes-ctr\.fake//);
+ # aes-xts.fake indicates presence of AES_xts_[en|de]crypt...
+ push @{$config{lib_defines}}, "AES_XTS_ASM" if ($target{aes_asm_src} =~ s/\s*aes-xts\.fake//);
+ $target{aes_asm_src} =~ s/\s*(vpaes|aesni)-x86\.s//g if ($disabled{sse2});
+ push @{$config{lib_defines}}, "VPAES_ASM" if ($target{aes_asm_src} =~ m/vpaes/);
+ push @{$config{lib_defines}}, "BSAES_ASM" if ($target{aes_asm_src} =~ m/bsaes/);
}
if ($target{wp_asm_src} =~ /mmx/) {
if ($config{processor} eq "386") {
- $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
- } elsif (!$disabled{"whirlpool"}) {
- push @{$config{lib_defines}}, "WHIRLPOOL_ASM";
- }
+ $target{wp_asm_src}=$table{DEFAULTS}->{wp_asm_src};
+ } elsif (!$disabled{"whirlpool"}) {
+ push @{$config{lib_defines}}, "WHIRLPOOL_ASM";
+ }
}
if ($target{modes_asm_src} =~ /ghash-/) {
- push @{$config{lib_defines}}, "GHASH_ASM";
+ push @{$config{lib_defines}}, "GHASH_ASM";
}
if ($target{ec_asm_src} =~ /ecp_nistz256/) {
- push @{$config{lib_defines}}, "ECP_NISTZ256_ASM";
+ push @{$config{lib_defines}}, "ECP_NISTZ256_ASM";
}
if ($target{ec_asm_src} =~ /x25519/) {
- push @{$config{lib_defines}}, "X25519_ASM";
+ push @{$config{lib_defines}}, "X25519_ASM";
}
if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
- push @{$config{lib_defines}}, "PADLOCK_ASM";
+ push @{$config{dso_defines}}, "PADLOCK_ASM";
}
if ($target{poly1305_asm_src} ne "") {
- push @{$config{lib_defines}}, "POLY1305_ASM";
+ push @{$config{lib_defines}}, "POLY1305_ASM";
}
}
-my %predefined = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
+my %predefined_C = compiler_predefined($config{CROSS_COMPILE}.$config{CC});
+my %predefined_CXX = $config{CXX}
+ ? compiler_predefined($config{CROSS_COMPILE}.$config{CXX})
+ : ();
# Check for makedepend capabilities.
if (!$disabled{makedepend}) {
if ($config{target} =~ /^(VC|vms)-/) {
# For VC- and vms- targets, there's nothing more to do here. The
# functionality is hard coded in the corresponding build files for
# cl (Windows) and CC/DECC (VMS).
- } elsif (($predefined{__GNUC__} // -1) >= 3
- && !($predefined{__APPLE_CC__} && !$predefined{__clang__})) {
+ } elsif (($predefined_C{__GNUC__} // -1) >= 3
+ && !($predefined_C{__APPLE_CC__} && !$predefined_C{__clang__})) {
# We know that GNU C version 3 and up as well as all clang
# versions support dependency generation, but Xcode did not
# handle $cc -M before clang support (but claims __GNUC__ = 3)
$config{makedepprog} = "\$(CROSS_COMPILE)$config{CC}";
} else {
# In all other cases, we look for 'makedepend', and disable the
# capability if not found.
$config{makedepprog} = which('makedepend');
- $disabled{makedepend} = "unavailable" unless $config{makedepprog};
+ disable('unavailable', 'makedepend') unless $config{makedepprog};
}
}
-if (!$disabled{asm} && !$predefined{__MACH__} && $^O ne 'VMS') {
+if (!$disabled{asm} && !$predefined_C{__MACH__} && $^O ne 'VMS') {
# probe for -Wa,--noexecstack option...
- if ($predefined{__clang__}) {
+ if ($predefined_C{__clang__}) {
# clang has builtin assembler, which doesn't recognize --help,
# but it apparently recognizes the option in question on all
# supported platforms even when it's meaningless. In other words
# probe would fail, but probed option always accepted...
push @{$config{cflags}}, "-Wa,--noexecstack", "-Qunused-arguments";
} else {
my $cc = $config{CROSS_COMPILE}.$config{CC};
open(PIPE, "$cc -Wa,--help -c -o null.$$.o -x assembler /dev/null 2>&1 |");
while(<PIPE>) {
if (m/--noexecstack/) {
push @{$config{cflags}}, "-Wa,--noexecstack";
last;
}
}
close(PIPE);
unlink("null.$$.o");
}
}
# Deal with bn_ops ###################################################
-$config{bn_ll} =0;
-$config{export_var_as_fn} =0;
+$config{bn_ll} =0;
+$config{export_var_as_fn} =0;
my $def_int="unsigned int";
-$config{rc4_int} =$def_int;
+$config{rc4_int} =$def_int;
($config{b64l},$config{b64},$config{b32})=(0,0,1);
my $count = 0;
foreach (sort split(/\s+/,$target{bn_ops})) {
$count++ if /SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT/;
$config{export_var_as_fn}=1 if $_ eq 'EXPORT_VAR_AS_FN';
- $config{bn_ll}=1 if $_ eq 'BN_LLONG';
- $config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR';
+ $config{bn_ll}=1 if $_ eq 'BN_LLONG';
+ $config{rc4_int}="unsigned char" if $_ eq 'RC4_CHAR';
($config{b64l},$config{b64},$config{b32})
- =(0,1,0) if $_ eq 'SIXTY_FOUR_BIT';
+ =(0,1,0) if $_ eq 'SIXTY_FOUR_BIT';
($config{b64l},$config{b64},$config{b32})
- =(1,0,0) if $_ eq 'SIXTY_FOUR_BIT_LONG';
+ =(1,0,0) if $_ eq 'SIXTY_FOUR_BIT_LONG';
($config{b64l},$config{b64},$config{b32})
- =(0,0,1) if $_ eq 'THIRTY_TWO_BIT';
+ =(0,0,1) if $_ eq 'THIRTY_TWO_BIT';
}
die "Exactly one of SIXTY_FOUR_BIT|SIXTY_FOUR_BIT_LONG|THIRTY_TWO_BIT can be set in bn_ops\n"
if $count > 1;
# Hack cflags for better warnings (dev option) #######################
# "Stringify" the C and C++ flags string. This permits it to be made part of
# a string and works as well on command lines.
$config{cflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
@{$config{cflags}} ];
$config{cxxflags} = [ map { (my $x = $_) =~ s/([\\\"])/\\$1/g; $x }
@{$config{cxxflags}} ] if $config{CXX};
if (defined($config{api})) {
$config{openssl_api_defines} = [ "OPENSSL_MIN_API=".$apitable->{$config{api}} ];
my $apiflag = sprintf("OPENSSL_API_COMPAT=%s", $apitable->{$config{api}});
push @{$config{defines}}, $apiflag;
}
+my @strict_warnings_collection=();
if ($strict_warnings)
- {
- my $wopt;
- my $gccver = $predefined{__GNUC__} // -1;
+ {
+ my $wopt;
+ my $gccver = $predefined_C{__GNUC__} // -1;
- die "ERROR --strict-warnings requires gcc[>=4] or gcc-alike"
+ warn "WARNING --strict-warnings requires gcc[>=4] or gcc-alike"
unless $gccver >= 4;
- foreach $wopt (split /\s+/, $gcc_devteam_warn)
- {
- push @{$config{cflags}}, $wopt
- unless grep { $_ eq $wopt } @{$config{cflags}};
- push @{$config{cxxflags}}, $wopt
- if ($config{CXX}
- && !grep { $_ eq $wopt } @{$config{cxxflags}});
- }
- if (defined($predefined{__clang__}))
- {
- foreach $wopt (split /\s+/, $clang_devteam_warn)
- {
- push @{$config{cflags}}, $wopt
- unless grep { $_ eq $wopt } @{$config{cflags}};
- push @{$config{cxxflags}}, $wopt
- if ($config{CXX}
- && !grep { $_ eq $wopt } @{$config{cxxflags}});
- }
- }
- }
+ push @strict_warnings_collection, @gcc_devteam_warn;
+ push @strict_warnings_collection, @clang_devteam_warn
+ if (defined($predefined_C{__clang__}));
+ }
+
+if (grep { $_ eq '-static' } @{$config{LDFLAGS}}) {
+ disable('static', 'pic', 'threads');
+}
+
+$config{CFLAGS} = [ map { $_ eq '--ossl-strict-warnings'
+ ? @strict_warnings_collection
+ : ( $_ ) }
+ @{$config{CFLAGS}} ];
unless ($disabled{"crypto-mdebug-backtrace"})
- {
- foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
- {
- push @{$config{cflags}}, $wopt
- unless grep { $_ eq $wopt } @{$config{cflags}};
- push @{$config{cxxflags}}, $wopt
- if ($config{CXX}
- && !grep { $_ eq $wopt } @{$config{cxxflags}});
- }
- if ($target =~ /^BSD-/)
- {
- push @{$config{ex_libs}}, "-lexecinfo";
- }
- }
+ {
+ foreach my $wopt (split /\s+/, $memleak_devteam_backtrace)
+ {
+ push @{$config{cflags}}, $wopt
+ unless grep { $_ eq $wopt } @{$config{cflags}};
+ }
+ if ($target =~ /^BSD-/)
+ {
+ push @{$config{ex_libs}}, "-lexecinfo";
+ }
+ }
unless ($disabled{afalgeng}) {
$config{afalgeng}="";
if (grep { $_ eq 'afalgeng' } @{$target{enable}}) {
my $minver = 4*10000 + 1*100 + 0;
if ($config{CROSS_COMPILE} eq "") {
my $verstr = `uname -r`;
my ($ma, $mi1, $mi2) = split("\\.", $verstr);
($mi2) = $mi2 =~ /(\d+)/;
my $ver = $ma*10000 + $mi1*100 + $mi2;
if ($ver < $minver) {
- $disabled{afalgeng} = "too-old-kernel";
+ disable('too-old-kernel', 'afalgeng');
} else {
push @{$config{engdirs}}, "afalg";
}
} else {
- $disabled{afalgeng} = "cross-compiling";
+ disable('cross-compiling', 'afalgeng');
}
} else {
- $disabled{afalgeng} = "not-linux";
+ disable('not-linux', 'afalgeng');
}
}
push @{$config{openssl_other_defines}}, "OPENSSL_NO_AFALGENG" if ($disabled{afalgeng});
-# Finish up %config by appending things the user gave us on the command line
-# apart from "make variables"
-foreach (keys %useradd) {
- # The must all be lists, so we assert that here
- die "internal error: \$useradd{$_} isn't an ARRAY\n"
- unless ref $useradd{$_} eq 'ARRAY';
+# Get the extra flags used when building shared libraries and modules. We
+# do this late because some of them depend on %disabled.
- if (defined $config{$_}) {
- push @{$config{$_}}, @{$useradd{$_}};
- } else {
- $config{$_} = [ @{$useradd{$_}} ];
+# Make the flags to build DSOs the same as for shared libraries unless they
+# are already defined
+$target{module_cflags} = $target{shared_cflag} unless defined $target{module_cflags};
+$target{module_cxxflags} = $target{shared_cxxflag} unless defined $target{module_cxxflags};
+$target{module_ldflags} = $target{shared_ldflag} unless defined $target{module_ldflags};
+{
+ my $shared_info_pl =
+ catfile(dirname($0), "Configurations", "shared-info.pl");
+ my %shared_info = read_eval_file($shared_info_pl);
+ push @{$target{_conf_fname_int}}, $shared_info_pl;
+ my $si = $target{shared_target};
+ while (ref $si ne "HASH") {
+ last if ! defined $si;
+ if (ref $si eq "CODE") {
+ $si = $si->();
+ } else {
+ $si = $shared_info{$si};
+ }
+ }
+
+ # Some of the 'shared_target' values don't have any entries in
+ # %shared_info. That's perfectly fine, AS LONG AS the build file
+ # template knows how to handle this. That is currently the case for
+ # Windows and VMS.
+ if (defined $si) {
+ # Just as above, copy certain shared_* attributes to the corresponding
+ # module_ attribute unless the latter is already defined
+ $si->{module_cflags} = $si->{shared_cflag} unless defined $si->{module_cflags};
+ $si->{module_cxxflags} = $si->{shared_cxxflag} unless defined $si->{module_cxxflags};
+ $si->{module_ldflags} = $si->{shared_ldflag} unless defined $si->{module_ldflags};
+ foreach (sort keys %$si) {
+ $target{$_} = defined $target{$_}
+ ? add($si->{$_})->($target{$_})
+ : $si->{$_};
+ }
}
}
-# ALL MODIFICATIONS TO %config and %target MUST BE DONE FROM HERE ON
+# ALL MODIFICATIONS TO %disabled, %config and %target MUST BE DONE FROM HERE ON
# If we use the unified build, collect information from build.info files
my %unified_info = ();
my $buildinfo_debug = defined($ENV{CONFIGURE_DEBUG_BUILDINFO});
if ($builder eq "unified") {
use with_fallback qw(Text::Template);
sub cleandir {
my $base = shift;
my $dir = shift;
my $relativeto = shift || ".";
$dir = catdir($base,$dir) unless isabsolute($dir);
# Make sure the directories we're building in exists
mkpath($dir);
my $res = abs2rel(absolutedir($dir), rel2abs($relativeto));
#print STDERR "DEBUG[cleandir]: $dir , $base => $res\n";
return $res;
}
sub cleanfile {
my $base = shift;
my $file = shift;
my $relativeto = shift || ".";
$file = catfile($base,$file) unless isabsolute($file);
my $d = dirname($file);
my $f = basename($file);
# Make sure the directories we're building in exists
mkpath($d);
my $res = abs2rel(catfile(absolutedir($d), $f), rel2abs($relativeto));
#print STDERR "DEBUG[cleanfile]: $d , $f => $res\n";
return $res;
}
# Store the name of the template file we will build the build file from
# in %config. This may be useful for the build file itself.
my @build_file_template_names =
- ( $builder_platform."-".$target{build_file}.".tmpl",
- $target{build_file}.".tmpl" );
+ ( $builder_platform."-".$target{build_file}.".tmpl",
+ $target{build_file}.".tmpl" );
my @build_file_templates = ();
# First, look in the user provided directory, if given
if (defined env($local_config_envname)) {
- @build_file_templates =
- map {
- if ($^O eq 'VMS') {
- # VMS environment variables are logical names,
- # which can be used as is
- $local_config_envname . ':' . $_;
- } else {
- catfile(env($local_config_envname), $_);
- }
- }
- @build_file_template_names;
+ @build_file_templates =
+ map {
+ if ($^O eq 'VMS') {
+ # VMS environment variables are logical names,
+ # which can be used as is
+ $local_config_envname . ':' . $_;
+ } else {
+ catfile(env($local_config_envname), $_);
+ }
+ }
+ @build_file_template_names;
}
# Then, look in our standard directory
push @build_file_templates,
- ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
- @build_file_template_names );
+ ( map { cleanfile($srcdir, catfile("Configurations", $_), $blddir) }
+ @build_file_template_names );
my $build_file_template;
for $_ (@build_file_templates) {
- $build_file_template = $_;
+ $build_file_template = $_;
last if -f $build_file_template;
$build_file_template = undef;
}
if (!defined $build_file_template) {
- die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
+ die "*** Couldn't find any of:\n", join("\n", @build_file_templates), "\n";
}
$config{build_file_templates}
= [ cleanfile($srcdir, catfile("Configurations", "common0.tmpl"),
$blddir),
$build_file_template,
cleanfile($srcdir, catfile("Configurations", "common.tmpl"),
$blddir) ];
my @build_infos = ( [ ".", "build.info" ] );
foreach (@{$config{dirs}}) {
push @build_infos, [ $_, "build.info" ]
if (-f catfile($srcdir, $_, "build.info"));
}
foreach (@{$config{sdirs}}) {
push @build_infos, [ catdir("crypto", $_), "build.info" ]
if (-f catfile($srcdir, "crypto", $_, "build.info"));
}
foreach (@{$config{engdirs}}) {
push @build_infos, [ catdir("engines", $_), "build.info" ]
if (-f catfile($srcdir, "engines", $_, "build.info"));
}
foreach (@{$config{tdirs}}) {
push @build_infos, [ catdir("test", $_), "build.info" ]
if (-f catfile($srcdir, "test", $_, "build.info"));
}
$config{build_infos} = [ ];
my %ordinals = ();
foreach (@build_infos) {
my $sourced = catdir($srcdir, $_->[0]);
my $buildd = catdir($blddir, $_->[0]);
mkpath($buildd);
my $f = $_->[1];
# The basic things we're trying to build
my @programs = ();
my @programs_install = ();
my @libraries = ();
my @libraries_install = ();
my @engines = ();
my @engines_install = ();
my @scripts = ();
my @scripts_install = ();
my @extra = ();
my @overrides = ();
my @intermediates = ();
my @rawlines = ();
my %sources = ();
my %shared_sources = ();
my %includes = ();
my %depends = ();
my %renames = ();
my %sharednames = ();
my %generate = ();
# We want to detect configdata.pm in the source tree, so we
# don't use it if the build tree is different.
my $src_configdata = cleanfile($srcdir, "configdata.pm", $blddir);
push @{$config{build_infos}}, catfile(abs2rel($sourced, $blddir), $f);
my $template =
Text::Template->new(TYPE => 'FILE',
SOURCE => catfile($sourced, $f),
PREPEND => qq{use lib "$FindBin::Bin/util/perl";});
die "Something went wrong with $sourced/$f: $!\n" unless $template;
my @text =
split /^/m,
$template->fill_in(HASH => { config => \%config,
target => \%target,
disabled => \%disabled,
withargs => \%withargs,
builddir => abs2rel($buildd, $blddir),
sourcedir => abs2rel($sourced, $blddir),
buildtop => abs2rel($blddir, $blddir),
sourcetop => abs2rel($srcdir, $blddir) },
DELIMITERS => [ "{-", "-}" ]);
# The top item of this stack has the following values
# -2 positive already run and we found ELSE (following ELSIF should fail)
# -1 positive already run (skip until ENDIF)
# 0 negatives so far (if we're at a condition, check it)
# 1 last was positive (don't skip lines until next ELSE, ELSIF or ENDIF)
# 2 positive ELSE (following ELSIF should fail)
my @skip = ();
collect_information(
collect_from_array([ @text ],
qr/\\$/ => sub { my $l1 = shift; my $l2 = shift;
$l1 =~ s/\\$//; $l1.$l2 }),
# Info we're looking for
qr/^\s*IF\[((?:\\.|[^\\\]])*)\]\s*$/
=> sub {
if (! @skip || $skip[$#skip] > 0) {
push @skip, !! $1;
} else {
push @skip, -1;
}
},
qr/^\s*ELSIF\[((?:\\.|[^\\\]])*)\]\s*$/
=> sub { die "ELSIF out of scope" if ! @skip;
die "ELSIF following ELSE" if abs($skip[$#skip]) == 2;
$skip[$#skip] = -1 if $skip[$#skip] != 0;
$skip[$#skip] = !! $1
if $skip[$#skip] == 0; },
qr/^\s*ELSE\s*$/
=> sub { die "ELSE out of scope" if ! @skip;
$skip[$#skip] = -2 if $skip[$#skip] != 0;
$skip[$#skip] = 2 if $skip[$#skip] == 0; },
qr/^\s*ENDIF\s*$/
=> sub { die "ENDIF out of scope" if ! @skip;
pop @skip; },
qr/^\s*PROGRAMS(_NO_INST)?\s*=\s*(.*)\s*$/
=> sub {
if (!@skip || $skip[$#skip] > 0) {
my $install = $1;
my @x = tokenize($2);
push @programs, @x;
push @programs_install, @x unless $install;
}
},
qr/^\s*LIBS(_NO_INST)?\s*=\s*(.*)\s*$/
=> sub {
if (!@skip || $skip[$#skip] > 0) {
my $install = $1;
my @x = tokenize($2);
push @libraries, @x;
push @libraries_install, @x unless $install;
}
},
qr/^\s*ENGINES(_NO_INST)?\s*=\s*(.*)\s*$/
=> sub {
if (!@skip || $skip[$#skip] > 0) {
my $install = $1;
my @x = tokenize($2);
push @engines, @x;
push @engines_install, @x unless $install;
}
},
qr/^\s*SCRIPTS(_NO_INST)?\s*=\s*(.*)\s*$/
=> sub {
if (!@skip || $skip[$#skip] > 0) {
my $install = $1;
my @x = tokenize($2);
push @scripts, @x;
push @scripts_install, @x unless $install;
}
},
qr/^\s*EXTRA\s*=\s*(.*)\s*$/
=> sub { push @extra, tokenize($1)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*OVERRIDES\s*=\s*(.*)\s*$/
=> sub { push @overrides, tokenize($1)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*ORDINALS\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/,
=> sub { push @{$ordinals{$1}}, tokenize($2)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
=> sub { push @{$sources{$1}}, tokenize($2)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*SHARED_SOURCE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
=> sub { push @{$shared_sources{$1}}, tokenize($2)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*INCLUDE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
=> sub { push @{$includes{$1}}, tokenize($2)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*DEPEND\[((?:\\.|[^\\\]])*)\]\s*=\s*(.*)\s*$/
=> sub { push @{$depends{$1}}, tokenize($2)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*GENERATE\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
=> sub { push @{$generate{$1}}, $2
if !@skip || $skip[$#skip] > 0 },
qr/^\s*RENAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
=> sub { push @{$renames{$1}}, tokenize($2)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*SHARED_NAME\[((?:\\.|[^\\\]])+)\]\s*=\s*(.*)\s*$/
=> sub { push @{$sharednames{$1}}, tokenize($2)
if !@skip || $skip[$#skip] > 0 },
qr/^\s*BEGINRAW\[((?:\\.|[^\\\]])+)\]\s*$/
=> sub {
my $lineiterator = shift;
my $target_kind = $1;
while (defined $lineiterator->()) {
s|\R$||;
if (/^\s*ENDRAW\[((?:\\.|[^\\\]])+)\]\s*$/) {
die "ENDRAW doesn't match BEGINRAW"
if $1 ne $target_kind;
last;
}
next if @skip && $skip[$#skip] <= 0;
push @rawlines, $_
if ($target_kind eq $target{build_file}
|| $target_kind eq $target{build_file}."(".$builder_platform.")");
}
},
qr/^\s*(?:#.*)?$/ => sub { },
"OTHERWISE" => sub { die "Something wrong with this line:\n$_\nat $sourced/$f" },
"BEFORE" => sub {
if ($buildinfo_debug) {
print STDERR "DEBUG: Parsing ",join(" ", @_),"\n";
print STDERR "DEBUG: ... before parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
}
},
"AFTER" => sub {
if ($buildinfo_debug) {
print STDERR "DEBUG: .... after parsing, skip stack is ",join(" ", map { int($_) } @skip),"\n";
}
},
);
die "runaway IF?" if (@skip);
foreach (keys %renames) {
die "$_ renamed to more than one thing: "
,join(" ", @{$renames{$_}}),"\n"
if scalar @{$renames{$_}} > 1;
my $dest = cleanfile($buildd, $_, $blddir);
my $to = cleanfile($buildd, $renames{$_}->[0], $blddir);
die "$dest renamed to more than one thing: "
,$unified_info{rename}->{$dest}, $to
unless !defined($unified_info{rename}->{$dest})
or $unified_info{rename}->{$dest} eq $to;
$unified_info{rename}->{$dest} = $to;
}
foreach (@programs) {
my $program = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$program}) {
$program = $unified_info{rename}->{$program};
}
$unified_info{programs}->{$program} = 1;
}
foreach (@programs_install) {
my $program = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$program}) {
$program = $unified_info{rename}->{$program};
}
$unified_info{install}->{programs}->{$program} = 1;
}
foreach (@libraries) {
my $library = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$library}) {
$library = $unified_info{rename}->{$library};
}
$unified_info{libraries}->{$library} = 1;
}
foreach (@libraries_install) {
my $library = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$library}) {
$library = $unified_info{rename}->{$library};
}
$unified_info{install}->{libraries}->{$library} = 1;
}
die <<"EOF" if scalar @engines and !$config{dynamic_engines};
ENGINES can only be used if configured with 'dynamic-engine'.
This is usually a fault in a build.info file.
EOF
foreach (@engines) {
my $library = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$library}) {
$library = $unified_info{rename}->{$library};
}
$unified_info{engines}->{$library} = 1;
}
foreach (@engines_install) {
my $library = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$library}) {
$library = $unified_info{rename}->{$library};
}
$unified_info{install}->{engines}->{$library} = 1;
}
foreach (@scripts) {
my $script = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$script}) {
$script = $unified_info{rename}->{$script};
}
$unified_info{scripts}->{$script} = 1;
}
foreach (@scripts_install) {
my $script = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$script}) {
$script = $unified_info{rename}->{$script};
}
$unified_info{install}->{scripts}->{$script} = 1;
}
foreach (@extra) {
my $extra = cleanfile($buildd, $_, $blddir);
$unified_info{extra}->{$extra} = 1;
}
foreach (@overrides) {
my $override = cleanfile($buildd, $_, $blddir);
$unified_info{overrides}->{$override} = 1;
}
push @{$unified_info{rawlines}}, @rawlines;
unless ($disabled{shared}) {
# Check sharednames.
foreach (keys %sharednames) {
my $dest = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$dest}) {
$dest = $unified_info{rename}->{$dest};
}
die "shared_name for $dest with multiple values: "
,join(" ", @{$sharednames{$_}}),"\n"
if scalar @{$sharednames{$_}} > 1;
my $to = cleanfile($buildd, $sharednames{$_}->[0], $blddir);
die "shared_name found for a library $dest that isn't defined\n"
unless $unified_info{libraries}->{$dest};
die "shared_name for $dest with multiple values: "
,$unified_info{sharednames}->{$dest}, ", ", $to
unless !defined($unified_info{sharednames}->{$dest})
or $unified_info{sharednames}->{$dest} eq $to;
$unified_info{sharednames}->{$dest} = $to;
}
# Additionally, we set up sharednames for libraries that don't
# have any, as themselves. Only for libraries that aren't
# explicitly static.
foreach (grep !/\.a$/, keys %{$unified_info{libraries}}) {
if (!defined $unified_info{sharednames}->{$_}) {
$unified_info{sharednames}->{$_} = $_
}
}
# Check that we haven't defined any library as both shared and
# explicitly static. That is forbidden.
my @doubles = ();
foreach (grep /\.a$/, keys %{$unified_info{libraries}}) {
(my $l = $_) =~ s/\.a$//;
push @doubles, $l if defined $unified_info{sharednames}->{$l};
}
die "these libraries are both explicitly static and shared:\n ",
join(" ", @doubles), "\n"
if @doubles;
}
foreach (keys %sources) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$ddest}) {
$ddest = $unified_info{rename}->{$ddest};
}
foreach (@{$sources{$dest}}) {
my $s = cleanfile($sourced, $_, $blddir);
# If it isn't in the source tree, we assume it's generated
# in the build tree
if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
$s = cleanfile($buildd, $_, $blddir);
}
# We recognise C++, C and asm files
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
my $o = $_;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$o = cleanfile($buildd, $o, $blddir);
$unified_info{sources}->{$ddest}->{$o} = 1;
$unified_info{sources}->{$o}->{$s} = 1;
} elsif ($s =~ /\.rc$/) {
# We also recognise resource files
my $o = $_;
$o =~ s/\.rc$/.res/; # Resource configuration
my $o = cleanfile($buildd, $o, $blddir);
$unified_info{sources}->{$ddest}->{$o} = 1;
$unified_info{sources}->{$o}->{$s} = 1;
} else {
$unified_info{sources}->{$ddest}->{$s} = 1;
}
}
}
foreach (keys %shared_sources) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$ddest}) {
$ddest = $unified_info{rename}->{$ddest};
}
foreach (@{$shared_sources{$dest}}) {
my $s = cleanfile($sourced, $_, $blddir);
# If it isn't in the source tree, we assume it's generated
# in the build tree
if ($s eq $src_configdata || ! -f $s || $generate{$_}) {
$s = cleanfile($buildd, $_, $blddir);
}
if ($s =~ /\.(cc|cpp|c|s|S)$/) {
# We recognise C++, C and asm files
my $o = $_;
$o =~ s/\.[csS]$/.o/; # C and assembler
$o =~ s/\.(cc|cpp)$/_cc.o/; # C++
$o = cleanfile($buildd, $o, $blddir);
$unified_info{shared_sources}->{$ddest}->{$o} = 1;
$unified_info{sources}->{$o}->{$s} = 1;
} elsif ($s =~ /\.rc$/) {
# We also recognise resource files
my $o = $_;
$o =~ s/\.rc$/.res/; # Resource configuration
my $o = cleanfile($buildd, $o, $blddir);
$unified_info{shared_sources}->{$ddest}->{$o} = 1;
$unified_info{sources}->{$o}->{$s} = 1;
} elsif ($s =~ /\.(def|map|opt)$/) {
# We also recognise .def / .map / .opt files
# We know they are generated files
my $def = cleanfile($buildd, $s, $blddir);
$unified_info{shared_sources}->{$ddest}->{$def} = 1;
} else {
die "unrecognised source file type for shared library: $s\n";
}
}
}
foreach (keys %generate) {
my $dest = $_;
my $ddest = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$ddest}) {
$ddest = $unified_info{rename}->{$ddest};
}
die "more than one generator for $dest: "
,join(" ", @{$generate{$_}}),"\n"
if scalar @{$generate{$_}} > 1;
my @generator = split /\s+/, $generate{$dest}->[0];
$generator[0] = cleanfile($sourced, $generator[0], $blddir),
$unified_info{generate}->{$ddest} = [ @generator ];
}
foreach (keys %depends) {
my $dest = $_;
my $ddest = $dest eq "" ? "" : cleanfile($sourced, $_, $blddir);
# If the destination doesn't exist in source, it can only be
# a generated file in the build tree.
if ($ddest ne "" && ($ddest eq $src_configdata || ! -f $ddest)) {
$ddest = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$ddest}) {
$ddest = $unified_info{rename}->{$ddest};
}
}
foreach (@{$depends{$dest}}) {
my $d = cleanfile($sourced, $_, $blddir);
# If we know it's generated, or assume it is because we can't
# find it in the source tree, we set file we depend on to be
# in the build tree rather than the source tree, and assume
# and that there are lines to build it in a BEGINRAW..ENDRAW
# section or in the Makefile template.
if ($d eq $src_configdata
|| ! -f $d
|| (grep { $d eq $_ }
map { cleanfile($srcdir, $_, $blddir) }
grep { /\.h$/ } keys %{$unified_info{generate}})) {
$d = cleanfile($buildd, $_, $blddir);
}
# Take note if the file to depend on is being renamed
# Take extra care with files ending with .a, they should
# be treated without that extension, and the extension
# should be added back after treatment.
$d =~ /(\.a)?$/;
my $e = $1 // "";
$d = $`;
if ($unified_info{rename}->{$d}) {
$d = $unified_info{rename}->{$d};
}
$d .= $e;
$unified_info{depends}->{$ddest}->{$d} = 1;
}
}
foreach (keys %includes) {
my $dest = $_;
my $ddest = cleanfile($sourced, $_, $blddir);
# If the destination doesn't exist in source, it can only be
# a generated file in the build tree.
if ($ddest eq $src_configdata || ! -f $ddest) {
$ddest = cleanfile($buildd, $_, $blddir);
if ($unified_info{rename}->{$ddest}) {
$ddest = $unified_info{rename}->{$ddest};
}
}
foreach (@{$includes{$dest}}) {
my $is = cleandir($sourced, $_, $blddir);
my $ib = cleandir($buildd, $_, $blddir);
push @{$unified_info{includes}->{$ddest}->{source}}, $is
unless grep { $_ eq $is } @{$unified_info{includes}->{$ddest}->{source}};
push @{$unified_info{includes}->{$ddest}->{build}}, $ib
unless grep { $_ eq $ib } @{$unified_info{includes}->{$ddest}->{build}};
}
}
}
my $ordinals_text = join(', ', sort keys %ordinals);
warn <<"EOF" if $ordinals_text;
WARNING: ORDINALS were specified for $ordinals_text
They are ignored and should be replaced with a combination of GENERATE,
DEPEND and SHARED_SOURCE.
EOF
# Massage the result
# If the user configured no-shared, we allow no shared sources
if ($disabled{shared}) {
foreach (keys %{$unified_info{shared_sources}}) {
foreach (keys %{$unified_info{shared_sources}->{$_}}) {
delete $unified_info{sources}->{$_};
}
}
$unified_info{shared_sources} = {};
}
# If we depend on a header file or a perl module, add an inclusion of
# its directory to allow smoothe inclusion
foreach my $dest (keys %{$unified_info{depends}}) {
next if $dest eq "";
foreach my $d (keys %{$unified_info{depends}->{$dest}}) {
next unless $d =~ /\.(h|pm)$/;
my $i = dirname($d);
my $spot =
$d eq "configdata.pm" || defined($unified_info{generate}->{$d})
? 'build' : 'source';
push @{$unified_info{includes}->{$dest}->{$spot}}, $i
unless grep { $_ eq $i } @{$unified_info{includes}->{$dest}->{$spot}};
}
}
# Trickle down includes placed on libraries, engines and programs to
# their sources (i.e. object files)
foreach my $dest (keys %{$unified_info{engines}},
keys %{$unified_info{libraries}},
keys %{$unified_info{programs}}) {
foreach my $k (("source", "build")) {
next unless defined($unified_info{includes}->{$dest}->{$k});
my @incs = reverse @{$unified_info{includes}->{$dest}->{$k}};
foreach my $obj (grep /\.o$/,
(keys %{$unified_info{sources}->{$dest} // {}},
keys %{$unified_info{shared_sources}->{$dest} // {}})) {
foreach my $inc (@incs) {
unshift @{$unified_info{includes}->{$obj}->{$k}}, $inc
unless grep { $_ eq $inc } @{$unified_info{includes}->{$obj}->{$k}};
}
}
}
delete $unified_info{includes}->{$dest};
}
### Make unified_info a bit more efficient
# One level structures
foreach (("programs", "libraries", "engines", "scripts", "extra", "overrides")) {
$unified_info{$_} = [ sort keys %{$unified_info{$_}} ];
}
# Two level structures
foreach my $l1 (("install", "sources", "shared_sources", "ldadd", "depends")) {
foreach my $l2 (sort keys %{$unified_info{$l1}}) {
$unified_info{$l1}->{$l2} =
[ sort keys %{$unified_info{$l1}->{$l2}} ];
}
}
# Includes
foreach my $dest (sort keys %{$unified_info{includes}}) {
if (defined($unified_info{includes}->{$dest}->{build})) {
my @source_includes = ();
@source_includes = ( @{$unified_info{includes}->{$dest}->{source}} )
if defined($unified_info{includes}->{$dest}->{source});
$unified_info{includes}->{$dest} =
[ @{$unified_info{includes}->{$dest}->{build}} ];
foreach my $inc (@source_includes) {
push @{$unified_info{includes}->{$dest}}, $inc
unless grep { $_ eq $inc } @{$unified_info{includes}->{$dest}};
}
} else {
$unified_info{includes}->{$dest} =
[ @{$unified_info{includes}->{$dest}->{source}} ];
}
}
# For convenience collect information regarding directories where
# files are generated, those generated files and the end product
# they end up in where applicable. Then, add build rules for those
# directories
my %loopinfo = ( "lib" => [ @{$unified_info{libraries}} ],
"dso" => [ @{$unified_info{engines}} ],
"bin" => [ @{$unified_info{programs}} ],
"script" => [ @{$unified_info{scripts}} ] );
foreach my $type (keys %loopinfo) {
foreach my $product (@{$loopinfo{$type}}) {
my %dirs = ();
my $pd = dirname($product);
foreach (@{$unified_info{sources}->{$product} // []},
@{$unified_info{shared_sources}->{$product} // []}) {
my $d = dirname($_);
# We don't want to create targets for source directories
# when building out of source
next if ($config{sourcedir} ne $config{builddir}
&& $d =~ m|^\Q$config{sourcedir}\E|);
# We already have a "test" target, and the current directory
# is just silly to make a target for
next if $d eq "test" || $d eq ".";
$dirs{$d} = 1;
push @{$unified_info{dirinfo}->{$d}->{deps}}, $_
if $d ne $pd;
}
foreach (keys %dirs) {
push @{$unified_info{dirinfo}->{$_}->{products}->{$type}},
$product;
}
}
}
}
# For the schemes that need it, we provide the old *_obj configs
# from the *_asm_obj ones
foreach (grep /_(asm|aux)_src$/, keys %target) {
my $src = $_;
(my $obj = $_) =~ s/_(asm|aux)_src$/_obj/;
$target{$obj} = $target{$src};
$target{$obj} =~ s/\.[csS]\b/.o/g; # C and assembler
$target{$obj} =~ s/\.(cc|cpp)\b/_cc.o/g; # C++
}
# Write down our configuration where it fits #########################
print "Creating configdata.pm\n";
open(OUT,">configdata.pm") || die "unable to create configdata.pm: $!\n";
print OUT <<"EOF";
#! $config{HASHBANGPERL}
package configdata;
use strict;
use warnings;
use Exporter;
#use vars qw(\@ISA \@EXPORT);
our \@ISA = qw(Exporter);
our \@EXPORT = qw(\%config \%target \%disabled \%withargs \%unified_info \@disablables);
EOF
print OUT "our %config = (\n";
foreach (sort keys %config) {
if (ref($config{$_}) eq "ARRAY") {
- print OUT " ", $_, " => [ ", join(", ",
- map { quotify("perl", $_) }
- @{$config{$_}}), " ],\n";
+ print OUT " ", $_, " => [ ", join(", ",
+ map { quotify("perl", $_) }
+ @{$config{$_}}), " ],\n";
} elsif (ref($config{$_}) eq "HASH") {
- print OUT " ", $_, " => {";
+ print OUT " ", $_, " => {";
if (scalar keys %{$config{$_}} > 0) {
print OUT "\n";
foreach my $key (sort keys %{$config{$_}}) {
print OUT " ",
join(" => ",
quotify("perl", $key),
defined $config{$_}->{$key}
? quotify("perl", $config{$_}->{$key})
: "undef");
print OUT ",\n";
}
print OUT " ";
}
print OUT "},\n";
} else {
- print OUT " ", $_, " => ", quotify("perl", $config{$_}), ",\n"
+ print OUT " ", $_, " => ", quotify("perl", $config{$_}), ",\n"
}
}
print OUT <<"EOF";
);
EOF
print OUT "our %target = (\n";
foreach (sort keys %target) {
if (ref($target{$_}) eq "ARRAY") {
- print OUT " ", $_, " => [ ", join(", ",
- map { quotify("perl", $_) }
- @{$target{$_}}), " ],\n";
+ print OUT " ", $_, " => [ ", join(", ",
+ map { quotify("perl", $_) }
+ @{$target{$_}}), " ],\n";
} else {
- print OUT " ", $_, " => ", quotify("perl", $target{$_}), ",\n"
+ print OUT " ", $_, " => ", quotify("perl", $target{$_}), ",\n"
}
}
print OUT <<"EOF";
);
EOF
print OUT "our \%available_protocols = (\n";
print OUT " tls => [ ", join(", ", map { quotify("perl", $_) } @tls), " ],\n";
print OUT " dtls => [ ", join(", ", map { quotify("perl", $_) } @dtls), " ],\n";
print OUT <<"EOF";
);
EOF
print OUT "our \@disablables = (\n";
foreach (@disablables) {
print OUT " ", quotify("perl", $_), ",\n";
}
print OUT <<"EOF";
);
EOF
print OUT "our \%disabled = (\n";
foreach (sort keys %disabled) {
print OUT " ", quotify("perl", $_), " => ", quotify("perl", $disabled{$_}), ",\n";
}
print OUT <<"EOF";
);
EOF
print OUT "our %withargs = (\n";
foreach (sort keys %withargs) {
if (ref($withargs{$_}) eq "ARRAY") {
- print OUT " ", $_, " => [ ", join(", ",
- map { quotify("perl", $_) }
- @{$withargs{$_}}), " ],\n";
+ print OUT " ", $_, " => [ ", join(", ",
+ map { quotify("perl", $_) }
+ @{$withargs{$_}}), " ],\n";
} else {
- print OUT " ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
+ print OUT " ", $_, " => ", quotify("perl", $withargs{$_}), ",\n"
}
}
print OUT <<"EOF";
);
EOF
if ($builder eq "unified") {
my $recurse;
$recurse = sub {
my $indent = shift;
foreach (@_) {
if (ref $_ eq "ARRAY") {
print OUT " "x$indent, "[\n";
foreach (@$_) {
$recurse->($indent + 4, $_);
}
print OUT " "x$indent, "],\n";
} elsif (ref $_ eq "HASH") {
my %h = %$_;
print OUT " "x$indent, "{\n";
foreach (sort keys %h) {
if (ref $h{$_} eq "") {
print OUT " "x($indent + 4), quotify("perl", $_), " => ", quotify("perl", $h{$_}), ",\n";
} else {
print OUT " "x($indent + 4), quotify("perl", $_), " =>\n";
$recurse->($indent + 8, $h{$_});
}
}
print OUT " "x$indent, "},\n";
} else {
print OUT " "x$indent, quotify("perl", $_), ",\n";
}
}
};
print OUT "our %unified_info = (\n";
foreach (sort keys %unified_info) {
if (ref $unified_info{$_} eq "") {
print OUT " "x4, quotify("perl", $_), " => ", quotify("perl", $unified_info{$_}), ",\n";
} else {
print OUT " "x4, quotify("perl", $_), " =>\n";
$recurse->(8, $unified_info{$_});
}
}
print OUT <<"EOF";
);
EOF
}
print OUT
"# The following data is only used when this files is use as a script\n";
print OUT "my \@makevars = (\n";
foreach (sort keys %user) {
print OUT " '",$_,"',\n";
}
print OUT ");\n";
print OUT "my \%disabled_info = (\n";
foreach my $what (sort keys %disabled_info) {
print OUT " '$what' => {\n";
foreach my $info (sort keys %{$disabled_info{$what}}) {
if (ref $disabled_info{$what}->{$info} eq 'ARRAY') {
print OUT " $info => [ ",
join(', ', map { "'$_'" } @{$disabled_info{$what}->{$info}}),
" ],\n";
} else {
print OUT " $info => '", $disabled_info{$what}->{$info},
"',\n";
}
}
print OUT " },\n";
}
print OUT ");\n";
print OUT 'my @user_crossable = qw( ', join (' ', @user_crossable), " );\n";
print OUT << 'EOF';
# If run directly, we can give some answers, and even reconfigure
unless (caller) {
use Getopt::Long;
use File::Spec::Functions;
use File::Basename;
use Pod::Usage;
my $here = dirname($0);
my $dump = undef;
my $cmdline = undef;
my $options = undef;
my $target = undef;
my $envvars = undef;
my $makevars = undef;
my $buildparams = undef;
my $reconf = undef;
my $verbose = undef;
my $help = undef;
my $man = undef;
GetOptions('dump|d' => \$dump,
'command-line|c' => \$cmdline,
'options|o' => \$options,
'target|t' => \$target,
'environment|e' => \$envvars,
'make-variables|m' => \$makevars,
'build-parameters|b' => \$buildparams,
'reconfigure|reconf|r' => \$reconf,
'verbose|v' => \$verbose,
'help' => \$help,
'man' => \$man)
or die "Errors in command line arguments\n";
unless ($dump || $cmdline || $options || $target || $envvars || $makevars
|| $buildparams || $reconf || $verbose || $help || $man) {
print STDERR <<"_____";
You must give at least one option.
For more information, do '$0 --help'
_____
exit(2);
}
if ($help) {
pod2usage(-exitval => 0,
-verbose => 1);
}
if ($man) {
pod2usage(-exitval => 0,
-verbose => 2);
}
if ($dump || $cmdline) {
print "\nCommand line (with current working directory = $here):\n\n";
print ' ',join(' ',
$config{PERL},
catfile($config{sourcedir}, 'Configure'),
@{$config{perlargv}}), "\n";
print "\nPerl information:\n\n";
print ' ',$config{perl_cmd},"\n";
print ' ',$config{perl_version},' for ',$config{perl_archname},"\n";
}
if ($dump || $options) {
my $longest = 0;
my $longest2 = 0;
foreach my $what (@disablables) {
$longest = length($what) if $longest < length($what);
$longest2 = length($disabled{$what})
if $disabled{$what} && $longest2 < length($disabled{$what});
}
print "\nEnabled features:\n\n";
foreach my $what (@disablables) {
print " $what\n" unless $disabled{$what};
}
print "\nDisabled features:\n\n";
foreach my $what (@disablables) {
if ($disabled{$what}) {
print " $what", ' ' x ($longest - length($what) + 1),
"[$disabled{$what}]", ' ' x ($longest2 - length($disabled{$what}) + 1);
print $disabled_info{$what}->{macro}
if $disabled_info{$what}->{macro};
print ' (skip ',
join(', ', @{$disabled_info{$what}->{skipped}}),
')'
if $disabled_info{$what}->{skipped};
print "\n";
}
}
}
if ($dump || $target) {
print "\nConfig target attributes:\n\n";
foreach (sort keys %target) {
next if $_ =~ m|^_| || $_ eq 'template';
my $quotify = sub {
map { (my $x = $_) =~ s|([\\\$\@"])|\\$1|g; "\"$x\""} @_;
};
print ' ', $_, ' => ';
if (ref($target{$_}) eq "ARRAY") {
print '[ ', join(', ', $quotify->(@{$target{$_}})), " ],\n";
} else {
print $quotify->($target{$_}), ",\n"
}
}
}
if ($dump || $envvars) {
print "\nRecorded environment:\n\n";
foreach (sort keys %{$config{perlenv}}) {
print ' ',$_,' = ',($config{perlenv}->{$_} || ''),"\n";
}
}
if ($dump || $makevars) {
print "\nMakevars:\n\n";
foreach my $var (@makevars) {
my $prefix = '';
$prefix = $config{CROSS_COMPILE}
if grep { $var eq $_ } @user_crossable;
$prefix //= '';
print ' ',$var,' ' x (16 - length $var),'= ',
(ref $config{$var} eq 'ARRAY'
? join(' ', @{$config{$var}})
: $prefix.$config{$var}),
"\n"
if defined $config{$var};
}
my @buildfile = ($config{builddir}, $config{build_file});
unshift @buildfile, $here
unless file_name_is_absolute($config{builddir});
my $buildfile = canonpath(catdir(@buildfile));
print <<"_____";
NOTE: These variables only represent the configuration view. The build file
template may have processed these variables further, please have a look at the
build file for more exact data:
$buildfile
_____
}
if ($dump || $buildparams) {
my @buildfile = ($config{builddir}, $config{build_file});
unshift @buildfile, $here
unless file_name_is_absolute($config{builddir});
print "\nbuild file:\n\n";
print " ", canonpath(catfile(@buildfile)),"\n";
print "\nbuild file templates:\n\n";
foreach (@{$config{build_file_templates}}) {
my @tmpl = ($_);
unshift @tmpl, $here
unless file_name_is_absolute($config{sourcedir});
print ' ',canonpath(catfile(@tmpl)),"\n";
}
}
if ($reconf) {
if ($verbose) {
print 'Reconfiguring with: ', join(' ',@{$config{perlargv}}), "\n";
- foreach (sort keys %{$config{perlenv}}) {
- print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n";
- }
+ foreach (sort keys %{$config{perlenv}}) {
+ print ' ',$_,' = ',($config{perlenv}->{$_} || ""),"\n";
+ }
}
chdir $here;
exec $^X,catfile($config{sourcedir}, 'Configure'),'reconf';
}
}
1;
__END__
=head1 NAME
configdata.pm - configuration data for OpenSSL builds
=head1 SYNOPSIS
Interactive:
perl configdata.pm [options]
As data bank module:
use configdata;
=head1 DESCRIPTION
This module can be used in two modes, interactively and as a module containing
all the data recorded by OpenSSL's Configure script.
When used interactively, simply run it as any perl script, with at least one
option, and you will get the information you ask for. See L</OPTIONS> below.
When loaded as a module, you get a few databanks with useful information to
perform build related tasks. The databanks are:
%config Configured things.
%target The OpenSSL config target with all inheritances
resolved.
%disabled The features that are disabled.
@disablables The list of features that can be disabled.
%withargs All data given through --with-THING options.
%unified_info All information that was computed from the build.info
files.
=head1 OPTIONS
=over 4
=item B<--help>
Print a brief help message and exit.
=item B<--man>
Print the manual page and exit.
=item B<--dump> | B<-d>
Print all relevant configuration data. This is equivalent to B<--command-line>
B<--options> B<--target> B<--environment> B<--make-variables>
B<--build-parameters>.
=item B<--command-line> | B<-c>
Print the current configuration command line.
=item B<--options> | B<-o>
Print the features, both enabled and disabled, and display defined macro and
skipped directories where applicable.
=item B<--target> | B<-t>
Print the config attributes for this config target.
=item B<--environment> | B<-e>
Print the environment variables and their values at the time of configuration.
=item B<--make-variables> | B<-m>
Print the main make variables generated in the current configuration
=item B<--build-parameters> | B<-b>
Print the build parameters, i.e. build file and build file templates.
=item B<--reconfigure> | B<--reconf> | B<-r>
Redo the configuration.
=item B<--verbose> | B<-v>
Verbose output.
=back
=cut
EOF
close(OUT);
if ($builder_platform eq 'unix') {
my $mode = (0755 & ~umask);
chmod $mode, 'configdata.pm'
or warn sprintf("WARNING: Couldn't change mode for 'configdata.pm' to 0%03o: %s\n",$mode,$!);
}
my %builders = (
unified => sub {
print 'Creating ',$target{build_file},"\n";
run_dofile(catfile($blddir, $target{build_file}),
@{$config{build_file_templates}});
},
);
$builders{$builder}->($builder_platform, @builder_opts);
$SIG{__DIE__} = $orig_death_handler;
print <<"EOF" if ($disabled{threads} eq "unavailable");
The library could not be configured for supporting multi-threaded
applications as the compiler options required on this system are not known.
See file INSTALL for details if you need multi-threading.
EOF
print <<"EOF" if ($no_shared_warn);
The options 'shared', 'pic' and 'dynamic-engine' aren't supported on this
platform, so we will pretend you gave the option 'no-pic', which also disables
'shared' and 'dynamic-engine'. If you know how to implement shared libraries
or position independent code, please let us know (but please first make sure
you have tried with a current version of OpenSSL).
EOF
print <<"EOF";
**********************************************************************
*** ***
*** OpenSSL has been successfully configured ***
*** ***
*** If you encounter a problem while building, please open an ***
*** issue on GitHub <https://github.com/openssl/openssl/issues> ***
*** and include the output from the following command: ***
*** ***
*** perl configdata.pm --dump ***
*** ***
*** (If you are new to OpenSSL, you might want to consult the ***
*** 'Troubleshooting' section in the INSTALL file first) ***
*** ***
**********************************************************************
EOF
exit(0);
######################################################################
#
# Helpers and utility functions
#
# Death handler, to print a helpful message in case of failure #######
#
sub death_handler {
die @_ if $^S; # To prevent the added message in eval blocks
my $build_file = $target{build_file} // "build file";
my @message = ( <<"_____", @_ );
Failure! $build_file wasn't produced.
Please read INSTALL and associated NOTES files. You may also have to look over
your available compiler tool chain or change your configuration.
_____
# Dying is terminal, so it's ok to reset the signal handler here.
$SIG{__DIE__} = $orig_death_handler;
die @message;
}
# Configuration file reading #########################################
# Note: All of the helper functions are for lazy evaluation. They all
# return a CODE ref, which will return the intended value when evaluated.
# Thus, whenever there's mention of a returned value, it's about that
# intended value.
# Helper function to implement conditional inheritance depending on the
# value of $disabled{asm}. Used in inherit_from values as follows:
#
# inherit_from => [ "template", asm("asm_tmpl") ]
#
sub asm {
my @x = @_;
sub {
- $disabled{asm} ? () : @x;
+ $disabled{asm} ? () : @x;
}
}
# Helper function to implement conditional value variants, with a default
# plus additional values based on the value of $config{build_type}.
# Arguments are given in hash table form:
#
# picker(default => "Basic string: ",
# debug => "debug",
# release => "release")
#
# When configuring with --debug, the resulting string will be
# "Basic string: debug", and when not, it will be "Basic string: release"
#
# This can be used to create variants of sets of flags according to the
# build type:
#
# cflags => picker(default => "-Wall",
# debug => "-g -O0",
# release => "-O3")
#
sub picker {
my %opts = @_;
return sub { add($opts{default} || (),
$opts{$config{build_type}} || ())->(); }
}
# Helper function to combine several values of different types into one.
# This is useful if you want to combine a string with the result of a
# lazy function, such as:
#
# cflags => combine("-Wall", sub { $disabled{zlib} ? () : "-DZLIB" })
#
sub combine {
my @stuff = @_;
return sub { add(@stuff)->(); }
}
# Helper function to implement conditional values depending on the value
# of $disabled{threads}. Can be used as follows:
#
# cflags => combine("-Wall", threads("-pthread"))
#
sub threads {
my @flags = @_;
return sub { add($disabled{threads} ? () : @flags)->(); }
}
sub shared {
my @flags = @_;
return sub { add($disabled{shared} ? () : @flags)->(); }
}
our $add_called = 0;
# Helper function to implement adding values to already existing configuration
# values. It handles elements that are ARRAYs, CODEs and scalars
sub _add {
my $separator = shift;
# If there's any ARRAY in the collection of values OR the separator
# is undef, we will return an ARRAY of combined values, otherwise a
# string of joined values with $separator as the separator.
my $found_array = !defined($separator);
my @values =
- map {
- my $res = $_;
- while (ref($res) eq "CODE") {
- $res = $res->();
- }
- if (defined($res)) {
- if (ref($res) eq "ARRAY") {
- $found_array = 1;
- @$res;
- } else {
- $res;
- }
- } else {
- ();
- }
+ map {
+ my $res = $_;
+ while (ref($res) eq "CODE") {
+ $res = $res->();
+ }
+ if (defined($res)) {
+ if (ref($res) eq "ARRAY") {
+ $found_array = 1;
+ @$res;
+ } else {
+ $res;
+ }
+ } else {
+ ();
+ }
} (@_);
$add_called = 1;
if ($found_array) {
- [ @values ];
+ [ @values ];
} else {
- join($separator, grep { defined($_) && $_ ne "" } @values);
+ join($separator, grep { defined($_) && $_ ne "" } @values);
}
}
sub add_before {
my $separator = " ";
if (ref($_[$#_]) eq "HASH") {
my $opts = pop;
$separator = $opts->{separator};
}
my @x = @_;
sub { _add($separator, @x, @_) };
}
sub add {
my $separator = " ";
if (ref($_[$#_]) eq "HASH") {
my $opts = pop;
$separator = $opts->{separator};
}
my @x = @_;
sub { _add($separator, @_, @x) };
}
sub read_eval_file {
my $fname = shift;
my $content;
my @result;
open F, "< $fname" or die "Can't open '$fname': $!\n";
{
undef local $/;
$content = <F>;
}
close F;
{
local $@;
@result = ( eval $content );
warn $@ if $@;
}
return wantarray ? @result : $result[0];
}
# configuration reader, evaluates the input file as a perl script and expects
# it to fill %targets with target configurations. Those are then added to
# %table.
sub read_config {
my $fname = shift;
my %targets;
{
- # Protect certain tables from tampering
- local %table = ();
+ # Protect certain tables from tampering
+ local %table = ();
- %targets = read_eval_file($fname);
+ %targets = read_eval_file($fname);
}
my %preexisting = ();
foreach (sort keys %targets) {
$preexisting{$_} = 1 if $table{$_};
}
die <<"EOF",
The following config targets from $fname
shadow pre-existing config targets with the same name:
EOF
map { " $_\n" } sort keys %preexisting
if %preexisting;
# For each target, check that it's configured with a hash table.
foreach (keys %targets) {
- if (ref($targets{$_}) ne "HASH") {
- if (ref($targets{$_}) eq "") {
- warn "Deprecated target configuration for $_, ignoring...\n";
- } else {
- warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
- }
- delete $targets{$_};
- } else {
+ if (ref($targets{$_}) ne "HASH") {
+ if (ref($targets{$_}) eq "") {
+ warn "Deprecated target configuration for $_, ignoring...\n";
+ } else {
+ warn "Misconfigured target configuration for $_ (should be a hash table), ignoring...\n";
+ }
+ delete $targets{$_};
+ } else {
$targets{$_}->{_conf_fname_int} = add([ $fname ]);
}
}
%table = (%table, %targets);
}
# configuration resolver. Will only resolve all the lazy evaluation
# codeblocks for the chosen target and all those it inherits from,
# recursively
sub resolve_config {
my $target = shift;
my @breadcrumbs = @_;
# my $extra_checks = defined($ENV{CONFIGURE_EXTRA_CHECKS});
if (grep { $_ eq $target } @breadcrumbs) {
- die "inherit_from loop! target backtrace:\n "
- ,$target,"\n ",join("\n ", @breadcrumbs),"\n";
+ die "inherit_from loop! target backtrace:\n "
+ ,$target,"\n ",join("\n ", @breadcrumbs),"\n";
}
if (!defined($table{$target})) {
- warn "Warning! target $target doesn't exist!\n";
- return ();
+ warn "Warning! target $target doesn't exist!\n";
+ return ();
}
# Recurse through all inheritances. They will be resolved on the
# fly, so when this operation is done, they will all just be a
# bunch of attributes with string values.
# What we get here, though, are keys with references to lists of
# the combined values of them all. We will deal with lists after
# this stage is done.
my %combined_inheritance = ();
if ($table{$target}->{inherit_from}) {
- my @inherit_from =
- map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
- foreach (@inherit_from) {
- my %inherited_config = resolve_config($_, $target, @breadcrumbs);
-
- # 'template' is a marker that's considered private to
- # the config that had it.
- delete $inherited_config{template};
-
- foreach (keys %inherited_config) {
- if (!$combined_inheritance{$_}) {
- $combined_inheritance{$_} = [];
- }
- push @{$combined_inheritance{$_}}, $inherited_config{$_};
- }
- }
+ my @inherit_from =
+ map { ref($_) eq "CODE" ? $_->() : $_ } @{$table{$target}->{inherit_from}};
+ foreach (@inherit_from) {
+ my %inherited_config = resolve_config($_, $target, @breadcrumbs);
+
+ # 'template' is a marker that's considered private to
+ # the config that had it.
+ delete $inherited_config{template};
+
+ foreach (keys %inherited_config) {
+ if (!$combined_inheritance{$_}) {
+ $combined_inheritance{$_} = [];
+ }
+ push @{$combined_inheritance{$_}}, $inherited_config{$_};
+ }
+ }
}
# We won't need inherit_from in this target any more, since we've
# resolved all the inheritances that lead to this
delete $table{$target}->{inherit_from};
# Now is the time to deal with those lists. Here's the place to
# decide what shall be done with those lists, all based on the
# values of the target we're currently dealing with.
# - If a value is a coderef, it will be executed with the list of
# inherited values as arguments.
# - If the corresponding key doesn't have a value at all or is the
# empty string, the inherited value list will be run through the
# default combiner (below), and the result becomes this target's
# value.
# - Otherwise, this target's value is assumed to be a string that
# will simply override the inherited list of values.
my $default_combiner = add();
my %all_keys =
- map { $_ => 1 } (keys %combined_inheritance,
- keys %{$table{$target}});
+ map { $_ => 1 } (keys %combined_inheritance,
+ keys %{$table{$target}});
sub process_values {
- my $object = shift;
- my $inherited = shift; # Always a [ list ]
- my $target = shift;
- my $entry = shift;
+ my $object = shift;
+ my $inherited = shift; # Always a [ list ]
+ my $target = shift;
+ my $entry = shift;
$add_called = 0;
while(ref($object) eq "CODE") {
$object = $object->(@$inherited);
}
if (!defined($object)) {
return ();
}
elsif (ref($object) eq "ARRAY") {
local $add_called; # To make sure recursive calls don't affect it
return [ map { process_values($_, $inherited, $target, $entry) }
@$object ];
} elsif (ref($object) eq "") {
return $object;
} else {
die "cannot handle reference type ",ref($object)
," found in target ",$target," -> ",$entry,"\n";
}
}
foreach (sort keys %all_keys) {
my $previous = $combined_inheritance{$_};
- # Current target doesn't have a value for the current key?
- # Assign it the default combiner, the rest of this loop body
- # will handle it just like any other coderef.
- if (!exists $table{$target}->{$_}) {
- $table{$target}->{$_} = $default_combiner;
- }
+ # Current target doesn't have a value for the current key?
+ # Assign it the default combiner, the rest of this loop body
+ # will handle it just like any other coderef.
+ if (!exists $table{$target}->{$_}) {
+ $table{$target}->{$_} = $default_combiner;
+ }
- $table{$target}->{$_} = process_values($table{$target}->{$_},
- $combined_inheritance{$_},
- $target, $_);
+ $table{$target}->{$_} = process_values($table{$target}->{$_},
+ $combined_inheritance{$_},
+ $target, $_);
unless(defined($table{$target}->{$_})) {
delete $table{$target}->{$_};
}
# if ($extra_checks &&
# $previous && !($add_called || $previous ~~ $table{$target}->{$_})) {
# warn "$_ got replaced in $target\n";
# }
}
# Finally done, return the result.
return %{$table{$target}};
}
sub usage
- {
- print STDERR $usage;
- print STDERR "\npick os/compiler from:\n";
- my $j=0;
- my $i;
+ {
+ print STDERR $usage;
+ print STDERR "\npick os/compiler from:\n";
+ my $j=0;
+ my $i;
my $k=0;
- foreach $i (sort keys %table)
- {
- next if $table{$i}->{template};
- next if $i =~ /^debug/;
- $k += length($i) + 1;
- if ($k > 78)
- {
- print STDERR "\n";
- $k=length($i);
- }
- print STDERR $i . " ";
- }
- foreach $i (sort keys %table)
- {
- next if $table{$i}->{template};
- next if $i !~ /^debug/;
- $k += length($i) + 1;
- if ($k > 78)
- {
- print STDERR "\n";
- $k=length($i);
- }
- print STDERR $i . " ";
- }
- print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
- exit(1);
- }
+ foreach $i (sort keys %table)
+ {
+ next if $table{$i}->{template};
+ next if $i =~ /^debug/;
+ $k += length($i) + 1;
+ if ($k > 78)
+ {
+ print STDERR "\n";
+ $k=length($i);
+ }
+ print STDERR $i . " ";
+ }
+ foreach $i (sort keys %table)
+ {
+ next if $table{$i}->{template};
+ next if $i !~ /^debug/;
+ $k += length($i) + 1;
+ if ($k > 78)
+ {
+ print STDERR "\n";
+ $k=length($i);
+ }
+ print STDERR $i . " ";
+ }
+ print STDERR "\n\nNOTE: If in doubt, on Unix-ish systems use './config'.\n";
+ exit(1);
+ }
sub run_dofile
{
my $out = shift;
my @templates = @_;
unlink $out || warn "Can't remove $out, $!"
if -f $out;
foreach (@templates) {
die "Can't open $_, $!" unless -f $_;
}
my $perlcmd = (quotify("maybeshell", $config{PERL}))[0];
my $cmd = "$perlcmd \"-I.\" \"-Mconfigdata\" \"$dofile\" -o\"Configure\" \"".join("\" \"",@templates)."\" > \"$out.new\"";
#print STDERR "DEBUG[run_dofile]: \$cmd = $cmd\n";
system($cmd);
exit 1 if $? != 0;
rename("$out.new", $out) || die "Can't rename $out.new, $!";
}
sub compiler_predefined {
state %predefined;
my $cc = shift;
return () if $^O eq 'VMS';
die 'compiler_predefined called without a compiler command'
unless $cc;
if (! $predefined{$cc}) {
$predefined{$cc} = {};
# collect compiler pre-defines from gcc or gcc-alike...
open(PIPE, "$cc -dM -E -x c /dev/null 2>&1 |");
while (my $l = <PIPE>) {
$l =~ m/^#define\s+(\w+(?:\(\w+\))?)(?:\s+(.+))?/ or last;
$predefined{$cc}->{$1} = $2 // '';
}
close(PIPE);
}
return %{$predefined{$cc}};
}
sub which
{
my ($name)=@_;
if (eval { require IPC::Cmd; 1; }) {
IPC::Cmd->import();
return scalar IPC::Cmd::can_run($name);
} else {
# if there is $directories component in splitpath,
# then it's not something to test with $PATH...
return $name if (File::Spec->splitpath($name))[1];
foreach (File::Spec->path()) {
my $fullpath = catfile($_, "$name$target{exe_extension}");
if (-f $fullpath and -x $fullpath) {
return $fullpath;
}
}
}
}
sub env
{
my $name = shift;
my %opts = @_;
unless ($opts{cacheonly}) {
# Note that if $ENV{$name} doesn't exist or is undefined,
# $config{perlenv}->{$name} will be created with the value
# undef. This is intentional.
$config{perlenv}->{$name} = $ENV{$name}
if ! exists $config{perlenv}->{$name};
}
return $config{perlenv}->{$name};
}
# Configuration printer ##############################################
sub print_table_entry
{
local $now_printing = shift;
my %target = resolve_config($now_printing);
my $type = shift;
# Don't print the templates
return if $target{template};
my @sequence = (
- "sys_id",
- "cpp",
- "cppflags",
- "defines",
- "includes",
- "cc",
- "cflags",
- "unistd",
- "ld",
- "lflags",
- "loutflag",
- "ex_libs",
- "bn_ops",
- "apps_aux_src",
- "cpuid_asm_src",
- "uplink_aux_src",
- "bn_asm_src",
- "ec_asm_src",
- "des_asm_src",
- "aes_asm_src",
- "bf_asm_src",
- "md5_asm_src",
- "cast_asm_src",
- "sha1_asm_src",
- "rc4_asm_src",
- "rmd160_asm_src",
- "rc5_asm_src",
- "wp_asm_src",
- "cmll_asm_src",
- "modes_asm_src",
- "padlock_asm_src",
- "chacha_asm_src",
- "poly1035_asm_src",
- "thread_scheme",
- "perlasm_scheme",
- "dso_scheme",
- "shared_target",
- "shared_cflag",
- "shared_defines",
- "shared_ldflag",
- "shared_rcflag",
- "shared_extension",
- "dso_extension",
- "obj_extension",
- "exe_extension",
- "ranlib",
- "ar",
- "arflags",
- "aroutflag",
- "rc",
- "rcflags",
- "rcoutflag",
- "mt",
- "mtflags",
- "mtinflag",
- "mtoutflag",
- "multilib",
- "build_scheme",
- );
+ "sys_id",
+ "cpp",
+ "cppflags",
+ "defines",
+ "includes",
+ "cc",
+ "cflags",
+ "unistd",
+ "ld",
+ "lflags",
+ "loutflag",
+ "ex_libs",
+ "bn_ops",
+ "apps_aux_src",
+ "cpuid_asm_src",
+ "uplink_aux_src",
+ "bn_asm_src",
+ "ec_asm_src",
+ "des_asm_src",
+ "aes_asm_src",
+ "bf_asm_src",
+ "md5_asm_src",
+ "cast_asm_src",
+ "sha1_asm_src",
+ "rc4_asm_src",
+ "rmd160_asm_src",
+ "rc5_asm_src",
+ "wp_asm_src",
+ "cmll_asm_src",
+ "modes_asm_src",
+ "padlock_asm_src",
+ "chacha_asm_src",
+ "poly1035_asm_src",
+ "thread_scheme",
+ "perlasm_scheme",
+ "dso_scheme",
+ "shared_target",
+ "shared_cflag",
+ "shared_defines",
+ "shared_ldflag",
+ "shared_rcflag",
+ "shared_extension",
+ "dso_extension",
+ "obj_extension",
+ "exe_extension",
+ "ranlib",
+ "ar",
+ "arflags",
+ "aroutflag",
+ "rc",
+ "rcflags",
+ "rcoutflag",
+ "mt",
+ "mtflags",
+ "mtinflag",
+ "mtoutflag",
+ "multilib",
+ "build_scheme",
+ );
if ($type eq "TABLE") {
- print "\n";
- print "*** $now_printing\n";
+ print "\n";
+ print "*** $now_printing\n";
foreach (@sequence) {
if (ref($target{$_}) eq "ARRAY") {
printf "\$%-12s = %s\n", $_, join(" ", @{$target{$_}});
} else {
printf "\$%-12s = %s\n", $_, $target{$_};
}
}
} elsif ($type eq "HASH") {
- my $largest =
- length((sort { length($a) <=> length($b) } @sequence)[-1]);
- print " '$now_printing' => {\n";
- foreach (@sequence) {
- if ($target{$_}) {
+ my $largest =
+ length((sort { length($a) <=> length($b) } @sequence)[-1]);
+ print " '$now_printing' => {\n";
+ foreach (@sequence) {
+ if ($target{$_}) {
if (ref($target{$_}) eq "ARRAY") {
print " '",$_,"'"," " x ($largest - length($_))," => [ ",join(", ", map { "'$_'" } @{$target{$_}})," ],\n";
} else {
print " '",$_,"'"," " x ($largest - length($_))," => '",$target{$_},"',\n";
}
- }
- }
- print " },\n";
+ }
+ }
+ print " },\n";
}
}
# Utility routines ###################################################
# On VMS, if the given file is a logical name, File::Spec::Functions
# will consider it an absolute path. There are cases when we want a
# purely syntactic check without checking the environment.
sub isabsolute {
my $file = shift;
# On non-platforms, we just use file_name_is_absolute().
return file_name_is_absolute($file) unless $^O eq "VMS";
# If the file spec includes a device or a directory spec,
# file_name_is_absolute() is perfectly safe.
return file_name_is_absolute($file) if $file =~ m|[:\[]|;
# Here, we know the given file spec isn't absolute
return 0;
}
# Makes a directory absolute and cleans out /../ in paths like foo/../bar
# On some platforms, this uses rel2abs(), while on others, realpath() is used.
# realpath() requires that at least all path components except the last is an
# existing directory. On VMS, the last component of the directory spec must
# exist.
sub absolutedir {
my $dir = shift;
# realpath() is quite buggy on VMS. It uses LIB$FID_TO_NAME, which
# will return the volume name for the device, no matter what. Also,
# it will return an incorrect directory spec if the argument is a
# directory that doesn't exist.
if ($^O eq "VMS") {
return rel2abs($dir);
}
# We use realpath() on Unix, since no other will properly clean out
# a directory spec.
use Cwd qw/realpath/;
return realpath($dir);
}
sub quotify {
my %processors = (
- perl => sub { my $x = shift;
- $x =~ s/([\\\$\@"])/\\$1/g;
- return '"'.$x.'"'; },
- maybeshell => sub { my $x = shift;
- (my $y = $x) =~ s/([\\\"])/\\$1/g;
- if ($x ne $y || $x =~ m|\s|) {
- return '"'.$y.'"';
- } else {
- return $x;
- }
- },
- );
+ perl => sub { my $x = shift;
+ $x =~ s/([\\\$\@"])/\\$1/g;
+ return '"'.$x.'"'; },
+ maybeshell => sub { my $x = shift;
+ (my $y = $x) =~ s/([\\\"])/\\$1/g;
+ if ($x ne $y || $x =~ m|\s|) {
+ return '"'.$y.'"';
+ } else {
+ return $x;
+ }
+ },
+ );
my $for = shift;
my $processor =
- defined($processors{$for}) ? $processors{$for} : sub { shift; };
+ defined($processors{$for}) ? $processors{$for} : sub { shift; };
return map { $processor->($_); } @_;
}
# collect_from_file($filename, $line_concat_cond_re, $line_concat)
# $filename is a file name to read from
# $line_concat_cond_re is a regexp detecting a line continuation ending
# $line_concat is a CODEref that takes care of concatenating two lines
sub collect_from_file {
my $filename = shift;
my $line_concat_cond_re = shift;
my $line_concat = shift;
open my $fh, $filename || die "unable to read $filename: $!\n";
return sub {
my $saved_line = "";
$_ = "";
while (<$fh>) {
s|\R$||;
if (defined $line_concat) {
$_ = $line_concat->($saved_line, $_);
$saved_line = "";
}
if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
$saved_line = $_;
next;
}
return $_;
}
die "$filename ending with continuation line\n" if $_;
close $fh;
return undef;
}
}
# collect_from_array($array, $line_concat_cond_re, $line_concat)
# $array is an ARRAYref of lines
# $line_concat_cond_re is a regexp detecting a line continuation ending
# $line_concat is a CODEref that takes care of concatenating two lines
sub collect_from_array {
my $array = shift;
my $line_concat_cond_re = shift;
my $line_concat = shift;
my @array = (@$array);
return sub {
my $saved_line = "";
$_ = "";
while (defined($_ = shift @array)) {
s|\R$||;
if (defined $line_concat) {
$_ = $line_concat->($saved_line, $_);
$saved_line = "";
}
if (defined $line_concat_cond_re && /$line_concat_cond_re/) {
$saved_line = $_;
next;
}
return $_;
}
die "input text ending with continuation line\n" if $_;
return undef;
}
}
# collect_information($lineiterator, $line_continue, $regexp => $CODEref, ...)
# $lineiterator is a CODEref that delivers one line at a time.
# All following arguments are regex/CODEref pairs, where the regexp detects a
# line and the CODEref does something with the result of the regexp.
sub collect_information {
my $lineiterator = shift;
my %collectors = @_;
while(defined($_ = $lineiterator->())) {
s|\R$||;
my $found = 0;
if ($collectors{"BEFORE"}) {
$collectors{"BEFORE"}->($_);
}
foreach my $re (keys %collectors) {
if ($re !~ /^OTHERWISE|BEFORE|AFTER$/ && /$re/) {
$collectors{$re}->($lineiterator);
$found = 1;
};
}
if ($collectors{"OTHERWISE"}) {
$collectors{"OTHERWISE"}->($lineiterator, $_)
unless $found || !defined $collectors{"OTHERWISE"};
}
if ($collectors{"AFTER"}) {
$collectors{"AFTER"}->($_);
}
}
}
# tokenize($line)
# $line is a line of text to split up into tokens
# returns a list of tokens
#
# Tokens are divided by spaces. If the tokens include spaces, they
# have to be quoted with single or double quotes. Double quotes
# inside a double quoted token must be escaped. Escaping is done
# with backslash.
# Basically, the same quoting rules apply for " and ' as in any
# Unix shell.
sub tokenize {
my $line = my $debug_line = shift;
my @result = ();
while ($line =~ s|^\s+||, $line ne "") {
my $token = "";
while ($line ne "" && $line !~ m|^\s|) {
if ($line =~ m/^"((?:[^"\\]+|\\.)*)"/) {
$token .= $1;
$line = $';
} elsif ($line =~ m/^'([^']*)'/) {
$token .= $1;
$line = $';
} elsif ($line =~ m/^(\S+)/) {
$token .= $1;
$line = $';
}
}
push @result, $token;
}
if ($ENV{CONFIGURE_DEBUG_TOKENIZE}) {
- print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
- print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
+ print STDERR "DEBUG[tokenize]: Parsed '$debug_line' into:\n";
+ print STDERR "DEBUG[tokenize]: ('", join("', '", @result), "')\n";
}
return @result;
}
diff --git a/INSTALL b/INSTALL
index 7fe55d428f2f..0b6a3fd1ec39 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,1240 +1,1255 @@
OPENSSL INSTALLATION
--------------------
This document describes installation on all supported operating
systems (the Unix/Linux family (which includes Mac OS/X), OpenVMS,
and Windows).
To install OpenSSL, you will need:
* A make implementation
* Perl 5 with core modules (please read NOTES.PERL)
* The perl module Text::Template (please read NOTES.PERL)
* an ANSI C compiler
* a development environment in the form of development libraries and C
header files
* a supported operating system
For additional platform specific requirements, solutions to specific
issues and other details, please read one of these:
* NOTES.UNIX (any supported Unix like system)
* NOTES.VMS (OpenVMS)
* NOTES.WIN (any supported Windows)
* NOTES.DJGPP (DOS platform with DJGPP)
* NOTES.ANDROID (obviously Android [NDK])
Notational conventions in this document
---------------------------------------
Throughout this document, we use the following conventions in command
examples:
$ command Any line starting with a dollar sign
($) is a command line.
{ word1 | word2 | word3 } This denotes a mandatory choice, to be
replaced with one of the given words.
A simple example would be this:
$ echo { FOO | BAR | COOKIE }
which is to be understood as one of
these:
$ echo FOO
- or -
$ echo BAR
- or -
$ echo COOKIE
[ word1 | word2 | word3 ] Similar to { word1 | word2 | word3 }
except it's optional to give any of
those. In addition to the examples
above, this would also be valid:
$ echo
{{ target }} This denotes a mandatory word or
sequence of words of some sort. A
simple example would be this:
$ type {{ filename }}
which is to be understood to use the
command 'type' on some file name
determined by the user.
[[ options ]] Similar to {{ target }}, but is
optional.
Note that the notation assumes spaces around {, }, [, ], {{, }} and
[[, ]]. This is to differentiate from OpenVMS directory
specifications, which also use [ and ], but without spaces.
Quick Start
-----------
If you want to just get on with it, do:
on Unix (again, this includes Mac OS/X):
$ ./config
$ make
$ make test
$ make install
on OpenVMS:
$ @config
$ mms
$ mms test
$ mms install
on Windows (only pick one of the targets for configuration):
$ perl Configure { VC-WIN32 | VC-WIN64A | VC-WIN64I | VC-CE }
$ nmake
$ nmake test
$ nmake install
If any of these steps fails, see section Installation in Detail below.
This will build and install OpenSSL in the default location, which is:
Unix: normal installation directories under /usr/local
OpenVMS: SYS$COMMON:[OPENSSL-'version'...], where 'version' is the
OpenSSL version number with underscores instead of periods.
Windows: C:\Program Files\OpenSSL or C:\Program Files (x86)\OpenSSL
If you want to install it anywhere else, run config like this:
On Unix:
$ ./config --prefix=/opt/openssl --openssldir=/usr/local/ssl
On OpenVMS:
$ @config --prefix=PROGRAM:[INSTALLS] --openssldir=SYS$MANAGER:[OPENSSL]
(Note: if you do add options to the configuration command, please make sure
you've read more than just this Quick Start, such as relevant NOTES.* files,
the options outline below, as configuration options may change the outcome
in otherwise unexpected ways)
Configuration Options
---------------------
There are several options to ./config (or ./Configure) to customize
the build (note that for Windows, the defaults for --prefix and
--openssldir depend in what configuration is used and what Windows
implementation OpenSSL is built on. More notes on this in NOTES.WIN):
--api=x.y.z
Don't build with support for deprecated APIs below the
specified version number. For example "--api=1.1.0" will
remove support for all APIS that were deprecated in OpenSSL
version 1.1.0 or below.
--cross-compile-prefix=PREFIX
The PREFIX to include in front of commands for your
toolchain. It's likely to have to end with dash, e.g.
a-b-c- would invoke GNU compiler as a-b-c-gcc, etc.
Unfortunately cross-compiling is too case-specific to
put together one-size-fits-all instructions. You might
have to pass more flags or set up environment variables
to actually make it work. Android and iOS cases are
discussed in corresponding Configurations/15-*.conf
files. But there are cases when this option alone is
sufficient. For example to build the mingw64 target on
Linux "--cross-compile-prefix=x86_64-w64-mingw32-"
works. Naturally provided that mingw packages are
installed. Today Debian and Ubuntu users have option to
install a number of prepackaged cross-compilers along
with corresponding run-time and development packages for
"alien" hardware. To give another example
"--cross-compile-prefix=mipsel-linux-gnu-" suffices
in such case. Needless to mention that you have to
invoke ./Configure, not ./config, and pass your target
name explicitly. Also, note that --openssldir refers
to target's file system, not one you are building on.
--debug
Build OpenSSL with debugging symbols and zero optimization
level.
--libdir=DIR
The name of the directory under the top of the installation
directory tree (see the --prefix option) where libraries will
be installed. By default this is "lib". Note that on Windows
only ".lib" files will be stored in this location. dll files
will always be installed to the "bin" directory.
--openssldir=DIR
Directory for OpenSSL configuration files, and also the
default certificate and key store. Defaults are:
Unix: /usr/local/ssl
Windows: C:\Program Files\Common Files\SSL
or C:\Program Files (x86)\Common Files\SSL
OpenVMS: SYS$COMMON:[OPENSSL-COMMON]
--prefix=DIR
The top of the installation directory tree. Defaults are:
Unix: /usr/local
Windows: C:\Program Files\OpenSSL
or C:\Program Files (x86)\OpenSSL
OpenVMS: SYS$COMMON:[OPENSSL-'version']
--release
Build OpenSSL without debugging symbols. This is the default.
--strict-warnings
This is a developer flag that switches on various compiler
options recommended for OpenSSL development. It only works
when using gcc or clang as the compiler. If you are
developing a patch for OpenSSL then it is recommended that
you use this option where possible.
--with-zlib-include=DIR
The directory for the location of the zlib include file. This
option is only necessary if enable-zlib (see below) is used
and the include file is not already on the system include
path.
--with-zlib-lib=LIB
On Unix: this is the directory containing the zlib library.
If not provided the system library path will be used.
On Windows: this is the filename of the zlib library (with or
without a path). This flag must be provided if the
zlib-dynamic option is not also used. If zlib-dynamic is used
then this flag is optional and a default value ("ZLIB1") is
used if not provided.
On VMS: this is the filename of the zlib library (with or
without a path). This flag is optional and if not provided
then "GNV$LIBZSHR", "GNV$LIBZSHR32" or "GNV$LIBZSHR64" is
used by default depending on the pointer size chosen.
--with-rand-seed=seed1[,seed2,...]
A comma separated list of seeding methods which will be tried
by OpenSSL in order to obtain random input (a.k.a "entropy")
for seeding its cryptographically secure random number
generator (CSPRNG). The current seeding methods are:
os: Use a trusted operating system entropy source.
This is the default method if such an entropy
source exists.
getrandom: Use the L<getrandom(2)> or equivalent system
call.
devrandom: Use the the first device from the DEVRANDOM list
which can be opened to read random bytes. The
DEVRANDOM preprocessor constant expands to
"/dev/urandom","/dev/random","/dev/srandom" on
most unix-ish operating systems.
egd: Check for an entropy generating daemon.
rdcpu: Use the RDSEED or RDRAND command if provided by
the CPU.
librandom: Use librandom (not implemented yet).
none: Disable automatic seeding. This is the default
on some operating systems where no suitable
entropy source exists, or no support for it is
implemented yet.
For more information, see the section 'Note on random number
generation' at the end of this document.
no-afalgeng
Don't build the AFALG engine. This option will be forced if
on a platform that does not support AFALG.
enable-asan
Build with the Address sanitiser. This is a developer option
only. It may not work on all platforms and should never be
used in production environments. It will only work when used
with gcc or clang and should be used in conjunction with the
no-shared option.
no-asm
Do not use assembler code. This should be viewed as
debugging/trouble-shooting option rather than production.
On some platforms a small amount of assembler code may
still be used even with this option.
no-async
Do not build support for async operations.
no-autoalginit
Don't automatically load all supported ciphers and digests.
Typically OpenSSL will make available all of its supported
ciphers and digests. For a statically linked application this
may be undesirable if small executable size is an objective.
This only affects libcrypto. Ciphers and digests will have to
be loaded manually using EVP_add_cipher() and
EVP_add_digest() if this option is used. This option will
force a non-shared build.
no-autoerrinit
Don't automatically load all libcrypto/libssl error strings.
Typically OpenSSL will automatically load human readable
error strings. For a statically linked application this may
be undesirable if small executable size is an objective.
no-autoload-config
Don't automatically load the default openssl.cnf file.
Typically OpenSSL will automatically load a system config
file which configures default ssl options.
+ enable-buildtest-c++
+ While testing, generate C++ buildtest files that
+ simply check that the public OpenSSL header files
+ are usable standalone with C++.
+
+ Enabling this option demands extra care. For any
+ compiler flag given directly as configuration
+ option, you must ensure that it's valid for both
+ the C and the C++ compiler. If not, the C++ build
+ test will most likely break. As an alternative,
+ you can use the language specific variables, CFLAGS
+ and CXXFLAGS.
+
no-capieng
Don't build the CAPI engine. This option will be forced if
on a platform that does not support CAPI.
no-cms
Don't build support for CMS features
no-comp
Don't build support for SSL/TLS compression. If this option
is left enabled (the default), then compression will only
work if the zlib or zlib-dynamic options are also chosen.
enable-crypto-mdebug
Build support for debugging memory allocated via
OPENSSL_malloc() or OPENSSL_zalloc().
enable-crypto-mdebug-backtrace
As for crypto-mdebug, but additionally provide backtrace
information for allocated memory.
TO BE USED WITH CARE: this uses GNU C functionality, and
is therefore not usable for non-GNU config targets. If
your build complains about the use of '-rdynamic' or the
lack of header file execinfo.h, this option is not for you.
ALSO NOTE that even though execinfo.h is available on your
system (through Gnulib), the functions might just be stubs
that do nothing.
no-ct
Don't build support for Certificate Transparency.
no-deprecated
Don't build with support for any deprecated APIs. This is the
same as using "--api" and supplying the latest version
number.
no-dgram
Don't build support for datagram based BIOs. Selecting this
option will also force the disabling of DTLS.
enable-devcryptoeng
Build the /dev/crypto engine. It is automatically selected
on BSD implementations, in which case it can be disabled with
no-devcryptoeng.
- no-dso
- Don't build support for loading Dynamic Shared Objects.
-
no-dynamic-engine
Don't build the dynamically loaded engines. This only has an
effect in a "shared" build
no-ec
Don't build support for Elliptic Curves.
no-ec2m
Don't build support for binary Elliptic Curves
enable-ec_nistp_64_gcc_128
Enable support for optimised implementations of some commonly
used NIST elliptic curves.
This is only supported on platforms:
- with little-endian storage of non-byte types
- that tolerate misaligned memory references
- where the compiler:
- supports the non-standard type __uint128_t
- defines the built-in macro __SIZEOF_INT128__
enable-egd
Build support for gathering entropy from EGD (Entropy
Gathering Daemon).
no-engine
Don't build support for loading engines.
no-err
Don't compile in any error strings.
enable-external-tests
Enable building of integration with external test suites.
This is a developer option and may not work on all platforms.
The only supported external test suite at the current time is
the BoringSSL test suite. See the file test/README.external
for further details.
no-filenames
Don't compile in filename and line number information (e.g.
for errors and memory allocation).
enable-fuzz-libfuzzer, enable-fuzz-afl
Build with support for fuzzing using either libfuzzer or AFL.
These are developer options only. They may not work on all
platforms and should never be used in production environments.
See the file fuzz/README.md for further details.
no-gost
Don't build support for GOST based ciphersuites. Note that
if this feature is enabled then GOST ciphersuites are only
available if the GOST algorithms are also available through
loading an externally supplied engine.
no-hw-padlock
Don't build the padlock engine.
no-makedepend
Don't generate dependencies.
no-multiblock
Don't build support for writing multiple records in one
go in libssl (Note: this is a different capability to the
pipelining functionality).
no-nextprotoneg
Don't build support for the NPN TLS extension.
no-ocsp
Don't build support for OCSP.
no-pic
Don't build with support for Position Independent Code.
no-pinshared By default OpenSSL will attempt to stay in memory until the
process exits. This is so that libcrypto and libssl can be
properly cleaned up automatically via an "atexit()" handler.
The handler is registered by libcrypto and cleans up both
libraries. On some platforms the atexit() handler will run on
unload of libcrypto (if it has been dynamically loaded)
rather than at process exit. This option can be used to stop
OpenSSL from attempting to stay in memory until the process
exits. This could lead to crashes if either libcrypto or
libssl have already been unloaded at the point
that the atexit handler is invoked, e.g. on a platform which
calls atexit() on unload of the library, and libssl is
unloaded before libcrypto then a crash is likely to happen.
Applications can suppress running of the atexit() handler at
run time by using the OPENSSL_INIT_NO_ATEXIT option to
OPENSSL_init_crypto(). See the man page for it for further
details.
no-posix-io
Don't use POSIX IO capabilities.
no-psk
Don't build support for Pre-Shared Key based ciphersuites.
no-rdrand
Don't use hardware RDRAND capabilities.
no-rfc3779
Don't build support for RFC3779 ("X.509 Extensions for IP
Addresses and AS Identifiers")
sctp
Build support for SCTP
no-shared
Do not create shared libraries, only static ones. See "Note
on shared libraries" below.
no-sock
Don't build support for socket BIOs
no-srp
Don't build support for SRP or SRP based ciphersuites.
no-srtp
Don't build SRTP support
no-sse2
Exclude SSE2 code paths from 32-bit x86 assembly modules.
Normally SSE2 extension is detected at run-time, but the
decision whether or not the machine code will be executed
is taken solely on CPU capability vector. This means that
if you happen to run OS kernel which does not support SSE2
extension on Intel P4 processor, then your application
might be exposed to "illegal instruction" exception.
There might be a way to enable support in kernel, e.g.
FreeBSD kernel can be compiled with CPU_ENABLE_SSE, and
there is a way to disengage SSE2 code paths upon application
start-up, but if you aim for wider "audience" running
such kernel, consider no-sse2. Both the 386 and
no-asm options imply no-sse2.
enable-ssl-trace
Build with the SSL Trace capabilities (adds the "-trace"
option to s_client and s_server).
no-static-engine
Don't build the statically linked engines. This only
has an impact when not built "shared".
no-stdio
Don't use anything from the C header file "stdio.h" that
makes use of the "FILE" type. Only libcrypto and libssl can
be built in this way. Using this option will suppress
building the command line applications. Additionally since
the OpenSSL tests also use the command line applications the
tests will also be skipped.
no-tests
Don't build test programs or run any test.
no-threads
Don't try to build with support for multi-threaded
applications.
threads
Build with support for multi-threaded applications. Most
platforms will enable this by default. However if on a
platform where this is not the case then this will usually
require additional system-dependent options! See "Note on
multi-threading" below.
no-ts
Don't build Time Stamping Authority support.
enable-ubsan
Build with the Undefined Behaviour sanitiser. This is a
developer option only. It may not work on all platforms and
should never be used in production environments. It will only
work when used with gcc or clang and should be used in
conjunction with the "-DPEDANTIC" option (or the
--strict-warnings option).
no-ui
Don't build with the "UI" capability (i.e. the set of
features enabling text based prompts).
enable-unit-test
Enable additional unit test APIs. This should not typically
be used in production deployments.
enable-weak-ssl-ciphers
Build support for SSL/TLS ciphers that are considered "weak"
(e.g. RC4 based ciphersuites).
zlib
Build with support for zlib compression/decompression.
zlib-dynamic
Like "zlib", but has OpenSSL load the zlib library
dynamically when needed. This is only supported on systems
where loading of shared libraries is supported.
386
In 32-bit x86 builds, when generating assembly modules,
use the 80386 instruction set only (the default x86 code
is more efficient, but requires at least a 486). Note:
This doesn't affect code generated by compiler, you're
likely to complement configuration command line with
suitable compiler-specific option.
no-<prot>
Don't build support for negotiating the specified SSL/TLS
protocol (one of ssl, ssl3, tls, tls1, tls1_1, tls1_2,
tls1_3, dtls, dtls1 or dtls1_2). If "no-tls" is selected then
all of tls1, tls1_1, tls1_2 and tls1_3 are disabled.
Similarly "no-dtls" will disable dtls1 and dtls1_2. The
"no-ssl" option is synonymous with "no-ssl3". Note this only
affects version negotiation. OpenSSL will still provide the
methods for applications to explicitly select the individual
protocol versions.
no-<prot>-method
As for no-<prot> but in addition do not build the methods for
applications to explicitly select individual protocol
versions. Note that there is no "no-tls1_3-method" option
because there is no application method for TLSv1.3. Using
individual protocol methods directly is deprecated.
Applications should use TLS_method() instead.
enable-<alg>
Build with support for the specified algorithm, where <alg>
is one of: md2 or rc5.
no-<alg>
Build without support for the specified algorithm, where
<alg> is one of: aria, bf, blake2, camellia, cast, chacha,
cmac, des, dh, dsa, ecdh, ecdsa, idea, md4, mdc2, ocb,
poly1305, rc2, rc4, rmd160, scrypt, seed, siphash, sm2, sm3,
sm4 or whirlpool. The "ripemd" algorithm is deprecated and
if used is synonymous with rmd160.
-Dxxx, -Ixxx, -Wp, -lxxx, -Lxxx, -Wl, -rpath, -R, -framework, -static
These system specific options will be recognised and
passed through to the compiler to allow you to define
preprocessor symbols, specify additional libraries, library
directories or other compiler options. It might be worth
noting that some compilers generate code specifically for
processor the compiler currently executes on. This is not
necessarily what you might have in mind, since it might be
unsuitable for execution on other, typically older,
processor. Consult your compiler documentation.
Take note of the VAR=value documentation below and how
these flags interact with those variables.
-xxx, +xxx
Additional options that are not otherwise recognised are
passed through as they are to the compiler as well. Again,
consult your compiler documentation.
Take note of the VAR=value documentation below and how
these flags interact with those variables.
VAR=value
Assignment of environment variable for Configure. These
work just like normal environment variable assignments,
but are supported on all platforms and are confined to
the configuration scripts only. These assignments override
the corresponding value in the inherited environment, if
there is one.
The following variables are used as "make variables" and
can be used as an alternative to giving preprocessor,
compiler and linker options directly as configuration.
The following variables are supported:
AR The static library archiver.
ARFLAGS Flags for the static library archiver.
AS The assembler compiler.
ASFLAGS Flags for the assembler compiler.
CC The C compiler.
CFLAGS Flags for the C compiler.
CXX The C++ compiler.
CXXFLAGS Flags for the C++ compiler.
CPP The C/C++ preprocessor.
CPPFLAGS Flags for the C/C++ preprocessor.
CPPDEFINES List of CPP macro definitions, separated
by a platform specific character (':' or
space for Unix, ';' for Windows, ',' for
VMS). This can be used instead of using
-D (or what corresponds to that on your
compiler) in CPPFLAGS.
CPPINCLUDES List of CPP inclusion directories, separated
the same way as for CPPDEFINES. This can
be used instead of -I (or what corresponds
to that on your compiler) in CPPFLAGS.
HASHBANGPERL Perl invocation to be inserted after '#!'
in public perl scripts (only relevant on
Unix).
LD The program linker (not used on Unix, $(CC)
is used there).
LDFLAGS Flags for the shared library, DSO and
program linker.
LDLIBS Extra libraries to use when linking.
Takes the form of a space separated list
of library specifications on Unix and
Windows, and as a comma separated list of
libraries on VMS.
RANLIB The library archive indexer.
RC The Windows resource compiler.
RCFLAGS Flags for the Windows resource compiler.
RM The command to remove files and directories.
These cannot be mixed with compiling / linking flags given
on the command line. In other words, something like this
isn't permitted.
./config -DFOO CPPFLAGS=-DBAR -DCOOKIE
Backward compatibility note:
To be compatible with older configuration scripts, the
environment variables are ignored if compiling / linking
flags are given on the command line, except for these:
AR, CC, CXX, CROSS_COMPILE, HASHBANGPERL, PERL, RANLIB, RC
and WINDRES
For example, the following command will not see -DBAR:
CPPFLAGS=-DBAR ./config -DCOOKIE
However, the following will see both set variables:
CC=gcc CROSS_COMPILE=x86_64-w64-mingw32- \
./config -DCOOKIE
+ If CC is set, it is advisable to also set CXX to ensure
+ both C and C++ compilers are in the same "family". This
+ becomes relevant with 'enable-external-tests' and
+ 'enable-buildtest-c++'.
+
reconf
reconfigure
Reconfigure from earlier data. This fetches the previous
command line options and environment from data saved in
"configdata.pm", and runs the configuration process again,
using these options and environment.
Note: NO other option is permitted together with "reconf".
This means that you also MUST use "./Configure" (or
what corresponds to that on non-Unix platforms) directly
to invoke this option.
Note: The original configuration saves away values for ALL
environment variables that were used, and if they weren't
defined, they are still saved away with information that
they weren't originally defined. This information takes
precedence over environment variables that are defined
when reconfiguring.
Displaying configuration data
-----------------------------
The configuration script itself will say very little, and finishes by
creating "configdata.pm". This perl module can be loaded by other scripts
to find all the configuration data, and it can also be used as a script to
display all sorts of configuration data in a human readable form.
For more information, please do:
$ ./configdata.pm --help # Unix
or
$ perl configdata.pm --help # Windows and VMS
Installation in Detail
----------------------
1a. Configure OpenSSL for your operation system automatically:
NOTE: This is not available on Windows.
$ ./config [[ options ]] # Unix
or
$ @config [[ options ]] ! OpenVMS
For the remainder of this text, the Unix form will be used in all
examples, please use the appropriate form for your platform.
This guesses at your operating system (and compiler, if necessary) and
configures OpenSSL based on this guess. Run ./config -t to see
if it guessed correctly. If you want to use a different compiler, you
are cross-compiling for another platform, or the ./config guess was
wrong for other reasons, go to step 1b. Otherwise go to step 2.
On some systems, you can include debugging information as follows:
$ ./config -d [[ options ]]
1b. Configure OpenSSL for your operating system manually
OpenSSL knows about a range of different operating system, hardware and
compiler combinations. To see the ones it knows about, run
$ ./Configure # Unix
or
$ perl Configure # All other platforms
For the remainder of this text, the Unix form will be used in all
examples, please use the appropriate form for your platform.
Pick a suitable name from the list that matches your system. For most
operating systems there is a choice between using "cc" or "gcc". When
you have identified your system (and if necessary compiler) use this name
as the argument to Configure. For example, a "linux-elf" user would
run:
$ ./Configure linux-elf [[ options ]]
If your system isn't listed, you will have to create a configuration
file named Configurations/{{ something }}.conf and add the correct
configuration for your system. See the available configs as examples
and read Configurations/README and Configurations/README.design for
more information.
The generic configurations "cc" or "gcc" should usually work on 32 bit
Unix-like systems.
Configure creates a build file ("Makefile" on Unix, "makefile" on Windows
and "descrip.mms" on OpenVMS) from a suitable template in Configurations,
and defines various macros in include/openssl/opensslconf.h (generated from
include/openssl/opensslconf.h.in).
1c. Configure OpenSSL for building outside of the source tree.
OpenSSL can be configured to build in a build directory separate from
the directory with the source code. It's done by placing yourself in
some other directory and invoking the configuration commands from
there.
Unix example:
$ mkdir /var/tmp/openssl-build
$ cd /var/tmp/openssl-build
$ /PATH/TO/OPENSSL/SOURCE/config [[ options ]]
or
$ /PATH/TO/OPENSSL/SOURCE/Configure {{ target }} [[ options ]]
OpenVMS example:
$ set default sys$login:
$ create/dir [.tmp.openssl-build]
$ set default [.tmp.openssl-build]
$ @[PATH.TO.OPENSSL.SOURCE]config [[ options ]]
or
$ @[PATH.TO.OPENSSL.SOURCE]Configure {{ target }} [[ options ]]
Windows example:
$ C:
$ mkdir \temp-openssl
$ cd \temp-openssl
$ perl d:\PATH\TO\OPENSSL\SOURCE\Configure {{ target }} [[ options ]]
Paths can be relative just as well as absolute. Configure will
do its best to translate them to relative paths whenever possible.
2. Build OpenSSL by running:
$ make # Unix
$ mms ! (or mmk) OpenVMS
$ nmake # Windows
This will build the OpenSSL libraries (libcrypto.a and libssl.a on
Unix, corresponding on other platforms) and the OpenSSL binary
("openssl"). The libraries will be built in the top-level directory,
and the binary will be in the "apps" subdirectory.
Troubleshooting:
If the build fails, look at the output. There may be reasons
for the failure that aren't problems in OpenSSL itself (like
missing standard headers).
If the build succeeded previously, but fails after a source or
configuration change, it might be helpful to clean the build tree
before attempting another build. Use this command:
$ make clean # Unix
$ mms clean ! (or mmk) OpenVMS
$ nmake clean # Windows
Assembler error messages can sometimes be sidestepped by using the
"no-asm" configuration option.
Compiling parts of OpenSSL with gcc and others with the system
compiler will result in unresolved symbols on some systems.
If you are still having problems you can get help by sending an email
to the openssl-users email list (see
https://www.openssl.org/community/mailinglists.html for details). If
it is a bug with OpenSSL itself, please open an issue on GitHub, at
https://github.com/openssl/openssl/issues. Please review the existing
ones first; maybe the bug was already reported or has already been
fixed.
3. After a successful build, the libraries should be tested. Run:
$ make test # Unix
$ mms test ! OpenVMS
$ nmake test # Windows
NOTE: you MUST run the tests from an unprivileged account (or
disable your privileges temporarily if your platform allows it).
If some tests fail, look at the output. There may be reasons for
the failure that isn't a problem in OpenSSL itself (like a
malfunction with Perl). You may want increased verbosity, that
can be accomplished like this:
$ make VERBOSE=1 test # Unix
$ mms /macro=(VERBOSE=1) test ! OpenVMS
$ nmake VERBOSE=1 test # Windows
If you want to run just one or a few specific tests, you can use
the make variable TESTS to specify them, like this:
$ make TESTS='test_rsa test_dsa' test # Unix
$ mms/macro="TESTS=test_rsa test_dsa" test ! OpenVMS
$ nmake TESTS='test_rsa test_dsa' test # Windows
And of course, you can combine (Unix example shown):
$ make VERBOSE=1 TESTS='test_rsa test_dsa' test
You can find the list of available tests like this:
$ make list-tests # Unix
$ mms list-tests ! OpenVMS
$ nmake list-tests # Windows
Have a look at the manual for the perl module Test::Harness to
see what other HARNESS_* variables there are.
If you find a problem with OpenSSL itself, try removing any
compiler optimization flags from the CFLAGS line in Makefile and
run "make clean; make" or corresponding.
To report a bug please open an issue on GitHub, at
https://github.com/openssl/openssl/issues.
For more details on how the make variables TESTS can be used,
see section TESTS in Detail below.
4. If everything tests ok, install OpenSSL with
$ make install # Unix
$ mms install ! OpenVMS
$ nmake install # Windows
This will install all the software components in this directory
tree under PREFIX (the directory given with --prefix or its
default):
Unix:
bin/ Contains the openssl binary and a few other
utility scripts.
include/openssl
Contains the header files needed if you want
to build your own programs that use libcrypto
or libssl.
lib Contains the OpenSSL library files.
lib/engines Contains the OpenSSL dynamically loadable engines.
share/man/man1 Contains the OpenSSL command line man-pages.
share/man/man3 Contains the OpenSSL library calls man-pages.
share/man/man5 Contains the OpenSSL configuration format man-pages.
share/man/man7 Contains the OpenSSL other misc man-pages.
share/doc/openssl/html/man1
share/doc/openssl/html/man3
share/doc/openssl/html/man5
share/doc/openssl/html/man7
Contains the HTML rendition of the man-pages.
OpenVMS ('arch' is replaced with the architecture name, "Alpha"
or "ia64", 'sover' is replaced with the shared library version
(0101 for 1.1), and 'pz' is replaced with the pointer size
OpenSSL was built with):
[.EXE.'arch'] Contains the openssl binary.
[.EXE] Contains a few utility scripts.
[.include.openssl]
Contains the header files needed if you want
to build your own programs that use libcrypto
or libssl.
[.LIB.'arch'] Contains the OpenSSL library files.
[.ENGINES'sover''pz'.'arch']
Contains the OpenSSL dynamically loadable engines.
[.SYS$STARTUP] Contains startup, login and shutdown scripts.
These define appropriate logical names and
command symbols.
[.SYSTEST] Contains the installation verification procedure.
[.HTML] Contains the HTML rendition of the manual pages.
Additionally, install will add the following directories under
OPENSSLDIR (the directory given with --openssldir or its default)
for you convenience:
certs Initially empty, this is the default location
for certificate files.
private Initially empty, this is the default location
for private key files.
misc Various scripts.
Package builders who want to configure the library for standard
locations, but have the package installed somewhere else so that
it can easily be packaged, can use
$ make DESTDIR=/tmp/package-root install # Unix
$ mms/macro="DESTDIR=TMP:[PACKAGE-ROOT]" install ! OpenVMS
The specified destination directory will be prepended to all
installation target paths.
Compatibility issues with previous OpenSSL versions:
* COMPILING existing applications
Starting with version 1.1.0, OpenSSL hides a number of structures
that were previously open. This includes all internal libssl
structures and a number of EVP types. Accessor functions have
been added to allow controlled access to the structures' data.
This means that some software needs to be rewritten to adapt to
the new ways of doing things. This often amounts to allocating
an instance of a structure explicitly where you could previously
allocate them on the stack as automatic variables, and using the
provided accessor functions where you would previously access a
structure's field directly.
Some APIs have changed as well. However, older APIs have been
preserved when possible.
Environment Variables
---------------------
A number of environment variables can be used to provide additional control
over the build process. Typically these should be defined prior to running
config or Configure. Not all environment variables are relevant to all
platforms.
AR
The name of the ar executable to use.
BUILDFILE
Use a different build file name than the platform default
("Makefile" on Unix-like platforms, "makefile" on native Windows,
"descrip.mms" on OpenVMS). This requires that there is a
corresponding build file template. See Configurations/README
for further information.
CC
The compiler to use. Configure will attempt to pick a default
compiler for your platform but this choice can be overridden
using this variable. Set it to the compiler executable you wish
to use, e.g. "gcc" or "clang".
CROSS_COMPILE
This environment variable has the same meaning as for the
"--cross-compile-prefix" Configure flag described above. If both
are set then the Configure flag takes precedence.
NM
The name of the nm executable to use.
OPENSSL_LOCAL_CONFIG_DIR
OpenSSL comes with a database of information about how it
should be built on different platforms as well as build file
templates for those platforms. The database is comprised of
".conf" files in the Configurations directory. The build
file templates reside there as well as ".tmpl" files. See the
file Configurations/README for further information about the
format of ".conf" files as well as information on the ".tmpl"
files.
In addition to the standard ".conf" and ".tmpl" files, it is
possible to create your own ".conf" and ".tmpl" files and store
them locally, outside the OpenSSL source tree. This environment
variable can be set to the directory where these files are held
and will be considered by Configure before it looks in the
standard directories.
PERL
The name of the Perl executable to use when building OpenSSL.
This variable is used in config script only. Configure on the
other hand imposes the interpreter by which it itself was
executed on the whole build procedure.
HASHBANGPERL
The command string for the Perl executable to insert in the
#! line of perl scripts that will be publically installed.
Default: /usr/bin/env perl
Note: the value of this variable is added to the same scripts
on all platforms, but it's only relevant on Unix-like platforms.
RC
The name of the rc executable to use. The default will be as
defined for the target platform in the ".conf" file. If not
defined then "windres" will be used. The WINDRES environment
variable is synonymous to this. If both are defined then RC
takes precedence.
RANLIB
The name of the ranlib executable to use.
WINDRES
See RC.
Makefile targets
----------------
The Configure script generates a Makefile in a format relevant to the specific
platform. The Makefiles provide a number of targets that can be used. Not all
targets may be available on all platforms. Only the most common targets are
described here. Examine the Makefiles themselves for the full list.
all
The default target to build all the software components.
clean
Remove all build artefacts and return the directory to a "clean"
state.
depend
Rebuild the dependencies in the Makefiles. This is a legacy
option that no longer needs to be used since OpenSSL 1.1.0.
install
Install all OpenSSL components.
install_sw
Only install the OpenSSL software components.
install_docs
Only install the OpenSSL documentation components.
install_man_docs
Only install the OpenSSL man pages (Unix only).
install_html_docs
Only install the OpenSSL html documentation.
list-tests
Prints a list of all the self test names.
test
Build and run the OpenSSL self tests.
uninstall
Uninstall all OpenSSL components.
reconfigure
reconf
Re-run the configuration process, as exactly as the last time
as possible.
update
This is a developer option. If you are developing a patch for
OpenSSL you may need to use this if you want to update
automatically generated files; add new error codes or add new
(or change the visibility of) public API functions. (Unix only).
TESTS in Detail
---------------
The make variable TESTS supports a versatile set of space separated tokens
with which you can specify a set of tests to be performed. With a "current
set of tests" in mind, initially being empty, here are the possible tokens:
alltests The current set of tests becomes the whole set of available
tests (as listed when you do 'make list-tests' or similar).
xxx Adds the test 'xxx' to the current set of tests.
-xxx Removes 'xxx' from the current set of tests. If this is the
first token in the list, the current set of tests is first
assigned the whole set of available tests, effectively making
this token equivalent to TESTS="alltests -xxx".
nn Adds the test group 'nn' (which is a number) to the current
set of tests.
-nn Removes the test group 'nn' from the current set of tests.
If this is the first token in the list, the current set of
tests is first assigned the whole set of available tests,
effectively making this token equivalent to
TESTS="alltests -xxx".
Also, all tokens except for "alltests" may have wildcards, such as *.
(on Unix and Windows, BSD style wildcards are supported, while on VMS,
it's VMS style wildcards)
Example: All tests except for the fuzz tests:
$ make TESTS=-test_fuzz test
or (if you want to be explicit)
$ make TESTS='alltests -test_fuzz' test
Example: All tests that have a name starting with "test_ssl" but not those
starting with "test_ssl_":
$ make TESTS='test_ssl* -test_ssl_*' test
Example: Only test group 10:
$ make TESTS='10'
Example: All tests except the slow group (group 99):
$ make TESTS='-99'
Example: All tests in test groups 80 to 99 except for tests in group 90:
$ make TESTS='[89]? -90'
Note on multi-threading
-----------------------
For some systems, the OpenSSL Configure script knows what compiler options
are needed to generate a library that is suitable for multi-threaded
applications. On these systems, support for multi-threading is enabled
by default; use the "no-threads" option to disable (this should never be
necessary).
On other systems, to enable support for multi-threading, you will have
to specify at least two options: "threads", and a system-dependent option.
(The latter is "-D_REENTRANT" on various systems.) The default in this
case, obviously, is not to include support for multi-threading (but
you can still use "no-threads" to suppress an annoying warning message
from the Configure script.)
OpenSSL provides built-in support for two threading models: pthreads (found on
most UNIX/Linux systems), and Windows threads. No other threading models are
supported. If your platform does not provide pthreads or Windows threads then
you should Configure with the "no-threads" option.
Notes on shared libraries
-------------------------
For most systems the OpenSSL Configure script knows what is needed to
build shared libraries for libcrypto and libssl. On these systems
the shared libraries will be created by default. This can be suppressed and
only static libraries created by using the "no-shared" option. On systems
where OpenSSL does not know how to build shared libraries the "no-shared"
option will be forced and only static libraries will be created.
Shared libraries are named a little differently on different platforms.
One way or another, they all have the major OpenSSL version number as
part of the file name, i.e. for OpenSSL 1.1.x, 1.1 is somehow part of
the name.
On most POSIX platforms, shared libraries are named libcrypto.so.1.1
and libssl.so.1.1.
on Cygwin, shared libraries are named cygcrypto-1.1.dll and cygssl-1.1.dll
with import libraries libcrypto.dll.a and libssl.dll.a.
On Windows build with MSVC or using MingW, shared libraries are named
libcrypto-1_1.dll and libssl-1_1.dll for 32-bit Windows, libcrypto-1_1-x64.dll
and libssl-1_1-x64.dll for 64-bit x86_64 Windows, and libcrypto-1_1-ia64.dll
and libssl-1_1-ia64.dll for IA64 Windows. With MSVC, the import libraries
are named libcrypto.lib and libssl.lib, while with MingW, they are named
libcrypto.dll.a and libssl.dll.a.
On VMS, shareable images (VMS speak for shared libraries) are named
ossl$libcrypto0101_shr.exe and ossl$libssl0101_shr.exe. However, when
OpenSSL is specifically built for 32-bit pointers, the shareable images
are named ossl$libcrypto0101_shr32.exe and ossl$libssl0101_shr32.exe
instead, and when built for 64-bit pointers, they are named
ossl$libcrypto0101_shr64.exe and ossl$libssl0101_shr64.exe.
Note on random number generation
--------------------------------
Availability of cryptographically secure random numbers is required for
secret key generation. OpenSSL provides several options to seed the
internal CSPRNG. If not properly seeded, the internal CSPRNG will refuse
to deliver random bytes and a "PRNG not seeded error" will occur.
The seeding method can be configured using the --with-rand-seed option,
which can be used to specify a comma separated list of seed methods.
However in most cases OpenSSL will choose a suitable default method,
so it is not necessary to explicitly provide this option. Note also
that not all methods are available on all platforms.
I) On operating systems which provide a suitable randomness source (in
form of a system call or system device), OpenSSL will use the optimal
available method to seed the CSPRNG from the operating system's
randomness sources. This corresponds to the option --with-rand-seed=os.
II) On systems without such a suitable randomness source, automatic seeding
and reseeding is disabled (--with-rand-seed=none) and it may be necessary
to install additional support software to obtain a random seed and reseed
the CSPRNG manually. Please check out the manual pages for RAND_add(),
RAND_bytes(), RAND_egd(), and the FAQ for more information.
diff --git a/NEWS b/NEWS
index aa104ddc053e..0e38f69dbbaa 100644
--- a/NEWS
+++ b/NEWS
@@ -1,932 +1,936 @@
NEWS
====
This file gives a brief overview of the major changes between each OpenSSL
release. For more details please read the CHANGES file.
+ Major changes between OpenSSL 1.1.1b and OpenSSL 1.1.1c [28 May 2019]
+
+ o Prevent over long nonces in ChaCha20-Poly1305 (CVE-2019-1543)
+
Major changes between OpenSSL 1.1.1a and OpenSSL 1.1.1b [26 Feb 2019]
o Change the info callback signals for the start and end of a post-handshake
message exchange in TLSv1.3.
o Fix a bug in DTLS over SCTP. This breaks interoperability with older versions
of OpenSSL like OpenSSL 1.1.0 and OpenSSL 1.0.2.
Major changes between OpenSSL 1.1.1 and OpenSSL 1.1.1a [20 Nov 2018]
o Timing vulnerability in DSA signature generation (CVE-2018-0734)
o Timing vulnerability in ECDSA signature generation (CVE-2018-0735)
Major changes between OpenSSL 1.1.0i and OpenSSL 1.1.1 [11 Sep 2018]
o Support for TLSv1.3 added (see https://wiki.openssl.org/index.php/TLS1.3
for further important information). The TLSv1.3 implementation includes:
o Fully compliant implementation of RFC8446 (TLSv1.3) on by default
o Early data (0-RTT)
o Post-handshake authentication and key update
o Middlebox Compatibility Mode
o TLSv1.3 PSKs
o Support for all five RFC8446 ciphersuites
o RSA-PSS signature algorithms (backported to TLSv1.2)
o Configurable session ticket support
o Stateless server support
o Rewrite of the packet construction code for "safer" packet handling
o Rewrite of the extension handling code
o Complete rewrite of the OpenSSL random number generator to introduce the
following capabilities
o The default RAND method now utilizes an AES-CTR DRBG according to
NIST standard SP 800-90Ar1.
o Support for multiple DRBG instances with seed chaining.
o There is a public and private DRBG instance.
o The DRBG instances are fork-safe.
o Keep all global DRBG instances on the secure heap if it is enabled.
o The public and private DRBG instance are per thread for lock free
operation
o Support for various new cryptographic algorithms including:
o SHA3
o SHA512/224 and SHA512/256
o EdDSA (both Ed25519 and Ed448) including X509 and TLS support
o X448 (adding to the existing X25519 support in 1.1.0)
o Multi-prime RSA
o SM2
o SM3
o SM4
o SipHash
o ARIA (including TLS support)
o Significant Side-Channel attack security improvements
o Add a new ClientHello callback to provide the ability to adjust the SSL
object at an early stage.
o Add 'Maximum Fragment Length' TLS extension negotiation and support
o A new STORE module, which implements a uniform and URI based reader of
stores that can contain keys, certificates, CRLs and numerous other
objects.
o Move the display of configuration data to configdata.pm.
o Allow GNU style "make variables" to be used with Configure.
o Claim the namespaces OSSL and OPENSSL, represented as symbol prefixes
o Rewrite of devcrypto engine
Major changes between OpenSSL 1.1.0h and OpenSSL 1.1.0i [under development]
o Client DoS due to large DH parameter (CVE-2018-0732)
o Cache timing vulnerability in RSA Key Generation (CVE-2018-0737)
Major changes between OpenSSL 1.1.0g and OpenSSL 1.1.0h [under development]
o Constructed ASN.1 types with a recursive definition could exceed the
stack (CVE-2018-0739)
o Incorrect CRYPTO_memcmp on HP-UX PA-RISC (CVE-2018-0733)
o rsaz_1024_mul_avx2 overflow bug on x86_64 (CVE-2017-3738)
Major changes between OpenSSL 1.1.0f and OpenSSL 1.1.0g [2 Nov 2017]
o bn_sqrx8x_internal carry bug on x86_64 (CVE-2017-3736)
o Malformed X.509 IPAddressFamily could cause OOB read (CVE-2017-3735)
Major changes between OpenSSL 1.1.0e and OpenSSL 1.1.0f [25 May 2017]
o config now recognises 64-bit mingw and chooses mingw64 instead of mingw
Major changes between OpenSSL 1.1.0d and OpenSSL 1.1.0e [16 Feb 2017]
o Encrypt-Then-Mac renegotiation crash (CVE-2017-3733)
Major changes between OpenSSL 1.1.0c and OpenSSL 1.1.0d [26 Jan 2017]
o Truncated packet could crash via OOB read (CVE-2017-3731)
o Bad (EC)DHE parameters cause a client crash (CVE-2017-3730)
o BN_mod_exp may produce incorrect results on x86_64 (CVE-2017-3732)
Major changes between OpenSSL 1.1.0b and OpenSSL 1.1.0c [10 Nov 2016]
o ChaCha20/Poly1305 heap-buffer-overflow (CVE-2016-7054)
o CMS Null dereference (CVE-2016-7053)
o Montgomery multiplication may produce incorrect results (CVE-2016-7055)
Major changes between OpenSSL 1.1.0a and OpenSSL 1.1.0b [26 Sep 2016]
o Fix Use After Free for large message sizes (CVE-2016-6309)
Major changes between OpenSSL 1.1.0 and OpenSSL 1.1.0a [22 Sep 2016]
o OCSP Status Request extension unbounded memory growth (CVE-2016-6304)
o SSL_peek() hang on empty record (CVE-2016-6305)
o Excessive allocation of memory in tls_get_message_header()
(CVE-2016-6307)
o Excessive allocation of memory in dtls1_preprocess_fragment()
(CVE-2016-6308)
Major changes between OpenSSL 1.0.2h and OpenSSL 1.1.0 [25 Aug 2016]
o Copyright text was shrunk to a boilerplate that points to the license
o "shared" builds are now the default when possible
o Added support for "pipelining"
o Added the AFALG engine
o New threading API implemented
o Support for ChaCha20 and Poly1305 added to libcrypto and libssl
o Support for extended master secret
o CCM ciphersuites
o Reworked test suite, now based on perl, Test::Harness and Test::More
o *Most* libcrypto and libssl public structures were made opaque,
including:
BIGNUM and associated types, EC_KEY and EC_KEY_METHOD,
DH and DH_METHOD, DSA and DSA_METHOD, RSA and RSA_METHOD,
BIO and BIO_METHOD, EVP_MD_CTX, EVP_MD, EVP_CIPHER_CTX,
EVP_CIPHER, EVP_PKEY and associated types, HMAC_CTX,
X509, X509_CRL, X509_OBJECT, X509_STORE_CTX, X509_STORE,
X509_LOOKUP, X509_LOOKUP_METHOD
o libssl internal structures made opaque
o SSLv2 support removed
o Kerberos ciphersuite support removed
o RC4 removed from DEFAULT ciphersuites in libssl
o 40 and 56 bit cipher support removed from libssl
o All public header files moved to include/openssl, no more symlinking
o SSL/TLS state machine, version negotiation and record layer rewritten
o EC revision: now operations use new EC_KEY_METHOD.
o Support for OCB mode added to libcrypto
o Support for asynchronous crypto operations added to libcrypto and libssl
o Deprecated interfaces can now be disabled at build time either
relative to the latest release via the "no-deprecated" Configure
argument, or via the "--api=1.1.0|1.0.0|0.9.8" option.
o Application software can be compiled with -DOPENSSL_API_COMPAT=version
to ensure that features deprecated in that version are not exposed.
o Support for RFC6698/RFC7671 DANE TLSA peer authentication
o Change of Configure to use --prefix as the main installation
directory location rather than --openssldir. The latter becomes
the directory for certs, private key and openssl.cnf exclusively.
o Reworked BIO networking library, with full support for IPv6.
o New "unified" build system
o New security levels
o Support for scrypt algorithm
o Support for X25519
o Extended SSL_CONF support using configuration files
o KDF algorithm support. Implement TLS PRF as a KDF.
o Support for Certificate Transparency
o HKDF support.
Major changes between OpenSSL 1.0.2g and OpenSSL 1.0.2h [3 May 2016]
o Prevent padding oracle in AES-NI CBC MAC check (CVE-2016-2107)
o Fix EVP_EncodeUpdate overflow (CVE-2016-2105)
o Fix EVP_EncryptUpdate overflow (CVE-2016-2106)
o Prevent ASN.1 BIO excessive memory allocation (CVE-2016-2109)
o EBCDIC overread (CVE-2016-2176)
o Modify behavior of ALPN to invoke callback after SNI/servername
callback, such that updates to the SSL_CTX affect ALPN.
o Remove LOW from the DEFAULT cipher list. This removes singles DES from
the default.
o Only remove the SSLv2 methods with the no-ssl2-method option.
Major changes between OpenSSL 1.0.2f and OpenSSL 1.0.2g [1 Mar 2016]
o Disable weak ciphers in SSLv3 and up in default builds of OpenSSL.
o Disable SSLv2 default build, default negotiation and weak ciphers
(CVE-2016-0800)
o Fix a double-free in DSA code (CVE-2016-0705)
o Disable SRP fake user seed to address a server memory leak
(CVE-2016-0798)
o Fix BN_hex2bn/BN_dec2bn NULL pointer deref/heap corruption
(CVE-2016-0797)
o Fix memory issues in BIO_*printf functions (CVE-2016-0799)
o Fix side channel attack on modular exponentiation (CVE-2016-0702)
Major changes between OpenSSL 1.0.2e and OpenSSL 1.0.2f [28 Jan 2016]
o DH small subgroups (CVE-2016-0701)
o SSLv2 doesn't block disabled ciphers (CVE-2015-3197)
Major changes between OpenSSL 1.0.2d and OpenSSL 1.0.2e [3 Dec 2015]
o BN_mod_exp may produce incorrect results on x86_64 (CVE-2015-3193)
o Certificate verify crash with missing PSS parameter (CVE-2015-3194)
o X509_ATTRIBUTE memory leak (CVE-2015-3195)
o Rewrite EVP_DecodeUpdate (base64 decoding) to fix several bugs
o In DSA_generate_parameters_ex, if the provided seed is too short,
return an error
Major changes between OpenSSL 1.0.2c and OpenSSL 1.0.2d [9 Jul 2015]
o Alternate chains certificate forgery (CVE-2015-1793)
o Race condition handling PSK identify hint (CVE-2015-3196)
Major changes between OpenSSL 1.0.2b and OpenSSL 1.0.2c [12 Jun 2015]
o Fix HMAC ABI incompatibility
Major changes between OpenSSL 1.0.2a and OpenSSL 1.0.2b [11 Jun 2015]
o Malformed ECParameters causes infinite loop (CVE-2015-1788)
o Exploitable out-of-bounds read in X509_cmp_time (CVE-2015-1789)
o PKCS7 crash with missing EnvelopedContent (CVE-2015-1790)
o CMS verify infinite loop with unknown hash function (CVE-2015-1792)
o Race condition handling NewSessionTicket (CVE-2015-1791)
Major changes between OpenSSL 1.0.2 and OpenSSL 1.0.2a [19 Mar 2015]
o OpenSSL 1.0.2 ClientHello sigalgs DoS fix (CVE-2015-0291)
o Multiblock corrupted pointer fix (CVE-2015-0290)
o Segmentation fault in DTLSv1_listen fix (CVE-2015-0207)
o Segmentation fault in ASN1_TYPE_cmp fix (CVE-2015-0286)
o Segmentation fault for invalid PSS parameters fix (CVE-2015-0208)
o ASN.1 structure reuse memory corruption fix (CVE-2015-0287)
o PKCS7 NULL pointer dereferences fix (CVE-2015-0289)
o DoS via reachable assert in SSLv2 servers fix (CVE-2015-0293)
o Empty CKE with client auth and DHE fix (CVE-2015-1787)
o Handshake with unseeded PRNG fix (CVE-2015-0285)
o Use After Free following d2i_ECPrivatekey error fix (CVE-2015-0209)
o X509_to_X509_REQ NULL pointer deref fix (CVE-2015-0288)
o Removed the export ciphers from the DEFAULT ciphers
Major changes between OpenSSL 1.0.1l and OpenSSL 1.0.2 [22 Jan 2015]:
o Suite B support for TLS 1.2 and DTLS 1.2
o Support for DTLS 1.2
o TLS automatic EC curve selection.
o API to set TLS supported signature algorithms and curves
o SSL_CONF configuration API.
o TLS Brainpool support.
o ALPN support.
o CMS support for RSA-PSS, RSA-OAEP, ECDH and X9.42 DH.
Major changes between OpenSSL 1.0.1k and OpenSSL 1.0.1l [15 Jan 2015]
o Build fixes for the Windows and OpenVMS platforms
Major changes between OpenSSL 1.0.1j and OpenSSL 1.0.1k [8 Jan 2015]
o Fix for CVE-2014-3571
o Fix for CVE-2015-0206
o Fix for CVE-2014-3569
o Fix for CVE-2014-3572
o Fix for CVE-2015-0204
o Fix for CVE-2015-0205
o Fix for CVE-2014-8275
o Fix for CVE-2014-3570
Major changes between OpenSSL 1.0.1i and OpenSSL 1.0.1j [15 Oct 2014]
o Fix for CVE-2014-3513
o Fix for CVE-2014-3567
o Mitigation for CVE-2014-3566 (SSL protocol vulnerability)
o Fix for CVE-2014-3568
Major changes between OpenSSL 1.0.1h and OpenSSL 1.0.1i [6 Aug 2014]
o Fix for CVE-2014-3512
o Fix for CVE-2014-3511
o Fix for CVE-2014-3510
o Fix for CVE-2014-3507
o Fix for CVE-2014-3506
o Fix for CVE-2014-3505
o Fix for CVE-2014-3509
o Fix for CVE-2014-5139
o Fix for CVE-2014-3508
Major changes between OpenSSL 1.0.1g and OpenSSL 1.0.1h [5 Jun 2014]
o Fix for CVE-2014-0224
o Fix for CVE-2014-0221
o Fix for CVE-2014-0198
o Fix for CVE-2014-0195
o Fix for CVE-2014-3470
o Fix for CVE-2010-5298
Major changes between OpenSSL 1.0.1f and OpenSSL 1.0.1g [7 Apr 2014]
o Fix for CVE-2014-0160
o Add TLS padding extension workaround for broken servers.
o Fix for CVE-2014-0076
Major changes between OpenSSL 1.0.1e and OpenSSL 1.0.1f [6 Jan 2014]
o Don't include gmt_unix_time in TLS server and client random values
o Fix for TLS record tampering bug CVE-2013-4353
o Fix for TLS version checking bug CVE-2013-6449
o Fix for DTLS retransmission bug CVE-2013-6450
Major changes between OpenSSL 1.0.1d and OpenSSL 1.0.1e [11 Feb 2013]:
o Corrected fix for CVE-2013-0169
Major changes between OpenSSL 1.0.1c and OpenSSL 1.0.1d [4 Feb 2013]:
o Fix renegotiation in TLS 1.1, 1.2 by using the correct TLS version.
o Include the fips configuration module.
o Fix OCSP bad key DoS attack CVE-2013-0166
o Fix for SSL/TLS/DTLS CBC plaintext recovery attack CVE-2013-0169
o Fix for TLS AESNI record handling flaw CVE-2012-2686
Major changes between OpenSSL 1.0.1b and OpenSSL 1.0.1c [10 May 2012]:
o Fix TLS/DTLS record length checking bug CVE-2012-2333
o Don't attempt to use non-FIPS composite ciphers in FIPS mode.
Major changes between OpenSSL 1.0.1a and OpenSSL 1.0.1b [26 Apr 2012]:
o Fix compilation error on non-x86 platforms.
o Make FIPS capable OpenSSL ciphers work in non-FIPS mode.
o Fix SSL_OP_NO_TLSv1_1 clash with SSL_OP_ALL in OpenSSL 1.0.0
Major changes between OpenSSL 1.0.1 and OpenSSL 1.0.1a [19 Apr 2012]:
o Fix for ASN1 overflow bug CVE-2012-2110
o Workarounds for some servers that hang on long client hellos.
o Fix SEGV in AES code.
Major changes between OpenSSL 1.0.0h and OpenSSL 1.0.1 [14 Mar 2012]:
o TLS/DTLS heartbeat support.
o SCTP support.
o RFC 5705 TLS key material exporter.
o RFC 5764 DTLS-SRTP negotiation.
o Next Protocol Negotiation.
o PSS signatures in certificates, requests and CRLs.
o Support for password based recipient info for CMS.
o Support TLS v1.2 and TLS v1.1.
o Preliminary FIPS capability for unvalidated 2.0 FIPS module.
o SRP support.
Major changes between OpenSSL 1.0.0g and OpenSSL 1.0.0h [12 Mar 2012]:
o Fix for CMS/PKCS#7 MMA CVE-2012-0884
o Corrected fix for CVE-2011-4619
o Various DTLS fixes.
Major changes between OpenSSL 1.0.0f and OpenSSL 1.0.0g [18 Jan 2012]:
o Fix for DTLS DoS issue CVE-2012-0050
Major changes between OpenSSL 1.0.0e and OpenSSL 1.0.0f [4 Jan 2012]:
o Fix for DTLS plaintext recovery attack CVE-2011-4108
o Clear block padding bytes of SSL 3.0 records CVE-2011-4576
o Only allow one SGC handshake restart for SSL/TLS CVE-2011-4619
o Check parameters are not NULL in GOST ENGINE CVE-2012-0027
o Check for malformed RFC3779 data CVE-2011-4577
Major changes between OpenSSL 1.0.0d and OpenSSL 1.0.0e [6 Sep 2011]:
o Fix for CRL vulnerability issue CVE-2011-3207
o Fix for ECDH crashes CVE-2011-3210
o Protection against EC timing attacks.
o Support ECDH ciphersuites for certificates using SHA2 algorithms.
o Various DTLS fixes.
Major changes between OpenSSL 1.0.0c and OpenSSL 1.0.0d [8 Feb 2011]:
o Fix for security issue CVE-2011-0014
Major changes between OpenSSL 1.0.0b and OpenSSL 1.0.0c [2 Dec 2010]:
o Fix for security issue CVE-2010-4180
o Fix for CVE-2010-4252
o Fix mishandling of absent EC point format extension.
o Fix various platform compilation issues.
o Corrected fix for security issue CVE-2010-3864.
Major changes between OpenSSL 1.0.0a and OpenSSL 1.0.0b [16 Nov 2010]:
o Fix for security issue CVE-2010-3864.
o Fix for CVE-2010-2939
o Fix WIN32 build system for GOST ENGINE.
Major changes between OpenSSL 1.0.0 and OpenSSL 1.0.0a [1 Jun 2010]:
o Fix for security issue CVE-2010-1633.
o GOST MAC and CFB fixes.
Major changes between OpenSSL 0.9.8n and OpenSSL 1.0.0 [29 Mar 2010]:
o RFC3280 path validation: sufficient to process PKITS tests.
o Integrated support for PVK files and keyblobs.
o Change default private key format to PKCS#8.
o CMS support: able to process all examples in RFC4134
o Streaming ASN1 encode support for PKCS#7 and CMS.
o Multiple signer and signer add support for PKCS#7 and CMS.
o ASN1 printing support.
o Whirlpool hash algorithm added.
o RFC3161 time stamp support.
o New generalised public key API supporting ENGINE based algorithms.
o New generalised public key API utilities.
o New ENGINE supporting GOST algorithms.
o SSL/TLS GOST ciphersuite support.
o PKCS#7 and CMS GOST support.
o RFC4279 PSK ciphersuite support.
o Supported points format extension for ECC ciphersuites.
o ecdsa-with-SHA224/256/384/512 signature types.
o dsa-with-SHA224 and dsa-with-SHA256 signature types.
o Opaque PRF Input TLS extension support.
o Updated time routines to avoid OS limitations.
Major changes between OpenSSL 0.9.8m and OpenSSL 0.9.8n [24 Mar 2010]:
o CFB cipher definition fixes.
o Fix security issues CVE-2010-0740 and CVE-2010-0433.
Major changes between OpenSSL 0.9.8l and OpenSSL 0.9.8m [25 Feb 2010]:
o Cipher definition fixes.
o Workaround for slow RAND_poll() on some WIN32 versions.
o Remove MD2 from algorithm tables.
o SPKAC handling fixes.
o Support for RFC5746 TLS renegotiation extension.
o Compression memory leak fixed.
o Compression session resumption fixed.
o Ticket and SNI coexistence fixes.
o Many fixes to DTLS handling.
Major changes between OpenSSL 0.9.8k and OpenSSL 0.9.8l [5 Nov 2009]:
o Temporary work around for CVE-2009-3555: disable renegotiation.
Major changes between OpenSSL 0.9.8j and OpenSSL 0.9.8k [25 Mar 2009]:
o Fix various build issues.
o Fix security issues (CVE-2009-0590, CVE-2009-0591, CVE-2009-0789)
Major changes between OpenSSL 0.9.8i and OpenSSL 0.9.8j [7 Jan 2009]:
o Fix security issue (CVE-2008-5077)
o Merge FIPS 140-2 branch code.
Major changes between OpenSSL 0.9.8g and OpenSSL 0.9.8h [28 May 2008]:
o CryptoAPI ENGINE support.
o Various precautionary measures.
o Fix for bugs affecting certificate request creation.
o Support for local machine keyset attribute in PKCS#12 files.
Major changes between OpenSSL 0.9.8f and OpenSSL 0.9.8g [19 Oct 2007]:
o Backport of CMS functionality to 0.9.8.
o Fixes for bugs introduced with 0.9.8f.
Major changes between OpenSSL 0.9.8e and OpenSSL 0.9.8f [11 Oct 2007]:
o Add gcc 4.2 support.
o Add support for AES and SSE2 assembly language optimization
for VC++ build.
o Support for RFC4507bis and server name extensions if explicitly
selected at compile time.
o DTLS improvements.
o RFC4507bis support.
o TLS Extensions support.
Major changes between OpenSSL 0.9.8d and OpenSSL 0.9.8e [23 Feb 2007]:
o Various ciphersuite selection fixes.
o RFC3779 support.
Major changes between OpenSSL 0.9.8c and OpenSSL 0.9.8d [28 Sep 2006]:
o Introduce limits to prevent malicious key DoS (CVE-2006-2940)
o Fix security issues (CVE-2006-2937, CVE-2006-3737, CVE-2006-4343)
o Changes to ciphersuite selection algorithm
Major changes between OpenSSL 0.9.8b and OpenSSL 0.9.8c [5 Sep 2006]:
o Fix Daniel Bleichenbacher forged signature attack, CVE-2006-4339
o New cipher Camellia
Major changes between OpenSSL 0.9.8a and OpenSSL 0.9.8b [4 May 2006]:
o Cipher string fixes.
o Fixes for VC++ 2005.
o Updated ECC cipher suite support.
o New functions EVP_CIPHER_CTX_new() and EVP_CIPHER_CTX_free().
o Zlib compression usage fixes.
o Built in dynamic engine compilation support on Win32.
o Fixes auto dynamic engine loading in Win32.
Major changes between OpenSSL 0.9.8 and OpenSSL 0.9.8a [11 Oct 2005]:
o Fix potential SSL 2.0 rollback, CVE-2005-2969
o Extended Windows CE support
Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.8 [5 Jul 2005]:
o Major work on the BIGNUM library for higher efficiency and to
make operations more streamlined and less contradictory. This
is the result of a major audit of the BIGNUM library.
o Addition of BIGNUM functions for fields GF(2^m) and NIST
curves, to support the Elliptic Crypto functions.
o Major work on Elliptic Crypto; ECDH and ECDSA added, including
the use through EVP, X509 and ENGINE.
o New ASN.1 mini-compiler that's usable through the OpenSSL
configuration file.
o Added support for ASN.1 indefinite length constructed encoding.
o New PKCS#12 'medium level' API to manipulate PKCS#12 files.
o Complete rework of shared library construction and linking
programs with shared or static libraries, through a separate
Makefile.shared.
o Rework of the passing of parameters from one Makefile to another.
o Changed ENGINE framework to load dynamic engine modules
automatically from specifically given directories.
o New structure and ASN.1 functions for CertificatePair.
o Changed the ZLIB compression method to be stateful.
o Changed the key-generation and primality testing "progress"
mechanism to take a structure that contains the ticker
function and an argument.
o New engine module: GMP (performs private key exponentiation).
o New engine module: VIA PadLOck ACE extension in VIA C3
Nehemiah processors.
o Added support for IPv6 addresses in certificate extensions.
See RFC 1884, section 2.2.
o Added support for certificate policy mappings, policy
constraints and name constraints.
o Added support for multi-valued AVAs in the OpenSSL
configuration file.
o Added support for multiple certificates with the same subject
in the 'openssl ca' index file.
o Make it possible to create self-signed certificates using
'openssl ca -selfsign'.
o Make it possible to generate a serial number file with
'openssl ca -create_serial'.
o New binary search functions with extended functionality.
o New BUF functions.
o New STORE structure and library to provide an interface to all
sorts of data repositories. Supports storage of public and
private keys, certificates, CRLs, numbers and arbitrary blobs.
This library is unfortunately unfinished and unused within
OpenSSL.
o New control functions for the error stack.
o Changed the PKCS#7 library to support one-pass S/MIME
processing.
o Added the possibility to compile without old deprecated
functionality with the OPENSSL_NO_DEPRECATED macro or the
'no-deprecated' argument to the config and Configure scripts.
o Constification of all ASN.1 conversion functions, and other
affected functions.
o Improved platform support for PowerPC.
o New FIPS 180-2 algorithms (SHA-224, -256, -384 and -512).
o New X509_VERIFY_PARAM structure to support parameterisation
of X.509 path validation.
o Major overhaul of RC4 performance on Intel P4, IA-64 and
AMD64.
o Changed the Configure script to have some algorithms disabled
by default. Those can be explicitly enabled with the new
argument form 'enable-xxx'.
o Change the default digest in 'openssl' commands from MD5 to
SHA-1.
o Added support for DTLS.
o New BIGNUM blinding.
o Added support for the RSA-PSS encryption scheme
o Added support for the RSA X.931 padding.
o Added support for BSD sockets on NetWare.
o Added support for files larger than 2GB.
o Added initial support for Win64.
o Added alternate pkg-config files.
Major changes between OpenSSL 0.9.7l and OpenSSL 0.9.7m [23 Feb 2007]:
o FIPS 1.1.1 module linking.
o Various ciphersuite selection fixes.
Major changes between OpenSSL 0.9.7k and OpenSSL 0.9.7l [28 Sep 2006]:
o Introduce limits to prevent malicious key DoS (CVE-2006-2940)
o Fix security issues (CVE-2006-2937, CVE-2006-3737, CVE-2006-4343)
Major changes between OpenSSL 0.9.7j and OpenSSL 0.9.7k [5 Sep 2006]:
o Fix Daniel Bleichenbacher forged signature attack, CVE-2006-4339
Major changes between OpenSSL 0.9.7i and OpenSSL 0.9.7j [4 May 2006]:
o Visual C++ 2005 fixes.
o Update Windows build system for FIPS.
Major changes between OpenSSL 0.9.7h and OpenSSL 0.9.7i [14 Oct 2005]:
o Give EVP_MAX_MD_SIZE it's old value, except for a FIPS build.
Major changes between OpenSSL 0.9.7g and OpenSSL 0.9.7h [11 Oct 2005]:
o Fix SSL 2.0 Rollback, CVE-2005-2969
o Allow use of fixed-length exponent on DSA signing
o Default fixed-window RSA, DSA, DH private-key operations
Major changes between OpenSSL 0.9.7f and OpenSSL 0.9.7g [11 Apr 2005]:
o More compilation issues fixed.
o Adaptation to more modern Kerberos API.
o Enhanced or corrected configuration for Solaris64, Mingw and Cygwin.
o Enhanced x86_64 assembler BIGNUM module.
o More constification.
o Added processing of proxy certificates (RFC 3820).
Major changes between OpenSSL 0.9.7e and OpenSSL 0.9.7f [22 Mar 2005]:
o Several compilation issues fixed.
o Many memory allocation failure checks added.
o Improved comparison of X509 Name type.
o Mandatory basic checks on certificates.
o Performance improvements.
Major changes between OpenSSL 0.9.7d and OpenSSL 0.9.7e [25 Oct 2004]:
o Fix race condition in CRL checking code.
o Fixes to PKCS#7 (S/MIME) code.
Major changes between OpenSSL 0.9.7c and OpenSSL 0.9.7d [17 Mar 2004]:
o Security: Fix Kerberos ciphersuite SSL/TLS handshaking bug
o Security: Fix null-pointer assignment in do_change_cipher_spec()
o Allow multiple active certificates with same subject in CA index
o Multiple X509 verification fixes
o Speed up HMAC and other operations
Major changes between OpenSSL 0.9.7b and OpenSSL 0.9.7c [30 Sep 2003]:
o Security: fix various ASN1 parsing bugs.
o New -ignore_err option to OCSP utility.
o Various interop and bug fixes in S/MIME code.
o SSL/TLS protocol fix for unrequested client certificates.
Major changes between OpenSSL 0.9.7a and OpenSSL 0.9.7b [10 Apr 2003]:
o Security: counter the Klima-Pokorny-Rosa extension of
Bleichbacher's attack
o Security: make RSA blinding default.
o Configuration: Irix fixes, AIX fixes, better mingw support.
o Support for new platforms: linux-ia64-ecc.
o Build: shared library support fixes.
o ASN.1: treat domainComponent correctly.
o Documentation: fixes and additions.
Major changes between OpenSSL 0.9.7 and OpenSSL 0.9.7a [19 Feb 2003]:
o Security: Important security related bugfixes.
o Enhanced compatibility with MIT Kerberos.
o Can be built without the ENGINE framework.
o IA32 assembler enhancements.
o Support for new platforms: FreeBSD/IA64 and FreeBSD/Sparc64.
o Configuration: the no-err option now works properly.
o SSL/TLS: now handles manual certificate chain building.
o SSL/TLS: certain session ID malfunctions corrected.
Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.7 [30 Dec 2002]:
o New library section OCSP.
o Complete rewrite of ASN1 code.
o CRL checking in verify code and openssl utility.
o Extension copying in 'ca' utility.
o Flexible display options in 'ca' utility.
o Provisional support for international characters with UTF8.
o Support for external crypto devices ('engine') is no longer
a separate distribution.
o New elliptic curve library section.
o New AES (Rijndael) library section.
o Support for new platforms: Windows CE, Tandem OSS, A/UX, AIX 64-bit,
Linux x86_64, Linux 64-bit on Sparc v9
o Extended support for some platforms: VxWorks
o Enhanced support for shared libraries.
o Now only builds PIC code when shared library support is requested.
o Support for pkg-config.
o Lots of new manuals.
o Makes symbolic links to or copies of manuals to cover all described
functions.
o Change DES API to clean up the namespace (some applications link also
against libdes providing similar functions having the same name).
Provide macros for backward compatibility (will be removed in the
future).
o Unify handling of cryptographic algorithms (software and engine)
to be available via EVP routines for asymmetric and symmetric ciphers.
o NCONF: new configuration handling routines.
o Change API to use more 'const' modifiers to improve error checking
and help optimizers.
o Finally remove references to RSAref.
o Reworked parts of the BIGNUM code.
o Support for new engines: Broadcom ubsec, Accelerated Encryption
Processing, IBM 4758.
o A few new engines added in the demos area.
o Extended and corrected OID (object identifier) table.
o PRNG: query at more locations for a random device, automatic query for
EGD style random sources at several locations.
o SSL/TLS: allow optional cipher choice according to server's preference.
o SSL/TLS: allow server to explicitly set new session ids.
o SSL/TLS: support Kerberos cipher suites (RFC2712).
Only supports MIT Kerberos for now.
o SSL/TLS: allow more precise control of renegotiations and sessions.
o SSL/TLS: add callback to retrieve SSL/TLS messages.
o SSL/TLS: support AES cipher suites (RFC3268).
Major changes between OpenSSL 0.9.6j and OpenSSL 0.9.6k [30 Sep 2003]:
o Security: fix various ASN1 parsing bugs.
o SSL/TLS protocol fix for unrequested client certificates.
Major changes between OpenSSL 0.9.6i and OpenSSL 0.9.6j [10 Apr 2003]:
o Security: counter the Klima-Pokorny-Rosa extension of
Bleichbacher's attack
o Security: make RSA blinding default.
o Build: shared library support fixes.
Major changes between OpenSSL 0.9.6h and OpenSSL 0.9.6i [19 Feb 2003]:
o Important security related bugfixes.
Major changes between OpenSSL 0.9.6g and OpenSSL 0.9.6h [5 Dec 2002]:
o New configuration targets for Tandem OSS and A/UX.
o New OIDs for Microsoft attributes.
o Better handling of SSL session caching.
o Better comparison of distinguished names.
o Better handling of shared libraries in a mixed GNU/non-GNU environment.
o Support assembler code with Borland C.
o Fixes for length problems.
o Fixes for uninitialised variables.
o Fixes for memory leaks, some unusual crashes and some race conditions.
o Fixes for smaller building problems.
o Updates of manuals, FAQ and other instructive documents.
Major changes between OpenSSL 0.9.6f and OpenSSL 0.9.6g [9 Aug 2002]:
o Important building fixes on Unix.
Major changes between OpenSSL 0.9.6e and OpenSSL 0.9.6f [8 Aug 2002]:
o Various important bugfixes.
Major changes between OpenSSL 0.9.6d and OpenSSL 0.9.6e [30 Jul 2002]:
o Important security related bugfixes.
o Various SSL/TLS library bugfixes.
Major changes between OpenSSL 0.9.6c and OpenSSL 0.9.6d [9 May 2002]:
o Various SSL/TLS library bugfixes.
o Fix DH parameter generation for 'non-standard' generators.
Major changes between OpenSSL 0.9.6b and OpenSSL 0.9.6c [21 Dec 2001]:
o Various SSL/TLS library bugfixes.
o BIGNUM library fixes.
o RSA OAEP and random number generation fixes.
o Object identifiers corrected and added.
o Add assembler BN routines for IA64.
o Add support for OS/390 Unix, UnixWare with gcc, OpenUNIX 8,
MIPS Linux; shared library support for Irix, HP-UX.
o Add crypto accelerator support for AEP, Baltimore SureWare,
Broadcom and Cryptographic Appliance's keyserver
[in 0.9.6c-engine release].
Major changes between OpenSSL 0.9.6a and OpenSSL 0.9.6b [9 Jul 2001]:
o Security fix: PRNG improvements.
o Security fix: RSA OAEP check.
o Security fix: Reinsert and fix countermeasure to Bleichbacher's
attack.
o MIPS bug fix in BIGNUM.
o Bug fix in "openssl enc".
o Bug fix in X.509 printing routine.
o Bug fix in DSA verification routine and DSA S/MIME verification.
o Bug fix to make PRNG thread-safe.
o Bug fix in RAND_file_name().
o Bug fix in compatibility mode trust settings.
o Bug fix in blowfish EVP.
o Increase default size for BIO buffering filter.
o Compatibility fixes in some scripts.
Major changes between OpenSSL 0.9.6 and OpenSSL 0.9.6a [5 Apr 2001]:
o Security fix: change behavior of OpenSSL to avoid using
environment variables when running as root.
o Security fix: check the result of RSA-CRT to reduce the
possibility of deducing the private key from an incorrectly
calculated signature.
o Security fix: prevent Bleichenbacher's DSA attack.
o Security fix: Zero the premaster secret after deriving the
master secret in DH ciphersuites.
o Reimplement SSL_peek(), which had various problems.
o Compatibility fix: the function des_encrypt() renamed to
des_encrypt1() to avoid clashes with some Unixen libc.
o Bug fixes for Win32, HP/UX and Irix.
o Bug fixes in BIGNUM, SSL, PKCS#7, PKCS#12, X.509, CONF and
memory checking routines.
o Bug fixes for RSA operations in threaded environments.
o Bug fixes in misc. openssl applications.
o Remove a few potential memory leaks.
o Add tighter checks of BIGNUM routines.
o Shared library support has been reworked for generality.
o More documentation.
o New function BN_rand_range().
o Add "-rand" option to openssl s_client and s_server.
Major changes between OpenSSL 0.9.5a and OpenSSL 0.9.6 [10 Oct 2000]:
o Some documentation for BIO and SSL libraries.
o Enhanced chain verification using key identifiers.
o New sign and verify options to 'dgst' application.
o Support for DER and PEM encoded messages in 'smime' application.
o New 'rsautl' application, low level RSA utility.
o MD4 now included.
o Bugfix for SSL rollback padding check.
o Support for external crypto devices [1].
o Enhanced EVP interface.
[1] The support for external crypto devices is currently a separate
distribution. See the file README.ENGINE.
Major changes between OpenSSL 0.9.5 and OpenSSL 0.9.5a [1 Apr 2000]:
o Bug fixes for Win32, SuSE Linux, NeXTSTEP and FreeBSD 2.2.8
o Shared library support for HPUX and Solaris-gcc
o Support of Linux/IA64
o Assembler support for Mingw32
o New 'rand' application
o New way to check for existence of algorithms from scripts
Major changes between OpenSSL 0.9.4 and OpenSSL 0.9.5 [25 May 2000]:
o S/MIME support in new 'smime' command
o Documentation for the OpenSSL command line application
o Automation of 'req' application
o Fixes to make s_client, s_server work under Windows
o Support for multiple fieldnames in SPKACs
o New SPKAC command line utility and associated library functions
o Options to allow passwords to be obtained from various sources
o New public key PEM format and options to handle it
o Many other fixes and enhancements to command line utilities
o Usable certificate chain verification
o Certificate purpose checking
o Certificate trust settings
o Support of authority information access extension
o Extensions in certificate requests
o Simplified X509 name and attribute routines
o Initial (incomplete) support for international character sets
o New DH_METHOD, DSA_METHOD and enhanced RSA_METHOD
o Read only memory BIOs and simplified creation function
o TLS/SSL protocol bugfixes: Accept TLS 'client hello' in SSL 3.0
record; allow fragmentation and interleaving of handshake and other
data
o TLS/SSL code now "tolerates" MS SGC
o Work around for Netscape client certificate hang bug
o RSA_NULL option that removes RSA patent code but keeps other
RSA functionality
o Memory leak detection now allows applications to add extra information
via a per-thread stack
o PRNG robustness improved
o EGD support
o BIGNUM library bug fixes
o Faster DSA parameter generation
o Enhanced support for Alpha Linux
o Experimental MacOS support
Major changes between OpenSSL 0.9.3 and OpenSSL 0.9.4 [9 Aug 1999]:
o Transparent support for PKCS#8 format private keys: these are used
by several software packages and are more secure than the standard
form
o PKCS#5 v2.0 implementation
o Password callbacks have a new void * argument for application data
o Avoid various memory leaks
o New pipe-like BIO that allows using the SSL library when actual I/O
must be handled by the application (BIO pair)
Major changes between OpenSSL 0.9.2b and OpenSSL 0.9.3 [24 May 1999]:
o Lots of enhancements and cleanups to the Configuration mechanism
o RSA OEAP related fixes
o Added `openssl ca -revoke' option for revoking a certificate
o Source cleanups: const correctness, type-safe stacks and ASN.1 SETs
o Source tree cleanups: removed lots of obsolete files
o Thawte SXNet, certificate policies and CRL distribution points
extension support
o Preliminary (experimental) S/MIME support
o Support for ASN.1 UTF8String and VisibleString
o Full integration of PKCS#12 code
o Sparc assembler bignum implementation, optimized hash functions
o Option to disable selected ciphers
Major changes between OpenSSL 0.9.1c and OpenSSL 0.9.2b [22 Mar 1999]:
o Fixed a security hole related to session resumption
o Fixed RSA encryption routines for the p < q case
o "ALL" in cipher lists now means "everything except NULL ciphers"
o Support for Triple-DES CBCM cipher
o Support of Optimal Asymmetric Encryption Padding (OAEP) for RSA
o First support for new TLSv1 ciphers
o Added a few new BIOs (syslog BIO, reliable BIO)
o Extended support for DSA certificate/keys.
o Extended support for Certificate Signing Requests (CSR)
o Initial support for X.509v3 extensions
o Extended support for compression inside the SSL record layer
o Overhauled Win32 builds
o Cleanups and fixes to the Big Number (BN) library
o Support for ASN.1 GeneralizedTime
o Splitted ASN.1 SETs from SEQUENCEs
o ASN1 and PEM support for Netscape Certificate Sequences
o Overhauled Perl interface
o Lots of source tree cleanups.
o Lots of memory leak fixes.
o Lots of bug fixes.
Major changes between SSLeay 0.9.0b and OpenSSL 0.9.1c [23 Dec 1998]:
o Integration of the popular NO_RSA/NO_DSA patches
o Initial support for compression inside the SSL record layer
o Added BIO proxy and filtering functionality
o Extended Big Number (BN) library
o Added RIPE MD160 message digest
o Added support for RC2/64bit cipher
o Extended ASN.1 parser routines
o Adjustments of the source tree for CVS
o Support for various new platforms
diff --git a/NOTES.PERL b/NOTES.PERL
index 46d585acca14..42c6127724b4 100644
--- a/NOTES.PERL
+++ b/NOTES.PERL
@@ -1,119 +1,119 @@
TOC
===
- Notes on Perl
- Notes on Perl on Windows
- Notes on Perl modules we use
- Notes on installing a perl module
Notes on Perl
-------------
For our scripts, we rely quite a bit on Perl, and increasingly on
some core Perl modules. These Perl modules are part of the Perl
source, so if you build Perl on your own, you should be set.
However, if you install Perl as binary packages, the outcome might
differ, and you may have to check that you do get the core modules
installed properly. We do not claim to know them all, but experience
has told us the following:
- on Linux distributions based on Debian, the package 'perl' will
install the core Perl modules as well, so you will be fine.
- on Linux distributions based on RPMs, you will need to install
'perl-core' rather than just 'perl'.
You MUST have at least Perl version 5.10.0 installed. This minimum
requirement is due to our use of regexp backslash sequence \R among
other features that didn't exist in core Perl before that version.
Notes on Perl on Windows
------------------------
There are a number of build targets that can be viewed as "Windows".
Indeed, there are VC-* configs targeting VisualStudio C, as well as
MinGW and Cygwin. The key recommendation is to use "matching" Perl,
one that matches build environment. For example, if you will build
on Cygwin be sure to use the Cygwin package manager to install Perl.
For MSYS builds use the MSYS provided Perl. For VC-* builds we
recommend ActiveState Perl, available from
http://www.activestate.com/ActivePerl.
Notes on Perl on VMS
--------------------
You will need to install Perl separately. One way to do so is to
download the source from http://perl.org/, unpacking it, reading
README.vms and follow the instructions. Another way is to download a
.PCSI file from http://www.vmsperl.com/ and install it using the
POLYCENTER install tool.
Notes on Perl modules we use
----------------------------
We make increasing use of Perl modules, and do our best to limit
ourselves to core Perl modules to keep the requirements down. There
are just a few exceptions:
Test::More We require the minimum version to be 0.96, which
appeared in Perl 5.13.4, because that version was
the first to have all the features we're using.
This module is required for testing only! If you
don't plan on running the tests, you don't need to
bother with this one.
Text::Template This module is not part of the core Perl modules.
As a matter of fact, the core Perl modules do not
include any templating module to date.
This module is absolutely needed, configuration
depends on it.
To avoid unnecessary initial hurdles, we have bundled a copy of the
following modules in our source. They will work as fallbacks if
these modules aren't already installed on the system.
Text::Template
Notes on installing a perl module
---------------------------------
There are a number of ways to install a perl module. In all
- descriptions below, Text::Template will server as an example.
+ descriptions below, Text::Template will serve as an example.
1. for Linux users, the easiest is to install with the use of your
favorite package manager. Usually, all you need to do is search
for the module name and to install the package that comes up.
On Debian based Linux distributions, it would go like this:
$ apt-cache search Text::Template
...
libtext-template-perl - perl module to process text templates
$ sudo apt-get install libtext-template-perl
Perl modules in Debian based distributions use package names like
the name of the module in question, with "lib" prepended and
"-perl" appended.
2. Install using CPAN. This is very easy, but usually requires root
access:
$ cpan -i Text::Template
Note that this runs all the tests that the module to be installed
comes with. This is usually a smooth operation, but there are
platforms where a failure is indicated even though the actual tests
were successful. Should that happen, you can force an
installation regardless (that should be safe since you've already
seen the tests succeed!):
$ cpan -f -i Text::Template
Note: on VMS, you must quote any argument that contains upper case
characters, so the lines above would be:
$ cpan -i "Text::Template"
and:
$ cpan -f -i "Text::Template"
diff --git a/README b/README
index d0023229572f..29757157c384 100644
--- a/README
+++ b/README
@@ -1,93 +1,93 @@
- OpenSSL 1.1.1b 26 Feb 2019
+ OpenSSL 1.1.1c 28 May 2019
- Copyright (c) 1998-2018 The OpenSSL Project
+ Copyright (c) 1998-2019 The OpenSSL Project
Copyright (c) 1995-1998 Eric A. Young, Tim J. Hudson
All rights reserved.
DESCRIPTION
-----------
The OpenSSL Project is a collaborative effort to develop a robust,
commercial-grade, fully featured, and Open Source toolkit implementing the
Transport Layer Security (TLS) protocols (including SSLv3) as well as a
full-strength general purpose cryptographic library.
OpenSSL is descended from the SSLeay library developed by Eric A. Young
and Tim J. Hudson. The OpenSSL toolkit is licensed under a dual-license (the
OpenSSL license plus the SSLeay license), which means that you are free to
get and use it for commercial and non-commercial purposes as long as you
fulfill the conditions of both licenses.
OVERVIEW
--------
The OpenSSL toolkit includes:
libssl (with platform specific naming):
Provides the client and server-side implementations for SSLv3 and TLS.
libcrypto (with platform specific naming):
Provides general cryptographic and X.509 support needed by SSL/TLS but
not logically part of it.
openssl:
A command line tool that can be used for:
Creation of key parameters
Creation of X.509 certificates, CSRs and CRLs
Calculation of message digests
Encryption and decryption
SSL/TLS client and server tests
Handling of S/MIME signed or encrypted mail
And more...
INSTALLATION
------------
See the appropriate file:
INSTALL Linux, Unix, Windows, OpenVMS, ...
NOTES.* INSTALL addendums for different platforms
SUPPORT
-------
See the OpenSSL website www.openssl.org for details on how to obtain
commercial technical support. Free community support is available through the
openssl-users email list (see
https://www.openssl.org/community/mailinglists.html for further details).
If you have any problems with OpenSSL then please take the following steps
first:
- Download the latest version from the repository
to see if the problem has already been addressed
- Configure with no-asm
- Remove compiler optimization flags
If you wish to report a bug then please include the following information
and create an issue on GitHub:
- OpenSSL version: output of 'openssl version -a'
- Configuration data: output of 'perl configdata.pm --dump'
- OS Name, Version, Hardware platform
- Compiler Details (name, version)
- Application Details (name, version)
- Problem Description (steps that will reproduce the problem, if known)
- Stack Traceback (if the application dumps core)
Just because something doesn't work the way you expect does not mean it
is necessarily a bug in OpenSSL. Use the openssl-users email list for this type
of query.
HOW TO CONTRIBUTE TO OpenSSL
----------------------------
See CONTRIBUTING
LEGALITIES
----------
A number of nations restrict the use or export of cryptography. If you
are potentially subject to such restrictions you should seek competent
professional legal advice before attempting to develop or distribute
cryptographic code.
diff --git a/apps/asn1pars.c b/apps/asn1pars.c
index 62c70b9cc440..6c44df7de490 100644
--- a/apps/asn1pars.c
+++ b/apps/asn1pars.c
@@ -1,357 +1,355 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "apps.h"
#include "progs.h"
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/asn1t.h>
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_INFORM, OPT_IN, OPT_OUT, OPT_INDENT, OPT_NOOUT,
OPT_OID, OPT_OFFSET, OPT_LENGTH, OPT_DUMP, OPT_DLIMIT,
OPT_STRPARSE, OPT_GENSTR, OPT_GENCONF, OPT_STRICTPEM,
OPT_ITEM
} OPTION_CHOICE;
const OPTIONS asn1parse_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"inform", OPT_INFORM, 'F', "input format - one of DER PEM"},
{"in", OPT_IN, '<', "input file"},
{"out", OPT_OUT, '>', "output file (output format is always DER)"},
{"i", OPT_INDENT, 0, "indents the output"},
{"noout", OPT_NOOUT, 0, "do not produce any output"},
{"offset", OPT_OFFSET, 'p', "offset into file"},
{"length", OPT_LENGTH, 'p', "length of section in file"},
{"oid", OPT_OID, '<', "file of extra oid definitions"},
{"dump", OPT_DUMP, 0, "unknown data in hex form"},
{"dlimit", OPT_DLIMIT, 'p',
"dump the first arg bytes of unknown data in hex form"},
{"strparse", OPT_STRPARSE, 'p',
"offset; a series of these can be used to 'dig'"},
{OPT_MORE_STR, 0, 0, "into multiple ASN1 blob wrappings"},
{"genstr", OPT_GENSTR, 's', "string to generate ASN1 structure from"},
{"genconf", OPT_GENCONF, 's', "file to generate ASN1 structure from"},
{OPT_MORE_STR, 0, 0, "(-inform will be ignored)"},
{"strictpem", OPT_STRICTPEM, 0,
"do not attempt base64 decode outside PEM markers"},
{"item", OPT_ITEM, 's', "item to parse and print"},
{NULL}
};
static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf);
int asn1parse_main(int argc, char **argv)
{
ASN1_TYPE *at = NULL;
BIO *in = NULL, *b64 = NULL, *derout = NULL;
BUF_MEM *buf = NULL;
STACK_OF(OPENSSL_STRING) *osk = NULL;
char *genstr = NULL, *genconf = NULL;
char *infile = NULL, *oidfile = NULL, *derfile = NULL;
unsigned char *str = NULL;
char *name = NULL, *header = NULL, *prog;
const unsigned char *ctmpbuf;
int indent = 0, noout = 0, dump = 0, strictpem = 0, informat = FORMAT_PEM;
int offset = 0, ret = 1, i, j;
long num, tmplen;
unsigned char *tmpbuf;
unsigned int length = 0;
OPTION_CHOICE o;
const ASN1_ITEM *it = NULL;
prog = opt_init(argc, argv, asn1parse_options);
if ((osk = sk_OPENSSL_STRING_new_null()) == NULL) {
BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
goto end;
}
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(asn1parse_options);
ret = 0;
goto end;
case OPT_INFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat))
goto opthelp;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUT:
derfile = opt_arg();
break;
case OPT_INDENT:
indent = 1;
break;
case OPT_NOOUT:
noout = 1;
break;
case OPT_OID:
oidfile = opt_arg();
break;
case OPT_OFFSET:
offset = strtol(opt_arg(), NULL, 0);
break;
case OPT_LENGTH:
length = strtol(opt_arg(), NULL, 0);
break;
case OPT_DUMP:
dump = -1;
break;
case OPT_DLIMIT:
dump = strtol(opt_arg(), NULL, 0);
break;
case OPT_STRPARSE:
sk_OPENSSL_STRING_push(osk, opt_arg());
break;
case OPT_GENSTR:
genstr = opt_arg();
break;
case OPT_GENCONF:
genconf = opt_arg();
break;
case OPT_STRICTPEM:
strictpem = 1;
informat = FORMAT_PEM;
break;
case OPT_ITEM:
it = ASN1_ITEM_lookup(opt_arg());
if (it == NULL) {
size_t tmp;
BIO_printf(bio_err, "Unknown item name %s\n", opt_arg());
BIO_puts(bio_err, "Supported types:\n");
for (tmp = 0;; tmp++) {
it = ASN1_ITEM_get(tmp);
if (it == NULL)
break;
BIO_printf(bio_err, " %s\n", it->sname);
}
goto end;
}
break;
}
}
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
if (oidfile != NULL) {
in = bio_open_default(oidfile, 'r', FORMAT_TEXT);
if (in == NULL)
goto end;
OBJ_create_objects(in);
BIO_free(in);
}
if ((in = bio_open_default(infile, 'r', informat)) == NULL)
goto end;
if (derfile && (derout = bio_open_default(derfile, 'w', FORMAT_ASN1)) == NULL)
goto end;
+ if ((buf = BUF_MEM_new()) == NULL)
+ goto end;
if (strictpem) {
- if (PEM_read_bio(in, &name, &header, &str, &num) !=
- 1) {
+ if (PEM_read_bio(in, &name, &header, &str, &num) != 1) {
BIO_printf(bio_err, "Error reading PEM file\n");
ERR_print_errors(bio_err);
goto end;
}
+ buf->data = (char *)str;
+ buf->length = buf->max = num;
} else {
-
- if ((buf = BUF_MEM_new()) == NULL)
- goto end;
if (!BUF_MEM_grow(buf, BUFSIZ * 8))
goto end; /* Pre-allocate :-) */
if (genstr || genconf) {
num = do_generate(genstr, genconf, buf);
if (num < 0) {
ERR_print_errors(bio_err);
goto end;
}
} else {
if (informat == FORMAT_PEM) {
BIO *tmp;
if ((b64 = BIO_new(BIO_f_base64())) == NULL)
goto end;
BIO_push(b64, in);
tmp = in;
in = b64;
b64 = tmp;
}
num = 0;
for (;;) {
if (!BUF_MEM_grow(buf, num + BUFSIZ))
goto end;
i = BIO_read(in, &(buf->data[num]), BUFSIZ);
if (i <= 0)
break;
num += i;
}
}
str = (unsigned char *)buf->data;
}
/* If any structs to parse go through in sequence */
if (sk_OPENSSL_STRING_num(osk)) {
tmpbuf = str;
tmplen = num;
for (i = 0; i < sk_OPENSSL_STRING_num(osk); i++) {
ASN1_TYPE *atmp;
int typ;
j = strtol(sk_OPENSSL_STRING_value(osk, i), NULL, 0);
if (j <= 0 || j >= tmplen) {
BIO_printf(bio_err, "'%s' is out of range\n",
sk_OPENSSL_STRING_value(osk, i));
continue;
}
tmpbuf += j;
tmplen -= j;
atmp = at;
ctmpbuf = tmpbuf;
at = d2i_ASN1_TYPE(NULL, &ctmpbuf, tmplen);
ASN1_TYPE_free(atmp);
if (!at) {
BIO_printf(bio_err, "Error parsing structure\n");
ERR_print_errors(bio_err);
goto end;
}
typ = ASN1_TYPE_get(at);
if ((typ == V_ASN1_OBJECT)
|| (typ == V_ASN1_BOOLEAN)
|| (typ == V_ASN1_NULL)) {
BIO_printf(bio_err, "Can't parse %s type\n", ASN1_tag2str(typ));
ERR_print_errors(bio_err);
goto end;
}
/* hmm... this is a little evil but it works */
tmpbuf = at->value.asn1_string->data;
tmplen = at->value.asn1_string->length;
}
str = tmpbuf;
num = tmplen;
}
if (offset < 0 || offset >= num) {
BIO_printf(bio_err, "Error: offset out of range\n");
goto end;
}
num -= offset;
if (length == 0 || length > (unsigned int)num)
length = (unsigned int)num;
if (derout != NULL) {
if (BIO_write(derout, str + offset, length) != (int)length) {
BIO_printf(bio_err, "Error writing output\n");
ERR_print_errors(bio_err);
goto end;
}
}
if (!noout) {
const unsigned char *p = str + offset;
if (it != NULL) {
ASN1_VALUE *value = ASN1_item_d2i(NULL, &p, length, it);
if (value == NULL) {
BIO_printf(bio_err, "Error parsing item %s\n", it->sname);
ERR_print_errors(bio_err);
goto end;
}
ASN1_item_print(bio_out, value, 0, it, NULL);
ASN1_item_free(value, it);
} else {
if (!ASN1_parse_dump(bio_out, p, length, indent, dump)) {
ERR_print_errors(bio_err);
goto end;
}
}
}
ret = 0;
end:
BIO_free(derout);
BIO_free(in);
BIO_free(b64);
if (ret != 0)
ERR_print_errors(bio_err);
BUF_MEM_free(buf);
OPENSSL_free(name);
OPENSSL_free(header);
- if (strictpem)
- OPENSSL_free(str);
ASN1_TYPE_free(at);
sk_OPENSSL_STRING_free(osk);
return ret;
}
static int do_generate(char *genstr, const char *genconf, BUF_MEM *buf)
{
CONF *cnf = NULL;
int len;
unsigned char *p;
ASN1_TYPE *atyp = NULL;
if (genconf != NULL) {
if ((cnf = app_load_config(genconf)) == NULL)
goto err;
if (genstr == NULL)
genstr = NCONF_get_string(cnf, "default", "asn1");
if (genstr == NULL) {
BIO_printf(bio_err, "Can't find 'asn1' in '%s'\n", genconf);
goto err;
}
}
atyp = ASN1_generate_nconf(genstr, cnf);
NCONF_free(cnf);
cnf = NULL;
if (atyp == NULL)
return -1;
len = i2d_ASN1_TYPE(atyp, NULL);
if (len <= 0)
goto err;
if (!BUF_MEM_grow(buf, len))
goto err;
p = (unsigned char *)buf->data;
i2d_ASN1_TYPE(atyp, &p);
ASN1_TYPE_free(atyp);
return len;
err:
NCONF_free(cnf);
ASN1_TYPE_free(atyp);
return -1;
}
diff --git a/apps/cms.c b/apps/cms.c
index e9d760c999b7..15edd67dbefd 100644
--- a/apps/cms.c
+++ b/apps/cms.c
@@ -1,1289 +1,1290 @@
/*
- * Copyright 2008-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* CMS utility function */
#include <stdio.h>
#include <string.h>
#include "apps.h"
#include "progs.h"
#ifndef OPENSSL_NO_CMS
# include <openssl/crypto.h>
# include <openssl/pem.h>
# include <openssl/err.h>
# include <openssl/x509_vfy.h>
# include <openssl/x509v3.h>
# include <openssl/cms.h>
static int save_certs(char *signerfile, STACK_OF(X509) *signers);
static int cms_cb(int ok, X509_STORE_CTX *ctx);
static void receipt_request_print(CMS_ContentInfo *cms);
static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
*rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
*rr_from);
static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
STACK_OF(OPENSSL_STRING) *param);
# define SMIME_OP 0x10
# define SMIME_IP 0x20
# define SMIME_SIGNERS 0x40
# define SMIME_ENCRYPT (1 | SMIME_OP)
# define SMIME_DECRYPT (2 | SMIME_IP)
# define SMIME_SIGN (3 | SMIME_OP | SMIME_SIGNERS)
# define SMIME_VERIFY (4 | SMIME_IP)
# define SMIME_CMSOUT (5 | SMIME_IP | SMIME_OP)
# define SMIME_RESIGN (6 | SMIME_IP | SMIME_OP | SMIME_SIGNERS)
# define SMIME_DATAOUT (7 | SMIME_IP)
# define SMIME_DATA_CREATE (8 | SMIME_OP)
# define SMIME_DIGEST_VERIFY (9 | SMIME_IP)
# define SMIME_DIGEST_CREATE (10 | SMIME_OP)
# define SMIME_UNCOMPRESS (11 | SMIME_IP)
# define SMIME_COMPRESS (12 | SMIME_OP)
# define SMIME_ENCRYPTED_DECRYPT (13 | SMIME_IP)
# define SMIME_ENCRYPTED_ENCRYPT (14 | SMIME_OP)
# define SMIME_SIGN_RECEIPT (15 | SMIME_IP | SMIME_OP)
# define SMIME_VERIFY_RECEIPT (16 | SMIME_IP)
static int verify_err = 0;
typedef struct cms_key_param_st cms_key_param;
struct cms_key_param_st {
int idx;
STACK_OF(OPENSSL_STRING) *param;
cms_key_param *next;
};
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_INFORM, OPT_OUTFORM, OPT_IN, OPT_OUT, OPT_ENCRYPT,
OPT_DECRYPT, OPT_SIGN, OPT_SIGN_RECEIPT, OPT_RESIGN,
OPT_VERIFY, OPT_VERIFY_RETCODE, OPT_VERIFY_RECEIPT,
OPT_CMSOUT, OPT_DATA_OUT, OPT_DATA_CREATE, OPT_DIGEST_VERIFY,
OPT_DIGEST_CREATE, OPT_COMPRESS, OPT_UNCOMPRESS,
OPT_ED_DECRYPT, OPT_ED_ENCRYPT, OPT_DEBUG_DECRYPT, OPT_TEXT,
OPT_ASCIICRLF, OPT_NOINTERN, OPT_NOVERIFY, OPT_NOCERTS,
OPT_NOATTR, OPT_NODETACH, OPT_NOSMIMECAP, OPT_BINARY, OPT_KEYID,
OPT_NOSIGS, OPT_NO_CONTENT_VERIFY, OPT_NO_ATTR_VERIFY, OPT_INDEF,
OPT_NOINDEF, OPT_CRLFEOL, OPT_NOOUT, OPT_RR_PRINT,
OPT_RR_ALL, OPT_RR_FIRST, OPT_RCTFORM, OPT_CERTFILE, OPT_CAFILE,
OPT_CAPATH, OPT_NOCAPATH, OPT_NOCAFILE,OPT_CONTENT, OPT_PRINT,
OPT_SECRETKEY, OPT_SECRETKEYID, OPT_PWRI_PASSWORD, OPT_ECONTENT_TYPE,
OPT_PASSIN, OPT_TO, OPT_FROM, OPT_SUBJECT, OPT_SIGNER, OPT_RECIP,
OPT_CERTSOUT, OPT_MD, OPT_INKEY, OPT_KEYFORM, OPT_KEYOPT, OPT_RR_FROM,
OPT_RR_TO, OPT_AES128_WRAP, OPT_AES192_WRAP, OPT_AES256_WRAP,
OPT_3DES_WRAP, OPT_ENGINE,
OPT_R_ENUM,
OPT_V_ENUM,
OPT_CIPHER
} OPTION_CHOICE;
const OPTIONS cms_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] cert.pem...\n"},
{OPT_HELP_STR, 1, '-',
" cert.pem... recipient certs for encryption\n"},
{OPT_HELP_STR, 1, '-', "Valid options are:\n"},
{"help", OPT_HELP, '-', "Display this summary"},
{"inform", OPT_INFORM, 'c', "Input format SMIME (default), PEM or DER"},
{"outform", OPT_OUTFORM, 'c',
"Output format SMIME (default), PEM or DER"},
{"in", OPT_IN, '<', "Input file"},
{"out", OPT_OUT, '>', "Output file"},
{"encrypt", OPT_ENCRYPT, '-', "Encrypt message"},
{"decrypt", OPT_DECRYPT, '-', "Decrypt encrypted message"},
{"sign", OPT_SIGN, '-', "Sign message"},
{"sign_receipt", OPT_SIGN_RECEIPT, '-', "Generate a signed receipt for the message"},
{"resign", OPT_RESIGN, '-', "Resign a signed message"},
{"verify", OPT_VERIFY, '-', "Verify signed message"},
{"verify_retcode", OPT_VERIFY_RETCODE, '-'},
{"verify_receipt", OPT_VERIFY_RECEIPT, '<'},
{"cmsout", OPT_CMSOUT, '-', "Output CMS structure"},
{"data_out", OPT_DATA_OUT, '-'},
{"data_create", OPT_DATA_CREATE, '-'},
{"digest_verify", OPT_DIGEST_VERIFY, '-'},
{"digest_create", OPT_DIGEST_CREATE, '-'},
{"compress", OPT_COMPRESS, '-'},
{"uncompress", OPT_UNCOMPRESS, '-'},
{"EncryptedData_decrypt", OPT_ED_DECRYPT, '-'},
{"EncryptedData_encrypt", OPT_ED_ENCRYPT, '-'},
{"debug_decrypt", OPT_DEBUG_DECRYPT, '-'},
{"text", OPT_TEXT, '-', "Include or delete text MIME headers"},
{"asciicrlf", OPT_ASCIICRLF, '-'},
{"nointern", OPT_NOINTERN, '-',
"Don't search certificates in message for signer"},
{"noverify", OPT_NOVERIFY, '-', "Don't verify signers certificate"},
{"nocerts", OPT_NOCERTS, '-',
"Don't include signers certificate when signing"},
{"noattr", OPT_NOATTR, '-', "Don't include any signed attributes"},
{"nodetach", OPT_NODETACH, '-', "Use opaque signing"},
{"nosmimecap", OPT_NOSMIMECAP, '-', "Omit the SMIMECapabilities attribute"},
{"binary", OPT_BINARY, '-', "Don't translate message to text"},
{"keyid", OPT_KEYID, '-', "Use subject key identifier"},
{"nosigs", OPT_NOSIGS, '-', "Don't verify message signature"},
{"no_content_verify", OPT_NO_CONTENT_VERIFY, '-'},
{"no_attr_verify", OPT_NO_ATTR_VERIFY, '-'},
{"stream", OPT_INDEF, '-', "Enable CMS streaming"},
{"indef", OPT_INDEF, '-', "Same as -stream"},
{"noindef", OPT_NOINDEF, '-', "Disable CMS streaming"},
{"crlfeol", OPT_CRLFEOL, '-', "Use CRLF as EOL termination instead of CR only" },
{"noout", OPT_NOOUT, '-', "For the -cmsout operation do not output the parsed CMS structure"},
{"receipt_request_print", OPT_RR_PRINT, '-', "Print CMS Receipt Request" },
{"receipt_request_all", OPT_RR_ALL, '-'},
{"receipt_request_first", OPT_RR_FIRST, '-'},
{"rctform", OPT_RCTFORM, 'F', "Receipt file format"},
{"certfile", OPT_CERTFILE, '<', "Other certificates file"},
{"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
{"CApath", OPT_CAPATH, '/', "trusted certificates directory"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
{"content", OPT_CONTENT, '<',
"Supply or override content for detached signature"},
{"print", OPT_PRINT, '-',
"For the -cmsout operation print out all fields of the CMS structure"},
{"secretkey", OPT_SECRETKEY, 's'},
{"secretkeyid", OPT_SECRETKEYID, 's'},
{"pwri_password", OPT_PWRI_PASSWORD, 's'},
{"econtent_type", OPT_ECONTENT_TYPE, 's'},
{"passin", OPT_PASSIN, 's', "Input file pass phrase source"},
{"to", OPT_TO, 's', "To address"},
{"from", OPT_FROM, 's', "From address"},
{"subject", OPT_SUBJECT, 's', "Subject"},
{"signer", OPT_SIGNER, 's', "Signer certificate file"},
{"recip", OPT_RECIP, '<', "Recipient cert file for decryption"},
{"certsout", OPT_CERTSOUT, '>', "Certificate output file"},
{"md", OPT_MD, 's', "Digest algorithm to use when signing or resigning"},
{"inkey", OPT_INKEY, 's',
"Input private key (if not signer or recipient)"},
{"keyform", OPT_KEYFORM, 'f', "Input private key format (PEM or ENGINE)"},
{"keyopt", OPT_KEYOPT, 's', "Set public key parameters as n:v pairs"},
{"receipt_request_from", OPT_RR_FROM, 's'},
{"receipt_request_to", OPT_RR_TO, 's'},
{"", OPT_CIPHER, '-', "Any supported cipher"},
OPT_R_OPTIONS,
OPT_V_OPTIONS,
{"aes128-wrap", OPT_AES128_WRAP, '-', "Use AES128 to wrap key"},
{"aes192-wrap", OPT_AES192_WRAP, '-', "Use AES192 to wrap key"},
{"aes256-wrap", OPT_AES256_WRAP, '-', "Use AES256 to wrap key"},
# ifndef OPENSSL_NO_DES
{"des3-wrap", OPT_3DES_WRAP, '-', "Use 3DES-EDE to wrap key"},
# endif
# ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine e, possibly a hardware device"},
# endif
{NULL}
};
int cms_main(int argc, char **argv)
{
ASN1_OBJECT *econtent_type = NULL;
BIO *in = NULL, *out = NULL, *indata = NULL, *rctin = NULL;
CMS_ContentInfo *cms = NULL, *rcms = NULL;
CMS_ReceiptRequest *rr = NULL;
ENGINE *e = NULL;
EVP_PKEY *key = NULL;
const EVP_CIPHER *cipher = NULL, *wrap_cipher = NULL;
const EVP_MD *sign_md = NULL;
STACK_OF(OPENSSL_STRING) *rr_to = NULL, *rr_from = NULL;
STACK_OF(OPENSSL_STRING) *sksigners = NULL, *skkeys = NULL;
STACK_OF(X509) *encerts = NULL, *other = NULL;
X509 *cert = NULL, *recip = NULL, *signer = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = NULL;
char *certfile = NULL, *keyfile = NULL, *contfile = NULL;
const char *CAfile = NULL, *CApath = NULL;
char *certsoutfile = NULL;
int noCAfile = 0, noCApath = 0;
char *infile = NULL, *outfile = NULL, *rctfile = NULL;
char *passinarg = NULL, *passin = NULL, *signerfile = NULL, *recipfile = NULL;
char *to = NULL, *from = NULL, *subject = NULL, *prog;
cms_key_param *key_first = NULL, *key_param = NULL;
int flags = CMS_DETACHED, noout = 0, print = 0, keyidx = -1, vpmtouched = 0;
int informat = FORMAT_SMIME, outformat = FORMAT_SMIME;
int operation = 0, ret = 1, rr_print = 0, rr_allorfirst = -1;
int verify_retcode = 0, rctformat = FORMAT_SMIME, keyform = FORMAT_PEM;
size_t secret_keylen = 0, secret_keyidlen = 0;
unsigned char *pwri_pass = NULL, *pwri_tmp = NULL;
unsigned char *secret_key = NULL, *secret_keyid = NULL;
long ltmp;
const char *mime_eol = "\n";
OPTION_CHOICE o;
if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
return 1;
prog = opt_init(argc, argv, cms_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(cms_options);
ret = 0;
goto end;
case OPT_INFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDS, &informat))
goto opthelp;
break;
case OPT_OUTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDS, &outformat))
goto opthelp;
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_ENCRYPT:
operation = SMIME_ENCRYPT;
break;
case OPT_DECRYPT:
operation = SMIME_DECRYPT;
break;
case OPT_SIGN:
operation = SMIME_SIGN;
break;
case OPT_SIGN_RECEIPT:
operation = SMIME_SIGN_RECEIPT;
break;
case OPT_RESIGN:
operation = SMIME_RESIGN;
break;
case OPT_VERIFY:
operation = SMIME_VERIFY;
break;
case OPT_VERIFY_RETCODE:
verify_retcode = 1;
break;
case OPT_VERIFY_RECEIPT:
operation = SMIME_VERIFY_RECEIPT;
rctfile = opt_arg();
break;
case OPT_CMSOUT:
operation = SMIME_CMSOUT;
break;
case OPT_DATA_OUT:
operation = SMIME_DATAOUT;
break;
case OPT_DATA_CREATE:
operation = SMIME_DATA_CREATE;
break;
case OPT_DIGEST_VERIFY:
operation = SMIME_DIGEST_VERIFY;
break;
case OPT_DIGEST_CREATE:
operation = SMIME_DIGEST_CREATE;
break;
case OPT_COMPRESS:
operation = SMIME_COMPRESS;
break;
case OPT_UNCOMPRESS:
operation = SMIME_UNCOMPRESS;
break;
case OPT_ED_DECRYPT:
operation = SMIME_ENCRYPTED_DECRYPT;
break;
case OPT_ED_ENCRYPT:
operation = SMIME_ENCRYPTED_ENCRYPT;
break;
case OPT_DEBUG_DECRYPT:
flags |= CMS_DEBUG_DECRYPT;
break;
case OPT_TEXT:
flags |= CMS_TEXT;
break;
case OPT_ASCIICRLF:
flags |= CMS_ASCIICRLF;
break;
case OPT_NOINTERN:
flags |= CMS_NOINTERN;
break;
case OPT_NOVERIFY:
flags |= CMS_NO_SIGNER_CERT_VERIFY;
break;
case OPT_NOCERTS:
flags |= CMS_NOCERTS;
break;
case OPT_NOATTR:
flags |= CMS_NOATTR;
break;
case OPT_NODETACH:
flags &= ~CMS_DETACHED;
break;
case OPT_NOSMIMECAP:
flags |= CMS_NOSMIMECAP;
break;
case OPT_BINARY:
flags |= CMS_BINARY;
break;
case OPT_KEYID:
flags |= CMS_USE_KEYID;
break;
case OPT_NOSIGS:
flags |= CMS_NOSIGS;
break;
case OPT_NO_CONTENT_VERIFY:
flags |= CMS_NO_CONTENT_VERIFY;
break;
case OPT_NO_ATTR_VERIFY:
flags |= CMS_NO_ATTR_VERIFY;
break;
case OPT_INDEF:
flags |= CMS_STREAM;
break;
case OPT_NOINDEF:
flags &= ~CMS_STREAM;
break;
case OPT_CRLFEOL:
mime_eol = "\r\n";
flags |= CMS_CRLFEOL;
break;
case OPT_NOOUT:
noout = 1;
break;
case OPT_RR_PRINT:
rr_print = 1;
break;
case OPT_RR_ALL:
rr_allorfirst = 0;
break;
case OPT_RR_FIRST:
rr_allorfirst = 1;
break;
case OPT_RCTFORM:
if (rctformat == FORMAT_SMIME)
rcms = SMIME_read_CMS(rctin, NULL);
else if (rctformat == FORMAT_PEM)
rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
else if (rctformat == FORMAT_ASN1)
if (!opt_format(opt_arg(),
OPT_FMT_PEMDER | OPT_FMT_SMIME, &rctformat))
goto opthelp;
break;
case OPT_CERTFILE:
certfile = opt_arg();
break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_CAPATH:
CApath = opt_arg();
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_CONTENT:
contfile = opt_arg();
break;
case OPT_RR_FROM:
if (rr_from == NULL
&& (rr_from = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
sk_OPENSSL_STRING_push(rr_from, opt_arg());
break;
case OPT_RR_TO:
if (rr_to == NULL
&& (rr_to = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
sk_OPENSSL_STRING_push(rr_to, opt_arg());
break;
case OPT_PRINT:
noout = print = 1;
break;
case OPT_SECRETKEY:
if (secret_key != NULL) {
BIO_printf(bio_err, "Invalid key (supplied twice) %s\n",
opt_arg());
goto opthelp;
}
secret_key = OPENSSL_hexstr2buf(opt_arg(), &ltmp);
if (secret_key == NULL) {
BIO_printf(bio_err, "Invalid key %s\n", opt_arg());
goto end;
}
secret_keylen = (size_t)ltmp;
break;
case OPT_SECRETKEYID:
if (secret_keyid != NULL) {
BIO_printf(bio_err, "Invalid id (supplied twice) %s\n",
opt_arg());
goto opthelp;
}
secret_keyid = OPENSSL_hexstr2buf(opt_arg(), &ltmp);
if (secret_keyid == NULL) {
BIO_printf(bio_err, "Invalid id %s\n", opt_arg());
goto opthelp;
}
secret_keyidlen = (size_t)ltmp;
break;
case OPT_PWRI_PASSWORD:
pwri_pass = (unsigned char *)opt_arg();
break;
case OPT_ECONTENT_TYPE:
if (econtent_type != NULL) {
BIO_printf(bio_err, "Invalid OID (supplied twice) %s\n",
opt_arg());
goto opthelp;
}
econtent_type = OBJ_txt2obj(opt_arg(), 0);
if (econtent_type == NULL) {
BIO_printf(bio_err, "Invalid OID %s\n", opt_arg());
goto opthelp;
}
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_PASSIN:
passinarg = opt_arg();
break;
case OPT_TO:
to = opt_arg();
break;
case OPT_FROM:
from = opt_arg();
break;
case OPT_SUBJECT:
subject = opt_arg();
break;
case OPT_CERTSOUT:
certsoutfile = opt_arg();
break;
case OPT_MD:
if (!opt_md(opt_arg(), &sign_md))
goto end;
break;
case OPT_SIGNER:
/* If previous -signer argument add signer to list */
if (signerfile != NULL) {
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
sk_OPENSSL_STRING_push(sksigners, signerfile);
if (keyfile == NULL)
keyfile = signerfile;
if (skkeys == NULL
&& (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
sk_OPENSSL_STRING_push(skkeys, keyfile);
keyfile = NULL;
}
signerfile = opt_arg();
break;
case OPT_INKEY:
/* If previous -inkey argument add signer to list */
if (keyfile != NULL) {
if (signerfile == NULL) {
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
goto end;
}
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
sk_OPENSSL_STRING_push(sksigners, signerfile);
signerfile = NULL;
if (skkeys == NULL
&& (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
sk_OPENSSL_STRING_push(skkeys, keyfile);
}
keyfile = opt_arg();
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_ANY, &keyform))
goto opthelp;
break;
case OPT_RECIP:
if (operation == SMIME_ENCRYPT) {
if (encerts == NULL && (encerts = sk_X509_new_null()) == NULL)
goto end;
cert = load_cert(opt_arg(), FORMAT_PEM,
"recipient certificate file");
if (cert == NULL)
goto end;
sk_X509_push(encerts, cert);
cert = NULL;
} else {
recipfile = opt_arg();
}
break;
case OPT_CIPHER:
if (!opt_cipher(opt_unknown(), &cipher))
goto end;
break;
case OPT_KEYOPT:
keyidx = -1;
if (operation == SMIME_ENCRYPT) {
if (encerts != NULL)
keyidx += sk_X509_num(encerts);
} else {
if (keyfile != NULL || signerfile != NULL)
keyidx++;
if (skkeys != NULL)
keyidx += sk_OPENSSL_STRING_num(skkeys);
}
if (keyidx < 0) {
BIO_printf(bio_err, "No key specified\n");
goto opthelp;
}
if (key_param == NULL || key_param->idx != keyidx) {
cms_key_param *nparam;
nparam = app_malloc(sizeof(*nparam), "key param buffer");
nparam->idx = keyidx;
if ((nparam->param = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
nparam->next = NULL;
if (key_first == NULL)
key_first = nparam;
else
key_param->next = nparam;
key_param = nparam;
}
sk_OPENSSL_STRING_push(key_param->param, opt_arg());
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto end;
vpmtouched++;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_3DES_WRAP:
# ifndef OPENSSL_NO_DES
wrap_cipher = EVP_des_ede3_wrap();
# endif
break;
case OPT_AES128_WRAP:
wrap_cipher = EVP_aes_128_wrap();
break;
case OPT_AES192_WRAP:
wrap_cipher = EVP_aes_192_wrap();
break;
case OPT_AES256_WRAP:
wrap_cipher = EVP_aes_256_wrap();
break;
}
}
argc = opt_num_rest();
argv = opt_rest();
if ((rr_allorfirst != -1 || rr_from != NULL) && rr_to == NULL) {
BIO_puts(bio_err, "No Signed Receipts Recipients\n");
goto opthelp;
}
if (!(operation & SMIME_SIGNERS) && (rr_to != NULL || rr_from != NULL)) {
BIO_puts(bio_err, "Signed receipts only allowed with -sign\n");
goto opthelp;
}
if (!(operation & SMIME_SIGNERS) && (skkeys != NULL || sksigners != NULL)) {
BIO_puts(bio_err, "Multiple signers or keys not allowed\n");
goto opthelp;
}
if (operation & SMIME_SIGNERS) {
if (keyfile != NULL && signerfile == NULL) {
BIO_puts(bio_err, "Illegal -inkey without -signer\n");
goto opthelp;
}
/* Check to see if any final signer needs to be appended */
if (signerfile != NULL) {
if (sksigners == NULL
&& (sksigners = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
sk_OPENSSL_STRING_push(sksigners, signerfile);
if (skkeys == NULL && (skkeys = sk_OPENSSL_STRING_new_null()) == NULL)
goto end;
if (keyfile == NULL)
keyfile = signerfile;
sk_OPENSSL_STRING_push(skkeys, keyfile);
}
if (sksigners == NULL) {
BIO_printf(bio_err, "No signer certificate specified\n");
goto opthelp;
}
signerfile = NULL;
keyfile = NULL;
} else if (operation == SMIME_DECRYPT) {
if (recipfile == NULL && keyfile == NULL
&& secret_key == NULL && pwri_pass == NULL) {
BIO_printf(bio_err,
"No recipient certificate or key specified\n");
goto opthelp;
}
} else if (operation == SMIME_ENCRYPT) {
if (*argv == NULL && secret_key == NULL
&& pwri_pass == NULL && encerts == NULL) {
BIO_printf(bio_err, "No recipient(s) certificate(s) specified\n");
goto opthelp;
}
} else if (!operation) {
+ BIO_printf(bio_err, "No operation option (-encrypt|-decrypt|-sign|-verify|...) specified.\n");
goto opthelp;
}
if (!app_passwd(passinarg, NULL, &passin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
ret = 2;
if (!(operation & SMIME_SIGNERS))
flags &= ~CMS_DETACHED;
if (!(operation & SMIME_OP))
if (flags & CMS_BINARY)
outformat = FORMAT_BINARY;
if (!(operation & SMIME_IP))
if (flags & CMS_BINARY)
informat = FORMAT_BINARY;
if (operation == SMIME_ENCRYPT) {
if (!cipher) {
# ifndef OPENSSL_NO_DES
cipher = EVP_des_ede3_cbc();
# else
BIO_printf(bio_err, "No cipher selected\n");
goto end;
# endif
}
if (secret_key && !secret_keyid) {
BIO_printf(bio_err, "No secret key id\n");
goto end;
}
if (*argv && encerts == NULL)
if ((encerts = sk_X509_new_null()) == NULL)
goto end;
while (*argv) {
if ((cert = load_cert(*argv, FORMAT_PEM,
"recipient certificate file")) == NULL)
goto end;
sk_X509_push(encerts, cert);
cert = NULL;
argv++;
}
}
if (certfile != NULL) {
if (!load_certs(certfile, &other, FORMAT_PEM, NULL,
"certificate file")) {
ERR_print_errors(bio_err);
goto end;
}
}
if (recipfile != NULL && (operation == SMIME_DECRYPT)) {
if ((recip = load_cert(recipfile, FORMAT_PEM,
"recipient certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (operation == SMIME_SIGN_RECEIPT) {
if ((signer = load_cert(signerfile, FORMAT_PEM,
"receipt signer certificate file")) == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (operation == SMIME_DECRYPT) {
if (keyfile == NULL)
keyfile = recipfile;
} else if ((operation == SMIME_SIGN) || (operation == SMIME_SIGN_RECEIPT)) {
if (keyfile == NULL)
keyfile = signerfile;
} else {
keyfile = NULL;
}
if (keyfile != NULL) {
key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
if (key == NULL)
goto end;
}
in = bio_open_default(infile, 'r', informat);
if (in == NULL)
goto end;
if (operation & SMIME_IP) {
if (informat == FORMAT_SMIME) {
cms = SMIME_read_CMS(in, &indata);
} else if (informat == FORMAT_PEM) {
cms = PEM_read_bio_CMS(in, NULL, NULL, NULL);
} else if (informat == FORMAT_ASN1) {
cms = d2i_CMS_bio(in, NULL);
} else {
BIO_printf(bio_err, "Bad input format for CMS file\n");
goto end;
}
if (cms == NULL) {
BIO_printf(bio_err, "Error reading S/MIME message\n");
goto end;
}
if (contfile != NULL) {
BIO_free(indata);
if ((indata = BIO_new_file(contfile, "rb")) == NULL) {
BIO_printf(bio_err, "Can't read content file %s\n", contfile);
goto end;
}
}
if (certsoutfile != NULL) {
STACK_OF(X509) *allcerts;
allcerts = CMS_get1_certs(cms);
if (!save_certs(certsoutfile, allcerts)) {
BIO_printf(bio_err,
"Error writing certs to %s\n", certsoutfile);
ret = 5;
goto end;
}
sk_X509_pop_free(allcerts, X509_free);
}
}
if (rctfile != NULL) {
char *rctmode = (rctformat == FORMAT_ASN1) ? "rb" : "r";
if ((rctin = BIO_new_file(rctfile, rctmode)) == NULL) {
BIO_printf(bio_err, "Can't open receipt file %s\n", rctfile);
goto end;
}
if (rctformat == FORMAT_SMIME) {
rcms = SMIME_read_CMS(rctin, NULL);
} else if (rctformat == FORMAT_PEM) {
rcms = PEM_read_bio_CMS(rctin, NULL, NULL, NULL);
} else if (rctformat == FORMAT_ASN1) {
rcms = d2i_CMS_bio(rctin, NULL);
} else {
BIO_printf(bio_err, "Bad input format for receipt\n");
goto end;
}
if (rcms == NULL) {
BIO_printf(bio_err, "Error reading receipt\n");
goto end;
}
}
out = bio_open_default(outfile, 'w', outformat);
if (out == NULL)
goto end;
if ((operation == SMIME_VERIFY) || (operation == SMIME_VERIFY_RECEIPT)) {
if ((store = setup_verify(CAfile, CApath, noCAfile, noCApath)) == NULL)
goto end;
X509_STORE_set_verify_cb(store, cms_cb);
if (vpmtouched)
X509_STORE_set1_param(store, vpm);
}
ret = 3;
if (operation == SMIME_DATA_CREATE) {
cms = CMS_data_create(in, flags);
} else if (operation == SMIME_DIGEST_CREATE) {
cms = CMS_digest_create(in, sign_md, flags);
} else if (operation == SMIME_COMPRESS) {
cms = CMS_compress(in, -1, flags);
} else if (operation == SMIME_ENCRYPT) {
int i;
flags |= CMS_PARTIAL;
cms = CMS_encrypt(NULL, in, cipher, flags);
if (cms == NULL)
goto end;
for (i = 0; i < sk_X509_num(encerts); i++) {
CMS_RecipientInfo *ri;
cms_key_param *kparam;
int tflags = flags;
X509 *x = sk_X509_value(encerts, i);
for (kparam = key_first; kparam; kparam = kparam->next) {
if (kparam->idx == i) {
tflags |= CMS_KEY_PARAM;
break;
}
}
ri = CMS_add1_recipient_cert(cms, x, tflags);
if (ri == NULL)
goto end;
if (kparam != NULL) {
EVP_PKEY_CTX *pctx;
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (!cms_set_pkey_param(pctx, kparam->param))
goto end;
}
if (CMS_RecipientInfo_type(ri) == CMS_RECIPINFO_AGREE
&& wrap_cipher) {
EVP_CIPHER_CTX *wctx;
wctx = CMS_RecipientInfo_kari_get0_ctx(ri);
EVP_EncryptInit_ex(wctx, wrap_cipher, NULL, NULL, NULL);
}
}
if (secret_key != NULL) {
if (!CMS_add0_recipient_key(cms, NID_undef,
secret_key, secret_keylen,
secret_keyid, secret_keyidlen,
NULL, NULL, NULL))
goto end;
/* NULL these because call absorbs them */
secret_key = NULL;
secret_keyid = NULL;
}
if (pwri_pass != NULL) {
pwri_tmp = (unsigned char *)OPENSSL_strdup((char *)pwri_pass);
if (pwri_tmp == NULL)
goto end;
if (CMS_add0_recipient_password(cms,
-1, NID_undef, NID_undef,
pwri_tmp, -1, NULL) == NULL)
goto end;
pwri_tmp = NULL;
}
if (!(flags & CMS_STREAM)) {
if (!CMS_final(cms, in, NULL, flags))
goto end;
}
} else if (operation == SMIME_ENCRYPTED_ENCRYPT) {
cms = CMS_EncryptedData_encrypt(in, cipher,
secret_key, secret_keylen, flags);
} else if (operation == SMIME_SIGN_RECEIPT) {
CMS_ContentInfo *srcms = NULL;
STACK_OF(CMS_SignerInfo) *sis;
CMS_SignerInfo *si;
sis = CMS_get0_SignerInfos(cms);
if (sis == NULL)
goto end;
si = sk_CMS_SignerInfo_value(sis, 0);
srcms = CMS_sign_receipt(si, signer, key, other, flags);
if (srcms == NULL)
goto end;
CMS_ContentInfo_free(cms);
cms = srcms;
} else if (operation & SMIME_SIGNERS) {
int i;
/*
* If detached data content we enable streaming if S/MIME output
* format.
*/
if (operation == SMIME_SIGN) {
if (flags & CMS_DETACHED) {
if (outformat == FORMAT_SMIME)
flags |= CMS_STREAM;
}
flags |= CMS_PARTIAL;
cms = CMS_sign(NULL, NULL, other, in, flags);
if (cms == NULL)
goto end;
if (econtent_type != NULL)
CMS_set1_eContentType(cms, econtent_type);
if (rr_to != NULL) {
rr = make_receipt_request(rr_to, rr_allorfirst, rr_from);
if (rr == NULL) {
BIO_puts(bio_err,
"Signed Receipt Request Creation Error\n");
goto end;
}
}
} else {
flags |= CMS_REUSE_DIGEST;
}
for (i = 0; i < sk_OPENSSL_STRING_num(sksigners); i++) {
CMS_SignerInfo *si;
cms_key_param *kparam;
int tflags = flags;
signerfile = sk_OPENSSL_STRING_value(sksigners, i);
keyfile = sk_OPENSSL_STRING_value(skkeys, i);
signer = load_cert(signerfile, FORMAT_PEM, "signer certificate");
if (signer == NULL) {
ret = 2;
goto end;
}
key = load_key(keyfile, keyform, 0, passin, e, "signing key file");
if (key == NULL) {
ret = 2;
goto end;
}
for (kparam = key_first; kparam; kparam = kparam->next) {
if (kparam->idx == i) {
tflags |= CMS_KEY_PARAM;
break;
}
}
si = CMS_add1_signer(cms, signer, key, sign_md, tflags);
if (si == NULL)
goto end;
if (kparam != NULL) {
EVP_PKEY_CTX *pctx;
pctx = CMS_SignerInfo_get0_pkey_ctx(si);
if (!cms_set_pkey_param(pctx, kparam->param))
goto end;
}
if (rr != NULL && !CMS_add1_ReceiptRequest(si, rr))
goto end;
X509_free(signer);
signer = NULL;
EVP_PKEY_free(key);
key = NULL;
}
/* If not streaming or resigning finalize structure */
if ((operation == SMIME_SIGN) && !(flags & CMS_STREAM)) {
if (!CMS_final(cms, in, NULL, flags))
goto end;
}
}
if (cms == NULL) {
BIO_printf(bio_err, "Error creating CMS structure\n");
goto end;
}
ret = 4;
if (operation == SMIME_DECRYPT) {
if (flags & CMS_DEBUG_DECRYPT)
CMS_decrypt(cms, NULL, NULL, NULL, NULL, flags);
if (secret_key != NULL) {
if (!CMS_decrypt_set1_key(cms,
secret_key, secret_keylen,
secret_keyid, secret_keyidlen)) {
BIO_puts(bio_err, "Error decrypting CMS using secret key\n");
goto end;
}
}
if (key != NULL) {
if (!CMS_decrypt_set1_pkey(cms, key, recip)) {
BIO_puts(bio_err, "Error decrypting CMS using private key\n");
goto end;
}
}
if (pwri_pass != NULL) {
if (!CMS_decrypt_set1_password(cms, pwri_pass, -1)) {
BIO_puts(bio_err, "Error decrypting CMS using password\n");
goto end;
}
}
if (!CMS_decrypt(cms, NULL, NULL, indata, out, flags)) {
BIO_printf(bio_err, "Error decrypting CMS structure\n");
goto end;
}
} else if (operation == SMIME_DATAOUT) {
if (!CMS_data(cms, out, flags))
goto end;
} else if (operation == SMIME_UNCOMPRESS) {
if (!CMS_uncompress(cms, indata, out, flags))
goto end;
} else if (operation == SMIME_DIGEST_VERIFY) {
if (CMS_digest_verify(cms, indata, out, flags) > 0) {
BIO_printf(bio_err, "Verification successful\n");
} else {
BIO_printf(bio_err, "Verification failure\n");
goto end;
}
} else if (operation == SMIME_ENCRYPTED_DECRYPT) {
if (!CMS_EncryptedData_decrypt(cms, secret_key, secret_keylen,
indata, out, flags))
goto end;
} else if (operation == SMIME_VERIFY) {
if (CMS_verify(cms, other, store, indata, out, flags) > 0) {
BIO_printf(bio_err, "Verification successful\n");
} else {
BIO_printf(bio_err, "Verification failure\n");
if (verify_retcode)
ret = verify_err + 32;
goto end;
}
if (signerfile != NULL) {
STACK_OF(X509) *signers;
signers = CMS_get0_signers(cms);
if (!save_certs(signerfile, signers)) {
BIO_printf(bio_err,
"Error writing signers to %s\n", signerfile);
ret = 5;
goto end;
}
sk_X509_free(signers);
}
if (rr_print)
receipt_request_print(cms);
} else if (operation == SMIME_VERIFY_RECEIPT) {
if (CMS_verify_receipt(rcms, cms, other, store, flags) > 0) {
BIO_printf(bio_err, "Verification successful\n");
} else {
BIO_printf(bio_err, "Verification failure\n");
goto end;
}
} else {
if (noout) {
if (print)
CMS_ContentInfo_print_ctx(out, cms, 0, NULL);
} else if (outformat == FORMAT_SMIME) {
if (to)
BIO_printf(out, "To: %s%s", to, mime_eol);
if (from)
BIO_printf(out, "From: %s%s", from, mime_eol);
if (subject)
BIO_printf(out, "Subject: %s%s", subject, mime_eol);
if (operation == SMIME_RESIGN)
ret = SMIME_write_CMS(out, cms, indata, flags);
else
ret = SMIME_write_CMS(out, cms, in, flags);
} else if (outformat == FORMAT_PEM) {
ret = PEM_write_bio_CMS_stream(out, cms, in, flags);
} else if (outformat == FORMAT_ASN1) {
ret = i2d_CMS_bio_stream(out, cms, in, flags);
} else {
BIO_printf(bio_err, "Bad output format for CMS file\n");
goto end;
}
if (ret <= 0) {
ret = 6;
goto end;
}
}
ret = 0;
end:
if (ret)
ERR_print_errors(bio_err);
sk_X509_pop_free(encerts, X509_free);
sk_X509_pop_free(other, X509_free);
X509_VERIFY_PARAM_free(vpm);
sk_OPENSSL_STRING_free(sksigners);
sk_OPENSSL_STRING_free(skkeys);
OPENSSL_free(secret_key);
OPENSSL_free(secret_keyid);
OPENSSL_free(pwri_tmp);
ASN1_OBJECT_free(econtent_type);
CMS_ReceiptRequest_free(rr);
sk_OPENSSL_STRING_free(rr_to);
sk_OPENSSL_STRING_free(rr_from);
for (key_param = key_first; key_param;) {
cms_key_param *tparam;
sk_OPENSSL_STRING_free(key_param->param);
tparam = key_param->next;
OPENSSL_free(key_param);
key_param = tparam;
}
X509_STORE_free(store);
X509_free(cert);
X509_free(recip);
X509_free(signer);
EVP_PKEY_free(key);
CMS_ContentInfo_free(cms);
CMS_ContentInfo_free(rcms);
release_engine(e);
BIO_free(rctin);
BIO_free(in);
BIO_free(indata);
BIO_free_all(out);
OPENSSL_free(passin);
return ret;
}
static int save_certs(char *signerfile, STACK_OF(X509) *signers)
{
int i;
BIO *tmp;
if (signerfile == NULL)
return 1;
tmp = BIO_new_file(signerfile, "w");
if (tmp == NULL)
return 0;
for (i = 0; i < sk_X509_num(signers); i++)
PEM_write_bio_X509(tmp, sk_X509_value(signers, i));
BIO_free(tmp);
return 1;
}
/* Minimal callback just to output policy info (if any) */
static int cms_cb(int ok, X509_STORE_CTX *ctx)
{
int error;
error = X509_STORE_CTX_get_error(ctx);
verify_err = error;
if ((error != X509_V_ERR_NO_EXPLICIT_POLICY)
&& ((error != X509_V_OK) || (ok != 2)))
return ok;
policies_print(ctx);
return ok;
}
static void gnames_stack_print(STACK_OF(GENERAL_NAMES) *gns)
{
STACK_OF(GENERAL_NAME) *gens;
GENERAL_NAME *gen;
int i, j;
for (i = 0; i < sk_GENERAL_NAMES_num(gns); i++) {
gens = sk_GENERAL_NAMES_value(gns, i);
for (j = 0; j < sk_GENERAL_NAME_num(gens); j++) {
gen = sk_GENERAL_NAME_value(gens, j);
BIO_puts(bio_err, " ");
GENERAL_NAME_print(bio_err, gen);
BIO_puts(bio_err, "\n");
}
}
return;
}
static void receipt_request_print(CMS_ContentInfo *cms)
{
STACK_OF(CMS_SignerInfo) *sis;
CMS_SignerInfo *si;
CMS_ReceiptRequest *rr;
int allorfirst;
STACK_OF(GENERAL_NAMES) *rto, *rlist;
ASN1_STRING *scid;
int i, rv;
sis = CMS_get0_SignerInfos(cms);
for (i = 0; i < sk_CMS_SignerInfo_num(sis); i++) {
si = sk_CMS_SignerInfo_value(sis, i);
rv = CMS_get1_ReceiptRequest(si, &rr);
BIO_printf(bio_err, "Signer %d:\n", i + 1);
if (rv == 0) {
BIO_puts(bio_err, " No Receipt Request\n");
} else if (rv < 0) {
BIO_puts(bio_err, " Receipt Request Parse Error\n");
ERR_print_errors(bio_err);
} else {
const char *id;
int idlen;
CMS_ReceiptRequest_get0_values(rr, &scid, &allorfirst,
&rlist, &rto);
BIO_puts(bio_err, " Signed Content ID:\n");
idlen = ASN1_STRING_length(scid);
id = (const char *)ASN1_STRING_get0_data(scid);
BIO_dump_indent(bio_err, id, idlen, 4);
BIO_puts(bio_err, " Receipts From");
if (rlist != NULL) {
BIO_puts(bio_err, " List:\n");
gnames_stack_print(rlist);
} else if (allorfirst == 1) {
BIO_puts(bio_err, ": First Tier\n");
} else if (allorfirst == 0) {
BIO_puts(bio_err, ": All\n");
} else {
BIO_printf(bio_err, " Unknown (%d)\n", allorfirst);
}
BIO_puts(bio_err, " Receipts To:\n");
gnames_stack_print(rto);
}
CMS_ReceiptRequest_free(rr);
}
}
static STACK_OF(GENERAL_NAMES) *make_names_stack(STACK_OF(OPENSSL_STRING) *ns)
{
int i;
STACK_OF(GENERAL_NAMES) *ret;
GENERAL_NAMES *gens = NULL;
GENERAL_NAME *gen = NULL;
ret = sk_GENERAL_NAMES_new_null();
if (ret == NULL)
goto err;
for (i = 0; i < sk_OPENSSL_STRING_num(ns); i++) {
char *str = sk_OPENSSL_STRING_value(ns, i);
gen = a2i_GENERAL_NAME(NULL, NULL, NULL, GEN_EMAIL, str, 0);
if (gen == NULL)
goto err;
gens = GENERAL_NAMES_new();
if (gens == NULL)
goto err;
if (!sk_GENERAL_NAME_push(gens, gen))
goto err;
gen = NULL;
if (!sk_GENERAL_NAMES_push(ret, gens))
goto err;
gens = NULL;
}
return ret;
err:
sk_GENERAL_NAMES_pop_free(ret, GENERAL_NAMES_free);
GENERAL_NAMES_free(gens);
GENERAL_NAME_free(gen);
return NULL;
}
static CMS_ReceiptRequest *make_receipt_request(STACK_OF(OPENSSL_STRING)
*rr_to, int rr_allorfirst, STACK_OF(OPENSSL_STRING)
*rr_from)
{
STACK_OF(GENERAL_NAMES) *rct_to = NULL, *rct_from = NULL;
CMS_ReceiptRequest *rr;
rct_to = make_names_stack(rr_to);
if (rct_to == NULL)
goto err;
if (rr_from != NULL) {
rct_from = make_names_stack(rr_from);
if (rct_from == NULL)
goto err;
} else {
rct_from = NULL;
}
rr = CMS_ReceiptRequest_create0(NULL, -1, rr_allorfirst, rct_from,
rct_to);
return rr;
err:
sk_GENERAL_NAMES_pop_free(rct_to, GENERAL_NAMES_free);
return NULL;
}
static int cms_set_pkey_param(EVP_PKEY_CTX *pctx,
STACK_OF(OPENSSL_STRING) *param)
{
char *keyopt;
int i;
if (sk_OPENSSL_STRING_num(param) <= 0)
return 1;
for (i = 0; i < sk_OPENSSL_STRING_num(param); i++) {
keyopt = sk_OPENSSL_STRING_value(param, i);
if (pkey_ctrl_string(pctx, keyopt) <= 0) {
BIO_printf(bio_err, "parameter error \"%s\"\n", keyopt);
ERR_print_errors(bio_err);
return 0;
}
}
return 1;
}
#endif
diff --git a/apps/enc.c b/apps/enc.c
index 8e5a57d3e5d7..de33e57a5f49 100644
--- a/apps/enc.c
+++ b/apps/enc.c
@@ -1,675 +1,675 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "apps.h"
#include "progs.h"
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/rand.h>
#include <openssl/pem.h>
#ifndef OPENSSL_NO_COMP
# include <openssl/comp.h>
#endif
#include <ctype.h>
#undef SIZE
#undef BSIZE
#define SIZE (512)
#define BSIZE (8*1024)
static int set_hex(const char *in, unsigned char *out, int size);
static void show_ciphers(const OBJ_NAME *name, void *bio_);
struct doall_enc_ciphers {
BIO *bio;
int n;
};
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_LIST,
OPT_E, OPT_IN, OPT_OUT, OPT_PASS, OPT_ENGINE, OPT_D, OPT_P, OPT_V,
OPT_NOPAD, OPT_SALT, OPT_NOSALT, OPT_DEBUG, OPT_UPPER_P, OPT_UPPER_A,
OPT_A, OPT_Z, OPT_BUFSIZE, OPT_K, OPT_KFILE, OPT_UPPER_K, OPT_NONE,
OPT_UPPER_S, OPT_IV, OPT_MD, OPT_ITER, OPT_PBKDF2, OPT_CIPHER,
OPT_R_ENUM
} OPTION_CHOICE;
const OPTIONS enc_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"ciphers", OPT_LIST, '-', "List ciphers"},
{"in", OPT_IN, '<', "Input file"},
{"out", OPT_OUT, '>', "Output file"},
{"pass", OPT_PASS, 's', "Passphrase source"},
{"e", OPT_E, '-', "Encrypt"},
{"d", OPT_D, '-', "Decrypt"},
{"p", OPT_P, '-', "Print the iv/key"},
{"P", OPT_UPPER_P, '-', "Print the iv/key and exit"},
{"v", OPT_V, '-', "Verbose output"},
{"nopad", OPT_NOPAD, '-', "Disable standard block padding"},
{"salt", OPT_SALT, '-', "Use salt in the KDF (default)"},
{"nosalt", OPT_NOSALT, '-', "Do not use salt in the KDF"},
{"debug", OPT_DEBUG, '-', "Print debug info"},
{"a", OPT_A, '-', "Base64 encode/decode, depending on encryption flag"},
{"base64", OPT_A, '-', "Same as option -a"},
{"A", OPT_UPPER_A, '-',
"Used with -[base64|a] to specify base64 buffer as a single line"},
{"bufsize", OPT_BUFSIZE, 's', "Buffer size"},
{"k", OPT_K, 's', "Passphrase"},
{"kfile", OPT_KFILE, '<', "Read passphrase from file"},
{"K", OPT_UPPER_K, 's', "Raw key, in hex"},
{"S", OPT_UPPER_S, 's', "Salt, in hex"},
{"iv", OPT_IV, 's', "IV in hex"},
{"md", OPT_MD, 's', "Use specified digest to create a key from the passphrase"},
{"iter", OPT_ITER, 'p', "Specify the iteration count and force use of PBKDF2"},
{"pbkdf2", OPT_PBKDF2, '-', "Use password-based key derivation function 2"},
{"none", OPT_NONE, '-', "Don't encrypt"},
{"", OPT_CIPHER, '-', "Any supported cipher"},
OPT_R_OPTIONS,
#ifdef ZLIB
{"z", OPT_Z, '-', "Use zlib as the 'encryption'"},
#endif
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{NULL}
};
int enc_main(int argc, char **argv)
{
static char buf[128];
static const char magic[] = "Salted__";
ENGINE *e = NULL;
BIO *in = NULL, *out = NULL, *b64 = NULL, *benc = NULL, *rbio =
NULL, *wbio = NULL;
EVP_CIPHER_CTX *ctx = NULL;
const EVP_CIPHER *cipher = NULL, *c;
const EVP_MD *dgst = NULL;
char *hkey = NULL, *hiv = NULL, *hsalt = NULL, *p;
char *infile = NULL, *outfile = NULL, *prog;
char *str = NULL, *passarg = NULL, *pass = NULL, *strbuf = NULL;
char mbuf[sizeof(magic) - 1];
OPTION_CHOICE o;
int bsize = BSIZE, verbose = 0, debug = 0, olb64 = 0, nosalt = 0;
int enc = 1, printkey = 0, i, k;
int base64 = 0, informat = FORMAT_BINARY, outformat = FORMAT_BINARY;
int ret = 1, inl, nopad = 0;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
unsigned char *buff = NULL, salt[PKCS5_SALT_LEN];
int pbkdf2 = 0;
int iter = 0;
long n;
struct doall_enc_ciphers dec;
#ifdef ZLIB
int do_zlib = 0;
BIO *bzl = NULL;
#endif
/* first check the program name */
prog = opt_progname(argv[0]);
if (strcmp(prog, "base64") == 0) {
base64 = 1;
#ifdef ZLIB
} else if (strcmp(prog, "zlib") == 0) {
do_zlib = 1;
#endif
} else {
cipher = EVP_get_cipherbyname(prog);
if (cipher == NULL && strcmp(prog, "enc") != 0) {
BIO_printf(bio_err, "%s is not a known cipher\n", prog);
goto end;
}
}
prog = opt_init(argc, argv, enc_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(enc_options);
ret = 0;
goto end;
case OPT_LIST:
BIO_printf(bio_out, "Supported ciphers:\n");
dec.bio = bio_out;
dec.n = 0;
OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_CIPHER_METH,
show_ciphers, &dec);
BIO_printf(bio_out, "\n");
ret = 0;
goto end;
case OPT_E:
enc = 1;
break;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_PASS:
passarg = opt_arg();
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 0);
break;
case OPT_D:
enc = 0;
break;
case OPT_P:
printkey = 1;
break;
case OPT_V:
verbose = 1;
break;
case OPT_NOPAD:
nopad = 1;
break;
case OPT_SALT:
nosalt = 0;
break;
case OPT_NOSALT:
nosalt = 1;
break;
case OPT_DEBUG:
debug = 1;
break;
case OPT_UPPER_P:
printkey = 2;
break;
case OPT_UPPER_A:
olb64 = 1;
break;
case OPT_A:
base64 = 1;
break;
case OPT_Z:
#ifdef ZLIB
do_zlib = 1;
#endif
break;
case OPT_BUFSIZE:
p = opt_arg();
i = (int)strlen(p) - 1;
k = i >= 1 && p[i] == 'k';
if (k)
p[i] = '\0';
if (!opt_long(opt_arg(), &n)
|| n < 0 || (k && n >= LONG_MAX / 1024))
goto opthelp;
if (k)
n *= 1024;
bsize = (int)n;
break;
case OPT_K:
str = opt_arg();
break;
case OPT_KFILE:
in = bio_open_default(opt_arg(), 'r', FORMAT_TEXT);
if (in == NULL)
goto opthelp;
i = BIO_gets(in, buf, sizeof(buf));
BIO_free(in);
in = NULL;
if (i <= 0) {
BIO_printf(bio_err,
"%s Can't read key from %s\n", prog, opt_arg());
goto opthelp;
}
while (--i > 0 && (buf[i] == '\r' || buf[i] == '\n'))
buf[i] = '\0';
if (i <= 0) {
BIO_printf(bio_err, "%s: zero length password\n", prog);
goto opthelp;
}
str = buf;
break;
case OPT_UPPER_K:
hkey = opt_arg();
break;
case OPT_UPPER_S:
hsalt = opt_arg();
break;
case OPT_IV:
hiv = opt_arg();
break;
case OPT_MD:
if (!opt_md(opt_arg(), &dgst))
goto opthelp;
break;
case OPT_CIPHER:
if (!opt_cipher(opt_unknown(), &c))
goto opthelp;
cipher = c;
break;
case OPT_ITER:
if (!opt_int(opt_arg(), &iter))
goto opthelp;
pbkdf2 = 1;
break;
case OPT_PBKDF2:
pbkdf2 = 1;
if (iter == 0) /* do not overwrite a chosen value */
iter = 10000;
break;
case OPT_NONE:
cipher = NULL;
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
}
}
if (opt_num_rest() != 0) {
BIO_printf(bio_err, "Extra arguments given.\n");
goto opthelp;
}
if (cipher && EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) {
BIO_printf(bio_err, "%s: AEAD ciphers not supported\n", prog);
goto end;
}
if (cipher && (EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)) {
BIO_printf(bio_err, "%s XTS ciphers not supported\n", prog);
goto end;
}
if (dgst == NULL)
dgst = EVP_sha256();
if (iter == 0)
iter = 1;
/* It must be large enough for a base64 encoded line */
if (base64 && bsize < 80)
bsize = 80;
if (verbose)
BIO_printf(bio_err, "bufsize=%d\n", bsize);
#ifdef ZLIB
if (!do_zlib)
#endif
if (base64) {
if (enc)
outformat = FORMAT_BASE64;
else
informat = FORMAT_BASE64;
}
strbuf = app_malloc(SIZE, "strbuf");
buff = app_malloc(EVP_ENCODE_LENGTH(bsize), "evp buffer");
if (infile == NULL) {
in = dup_bio_in(informat);
} else {
in = bio_open_default(infile, 'r', informat);
}
if (in == NULL)
goto end;
if (str == NULL && passarg != NULL) {
if (!app_passwd(passarg, NULL, &pass, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
str = pass;
}
if ((str == NULL) && (cipher != NULL) && (hkey == NULL)) {
if (1) {
#ifndef OPENSSL_NO_UI_CONSOLE
for (;;) {
char prompt[200];
BIO_snprintf(prompt, sizeof(prompt), "enter %s %s password:",
OBJ_nid2ln(EVP_CIPHER_nid(cipher)),
(enc) ? "encryption" : "decryption");
strbuf[0] = '\0';
i = EVP_read_pw_string((char *)strbuf, SIZE, prompt, enc);
if (i == 0) {
if (strbuf[0] == '\0') {
ret = 1;
goto end;
}
str = strbuf;
break;
}
if (i < 0) {
BIO_printf(bio_err, "bad password read\n");
goto end;
}
}
} else {
#endif
BIO_printf(bio_err, "password required\n");
goto end;
}
}
out = bio_open_default(outfile, 'w', outformat);
if (out == NULL)
goto end;
if (debug) {
BIO_set_callback(in, BIO_debug_callback);
BIO_set_callback(out, BIO_debug_callback);
BIO_set_callback_arg(in, (char *)bio_err);
BIO_set_callback_arg(out, (char *)bio_err);
}
rbio = in;
wbio = out;
#ifdef ZLIB
if (do_zlib) {
if ((bzl = BIO_new(BIO_f_zlib())) == NULL)
goto end;
if (debug) {
BIO_set_callback(bzl, BIO_debug_callback);
BIO_set_callback_arg(bzl, (char *)bio_err);
}
if (enc)
wbio = BIO_push(bzl, wbio);
else
rbio = BIO_push(bzl, rbio);
}
#endif
if (base64) {
if ((b64 = BIO_new(BIO_f_base64())) == NULL)
goto end;
if (debug) {
BIO_set_callback(b64, BIO_debug_callback);
BIO_set_callback_arg(b64, (char *)bio_err);
}
if (olb64)
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
if (enc)
wbio = BIO_push(b64, wbio);
else
rbio = BIO_push(b64, rbio);
}
if (cipher != NULL) {
/*
* Note that str is NULL if a key was passed on the command line, so
* we get no salt in that case. Is this a bug?
*/
if (str != NULL) {
/*
* Salt handling: if encrypting generate a salt and write to
* output BIO. If decrypting read salt from input BIO.
*/
unsigned char *sptr;
size_t str_len = strlen(str);
if (nosalt) {
sptr = NULL;
} else {
if (enc) {
if (hsalt) {
if (!set_hex(hsalt, salt, sizeof(salt))) {
BIO_printf(bio_err, "invalid hex salt value\n");
goto end;
}
} else if (RAND_bytes(salt, sizeof(salt)) <= 0) {
goto end;
}
/*
* If -P option then don't bother writing
*/
if ((printkey != 2)
&& (BIO_write(wbio, magic,
sizeof(magic) - 1) != sizeof(magic) - 1
|| BIO_write(wbio,
(char *)salt,
sizeof(salt)) != sizeof(salt))) {
BIO_printf(bio_err, "error writing output file\n");
goto end;
}
} else if (BIO_read(rbio, mbuf, sizeof(mbuf)) != sizeof(mbuf)
|| BIO_read(rbio,
(unsigned char *)salt,
sizeof(salt)) != sizeof(salt)) {
BIO_printf(bio_err, "error reading input file\n");
goto end;
} else if (memcmp(mbuf, magic, sizeof(magic) - 1)) {
BIO_printf(bio_err, "bad magic number\n");
goto end;
}
sptr = salt;
}
if (pbkdf2 == 1) {
/*
* derive key and default iv
* concatenated into a temporary buffer
*/
unsigned char tmpkeyiv[EVP_MAX_KEY_LENGTH + EVP_MAX_IV_LENGTH];
int iklen = EVP_CIPHER_key_length(cipher);
int ivlen = EVP_CIPHER_iv_length(cipher);
/* not needed if HASH_UPDATE() is fixed : */
int islen = (sptr != NULL ? sizeof(salt) : 0);
if (!PKCS5_PBKDF2_HMAC(str, str_len, sptr, islen,
iter, dgst, iklen+ivlen, tmpkeyiv)) {
BIO_printf(bio_err, "PKCS5_PBKDF2_HMAC failed\n");
goto end;
}
/* split and move data back to global buffer */
memcpy(key, tmpkeyiv, iklen);
memcpy(iv, tmpkeyiv+iklen, ivlen);
} else {
BIO_printf(bio_err, "*** WARNING : "
"deprecated key derivation used.\n"
"Using -iter or -pbkdf2 would be better.\n");
if (!EVP_BytesToKey(cipher, dgst, sptr,
(unsigned char *)str, str_len,
1, key, iv)) {
BIO_printf(bio_err, "EVP_BytesToKey failed\n");
goto end;
}
}
/*
* zero the complete buffer or the string passed from the command
* line.
*/
if (str == strbuf)
OPENSSL_cleanse(str, SIZE);
else
OPENSSL_cleanse(str, str_len);
}
if (hiv != NULL) {
int siz = EVP_CIPHER_iv_length(cipher);
if (siz == 0) {
- BIO_printf(bio_err, "warning: iv not use by this cipher\n");
+ BIO_printf(bio_err, "warning: iv not used by this cipher\n");
} else if (!set_hex(hiv, iv, siz)) {
BIO_printf(bio_err, "invalid hex iv value\n");
goto end;
}
}
if ((hiv == NULL) && (str == NULL)
&& EVP_CIPHER_iv_length(cipher) != 0) {
/*
* No IV was explicitly set and no IV was generated.
* Hence the IV is undefined, making correct decryption impossible.
*/
BIO_printf(bio_err, "iv undefined\n");
goto end;
}
if (hkey != NULL) {
if (!set_hex(hkey, key, EVP_CIPHER_key_length(cipher))) {
BIO_printf(bio_err, "invalid hex key value\n");
goto end;
}
/* wiping secret data as we no longer need it */
OPENSSL_cleanse(hkey, strlen(hkey));
}
if ((benc = BIO_new(BIO_f_cipher())) == NULL)
goto end;
/*
* Since we may be changing parameters work on the encryption context
* rather than calling BIO_set_cipher().
*/
BIO_get_cipher_ctx(benc, &ctx);
if (!EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) {
BIO_printf(bio_err, "Error setting cipher %s\n",
EVP_CIPHER_name(cipher));
ERR_print_errors(bio_err);
goto end;
}
if (nopad)
EVP_CIPHER_CTX_set_padding(ctx, 0);
if (!EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) {
BIO_printf(bio_err, "Error setting cipher %s\n",
EVP_CIPHER_name(cipher));
ERR_print_errors(bio_err);
goto end;
}
if (debug) {
BIO_set_callback(benc, BIO_debug_callback);
BIO_set_callback_arg(benc, (char *)bio_err);
}
if (printkey) {
if (!nosalt) {
printf("salt=");
for (i = 0; i < (int)sizeof(salt); i++)
printf("%02X", salt[i]);
printf("\n");
}
if (EVP_CIPHER_key_length(cipher) > 0) {
printf("key=");
for (i = 0; i < EVP_CIPHER_key_length(cipher); i++)
printf("%02X", key[i]);
printf("\n");
}
if (EVP_CIPHER_iv_length(cipher) > 0) {
printf("iv =");
for (i = 0; i < EVP_CIPHER_iv_length(cipher); i++)
printf("%02X", iv[i]);
printf("\n");
}
if (printkey == 2) {
ret = 0;
goto end;
}
}
}
/* Only encrypt/decrypt as we write the file */
if (benc != NULL)
wbio = BIO_push(benc, wbio);
for (;;) {
inl = BIO_read(rbio, (char *)buff, bsize);
if (inl <= 0)
break;
if (BIO_write(wbio, (char *)buff, inl) != inl) {
BIO_printf(bio_err, "error writing output file\n");
goto end;
}
}
if (!BIO_flush(wbio)) {
BIO_printf(bio_err, "bad decrypt\n");
goto end;
}
ret = 0;
if (verbose) {
BIO_printf(bio_err, "bytes read : %8ju\n", BIO_number_read(in));
BIO_printf(bio_err, "bytes written: %8ju\n", BIO_number_written(out));
}
end:
ERR_print_errors(bio_err);
OPENSSL_free(strbuf);
OPENSSL_free(buff);
BIO_free(in);
BIO_free_all(out);
BIO_free(benc);
BIO_free(b64);
#ifdef ZLIB
BIO_free(bzl);
#endif
release_engine(e);
OPENSSL_free(pass);
return ret;
}
static void show_ciphers(const OBJ_NAME *name, void *arg)
{
struct doall_enc_ciphers *dec = (struct doall_enc_ciphers *)arg;
const EVP_CIPHER *cipher;
if (!islower((unsigned char)*name->name))
return;
/* Filter out ciphers that we cannot use */
cipher = EVP_get_cipherbyname(name->name);
if (cipher == NULL ||
(EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER) != 0 ||
EVP_CIPHER_mode(cipher) == EVP_CIPH_XTS_MODE)
return;
BIO_printf(dec->bio, "-%-25s", name->name);
if (++dec->n == 3) {
BIO_printf(dec->bio, "\n");
dec->n = 0;
} else
BIO_printf(dec->bio, " ");
}
static int set_hex(const char *in, unsigned char *out, int size)
{
int i, n;
unsigned char j;
i = size * 2;
n = strlen(in);
if (n > i) {
BIO_printf(bio_err, "hex string is too long, ignoring excess\n");
n = i; /* ignore exceeding part */
} else if (n < i) {
BIO_printf(bio_err, "hex string is too short, padding with zero bytes to length\n");
}
memset(out, 0, size);
for (i = 0; i < n; i++) {
j = (unsigned char)*in++;
if (!isxdigit(j)) {
BIO_printf(bio_err, "non-hex digit\n");
return 0;
}
j = (unsigned char)OPENSSL_hexchar2int(j);
if (i & 1)
out[i / 2] |= j;
else
out[i / 2] = (j << 4);
}
return 1;
}
diff --git a/apps/ocsp.c b/apps/ocsp.c
index e8aeb11cc51d..066a2e43af2b 100644
--- a/apps/ocsp.c
+++ b/apps/ocsp.c
@@ -1,1621 +1,1626 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
#ifdef OPENSSL_NO_OCSP
NON_EMPTY_TRANSLATION_UNIT
#else
# ifdef OPENSSL_SYS_VMS
# define _XOPEN_SOURCE_EXTENDED/* So fd_set and friends get properly defined
* on OpenVMS */
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
# include <ctype.h>
/* Needs to be included before the openssl headers */
# include "apps.h"
# include "progs.h"
# include "internal/sockets.h"
# include <openssl/e_os2.h>
# include <openssl/crypto.h>
# include <openssl/err.h>
# include <openssl/ssl.h>
# include <openssl/evp.h>
# include <openssl/bn.h>
# include <openssl/x509v3.h>
# include <openssl/rand.h>
#ifndef HAVE_FORK
# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS)
# define HAVE_FORK 0
# else
# define HAVE_FORK 1
# endif
#endif
#if HAVE_FORK
# undef NO_FORK
#else
# define NO_FORK
#endif
# if !defined(NO_FORK) && !defined(OPENSSL_NO_SOCK) \
&& !defined(OPENSSL_NO_POSIX_IO)
# define OCSP_DAEMON
# include <sys/types.h>
# include <sys/wait.h>
# include <syslog.h>
# include <signal.h>
# define MAXERRLEN 1000 /* limit error text sent to syslog to 1000 bytes */
# else
# undef LOG_INFO
# undef LOG_WARNING
# undef LOG_ERR
# define LOG_INFO 0
# define LOG_WARNING 1
# define LOG_ERR 2
# endif
# if defined(OPENSSL_SYS_VXWORKS)
/* not supported */
int setpgid(pid_t pid, pid_t pgid)
{
errno = ENOSYS;
return 0;
}
/* not supported */
pid_t fork(void)
{
errno = ENOSYS;
return (pid_t) -1;
}
# endif
/* Maximum leeway in validity period: default 5 minutes */
# define MAX_VALIDITY_PERIOD (5 * 60)
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
const EVP_MD *cert_id_md, X509 *issuer,
STACK_OF(OCSP_CERTID) *ids);
static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
const EVP_MD *cert_id_md, X509 *issuer,
STACK_OF(OCSP_CERTID) *ids);
static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
STACK_OF(OPENSSL_STRING) *names,
STACK_OF(OCSP_CERTID) *ids, long nsec,
long maxage);
static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req,
CA_DB *db, STACK_OF(X509) *ca, X509 *rcert,
EVP_PKEY *rkey, const EVP_MD *md,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(X509) *rother, unsigned long flags,
int nmin, int ndays, int badsig);
static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser);
static BIO *init_responder(const char *port);
static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio, int timeout);
static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp);
static void log_message(int level, const char *fmt, ...);
static char *prog;
static int multi = 0;
# ifdef OCSP_DAEMON
static int acfd = (int) INVALID_SOCKET;
static int index_changed(CA_DB *);
static void spawn_loop(void);
static int print_syslog(const char *str, size_t len, void *levPtr);
static void sock_timeout(int signum);
# endif
# ifndef OPENSSL_NO_SOCK
static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
const char *path,
const STACK_OF(CONF_VALUE) *headers,
OCSP_REQUEST *req, int req_timeout);
# endif
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_OUTFILE, OPT_TIMEOUT, OPT_URL, OPT_HOST, OPT_PORT,
OPT_IGNORE_ERR, OPT_NOVERIFY, OPT_NONCE, OPT_NO_NONCE,
OPT_RESP_NO_CERTS, OPT_RESP_KEY_ID, OPT_NO_CERTS,
OPT_NO_SIGNATURE_VERIFY, OPT_NO_CERT_VERIFY, OPT_NO_CHAIN,
OPT_NO_CERT_CHECKS, OPT_NO_EXPLICIT, OPT_TRUST_OTHER,
OPT_NO_INTERN, OPT_BADSIG, OPT_TEXT, OPT_REQ_TEXT, OPT_RESP_TEXT,
OPT_REQIN, OPT_RESPIN, OPT_SIGNER, OPT_VAFILE, OPT_SIGN_OTHER,
OPT_VERIFY_OTHER, OPT_CAFILE, OPT_CAPATH, OPT_NOCAFILE, OPT_NOCAPATH,
OPT_VALIDITY_PERIOD, OPT_STATUS_AGE, OPT_SIGNKEY, OPT_REQOUT,
OPT_RESPOUT, OPT_PATH, OPT_ISSUER, OPT_CERT, OPT_SERIAL,
OPT_INDEX, OPT_CA, OPT_NMIN, OPT_REQUEST, OPT_NDAYS, OPT_RSIGNER,
OPT_RKEY, OPT_ROTHER, OPT_RMD, OPT_RSIGOPT, OPT_HEADER,
OPT_V_ENUM,
OPT_MD,
OPT_MULTI
} OPTION_CHOICE;
const OPTIONS ocsp_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"out", OPT_OUTFILE, '>', "Output filename"},
{"timeout", OPT_TIMEOUT, 'p',
"Connection timeout (in seconds) to the OCSP responder"},
{"url", OPT_URL, 's', "Responder URL"},
{"host", OPT_HOST, 's', "TCP/IP hostname:port to connect to"},
{"port", OPT_PORT, 'p', "Port to run responder on"},
{"ignore_err", OPT_IGNORE_ERR, '-',
"Ignore error on OCSP request or response and continue running"},
{"noverify", OPT_NOVERIFY, '-', "Don't verify response at all"},
{"nonce", OPT_NONCE, '-', "Add OCSP nonce to request"},
{"no_nonce", OPT_NO_NONCE, '-', "Don't add OCSP nonce to request"},
{"resp_no_certs", OPT_RESP_NO_CERTS, '-',
"Don't include any certificates in response"},
{"resp_key_id", OPT_RESP_KEY_ID, '-',
"Identify response by signing certificate key ID"},
# ifdef OCSP_DAEMON
{"multi", OPT_MULTI, 'p', "run multiple responder processes"},
# endif
{"no_certs", OPT_NO_CERTS, '-',
"Don't include any certificates in signed request"},
{"no_signature_verify", OPT_NO_SIGNATURE_VERIFY, '-',
"Don't check signature on response"},
{"no_cert_verify", OPT_NO_CERT_VERIFY, '-',
"Don't check signing certificate"},
{"no_chain", OPT_NO_CHAIN, '-', "Don't chain verify response"},
{"no_cert_checks", OPT_NO_CERT_CHECKS, '-',
"Don't do additional checks on signing certificate"},
{"no_explicit", OPT_NO_EXPLICIT, '-',
"Do not explicitly check the chain, just verify the root"},
{"trust_other", OPT_TRUST_OTHER, '-',
"Don't verify additional certificates"},
{"no_intern", OPT_NO_INTERN, '-',
"Don't search certificates contained in response for signer"},
{"badsig", OPT_BADSIG, '-',
"Corrupt last byte of loaded OSCP response signature (for test)"},
{"text", OPT_TEXT, '-', "Print text form of request and response"},
{"req_text", OPT_REQ_TEXT, '-', "Print text form of request"},
{"resp_text", OPT_RESP_TEXT, '-', "Print text form of response"},
{"reqin", OPT_REQIN, 's', "File with the DER-encoded request"},
{"respin", OPT_RESPIN, 's', "File with the DER-encoded response"},
{"signer", OPT_SIGNER, '<', "Certificate to sign OCSP request with"},
{"VAfile", OPT_VAFILE, '<', "Validator certificates file"},
{"sign_other", OPT_SIGN_OTHER, '<',
"Additional certificates to include in signed request"},
{"verify_other", OPT_VERIFY_OTHER, '<',
"Additional certificates to search for signer"},
{"CAfile", OPT_CAFILE, '<', "Trusted certificates file"},
{"CApath", OPT_CAPATH, '<', "Trusted certificates directory"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
{"validity_period", OPT_VALIDITY_PERIOD, 'u',
"Maximum validity discrepancy in seconds"},
{"status_age", OPT_STATUS_AGE, 'p', "Maximum status age in seconds"},
{"signkey", OPT_SIGNKEY, 's', "Private key to sign OCSP request with"},
{"reqout", OPT_REQOUT, 's', "Output file for the DER-encoded request"},
{"respout", OPT_RESPOUT, 's', "Output file for the DER-encoded response"},
{"path", OPT_PATH, 's', "Path to use in OCSP request"},
{"issuer", OPT_ISSUER, '<', "Issuer certificate"},
{"cert", OPT_CERT, '<', "Certificate to check"},
{"serial", OPT_SERIAL, 's', "Serial number to check"},
{"index", OPT_INDEX, '<', "Certificate status index file"},
{"CA", OPT_CA, '<', "CA certificate"},
{"nmin", OPT_NMIN, 'p', "Number of minutes before next update"},
{"nrequest", OPT_REQUEST, 'p',
"Number of requests to accept (default unlimited)"},
{"ndays", OPT_NDAYS, 'p', "Number of days before next update"},
{"rsigner", OPT_RSIGNER, '<',
"Responder certificate to sign responses with"},
{"rkey", OPT_RKEY, '<', "Responder key to sign responses with"},
{"rother", OPT_ROTHER, '<', "Other certificates to include in response"},
{"rmd", OPT_RMD, 's', "Digest Algorithm to use in signature of OCSP response"},
{"rsigopt", OPT_RSIGOPT, 's', "OCSP response signature parameter in n:v form"},
{"header", OPT_HEADER, 's', "key=value header to add"},
{"", OPT_MD, '-', "Any supported digest algorithm (sha1,sha256, ... )"},
OPT_V_OPTIONS,
{NULL}
};
int ocsp_main(int argc, char **argv)
{
BIO *acbio = NULL, *cbio = NULL, *derbio = NULL, *out = NULL;
const EVP_MD *cert_id_md = NULL, *rsign_md = NULL;
STACK_OF(OPENSSL_STRING) *rsign_sigopts = NULL;
int trailing_md = 0;
CA_DB *rdb = NULL;
EVP_PKEY *key = NULL, *rkey = NULL;
OCSP_BASICRESP *bs = NULL;
OCSP_REQUEST *req = NULL;
OCSP_RESPONSE *resp = NULL;
STACK_OF(CONF_VALUE) *headers = NULL;
STACK_OF(OCSP_CERTID) *ids = NULL;
STACK_OF(OPENSSL_STRING) *reqnames = NULL;
STACK_OF(X509) *sign_other = NULL, *verify_other = NULL, *rother = NULL;
STACK_OF(X509) *issuers = NULL;
X509 *issuer = NULL, *cert = NULL;
STACK_OF(X509) *rca_cert = NULL;
X509 *signer = NULL, *rsigner = NULL;
X509_STORE *store = NULL;
X509_VERIFY_PARAM *vpm = NULL;
const char *CAfile = NULL, *CApath = NULL;
char *header, *value;
char *host = NULL, *port = NULL, *path = "/", *outfile = NULL;
char *rca_filename = NULL, *reqin = NULL, *respin = NULL;
char *reqout = NULL, *respout = NULL, *ridx_filename = NULL;
char *rsignfile = NULL, *rkeyfile = NULL;
char *sign_certfile = NULL, *verify_certfile = NULL, *rcertfile = NULL;
char *signfile = NULL, *keyfile = NULL;
char *thost = NULL, *tport = NULL, *tpath = NULL;
int noCAfile = 0, noCApath = 0;
int accept_count = -1, add_nonce = 1, noverify = 0, use_ssl = -1;
int vpmtouched = 0, badsig = 0, i, ignore_err = 0, nmin = 0, ndays = -1;
int req_text = 0, resp_text = 0, ret = 1;
int req_timeout = -1;
long nsec = MAX_VALIDITY_PERIOD, maxage = -1;
unsigned long sign_flags = 0, verify_flags = 0, rflags = 0;
OPTION_CHOICE o;
reqnames = sk_OPENSSL_STRING_new_null();
if (reqnames == NULL)
goto end;
ids = sk_OCSP_CERTID_new_null();
if (ids == NULL)
goto end;
if ((vpm = X509_VERIFY_PARAM_new()) == NULL)
return 1;
prog = opt_init(argc, argv, ocsp_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
ret = 0;
opt_help(ocsp_options);
goto end;
case OPT_OUTFILE:
outfile = opt_arg();
break;
case OPT_TIMEOUT:
#ifndef OPENSSL_NO_SOCK
req_timeout = atoi(opt_arg());
#endif
break;
case OPT_URL:
OPENSSL_free(thost);
OPENSSL_free(tport);
OPENSSL_free(tpath);
thost = tport = tpath = NULL;
if (!OCSP_parse_url(opt_arg(), &host, &port, &path, &use_ssl)) {
BIO_printf(bio_err, "%s Error parsing URL\n", prog);
goto end;
}
thost = host;
tport = port;
tpath = path;
break;
case OPT_HOST:
host = opt_arg();
break;
case OPT_PORT:
port = opt_arg();
break;
case OPT_IGNORE_ERR:
ignore_err = 1;
break;
case OPT_NOVERIFY:
noverify = 1;
break;
case OPT_NONCE:
add_nonce = 2;
break;
case OPT_NO_NONCE:
add_nonce = 0;
break;
case OPT_RESP_NO_CERTS:
rflags |= OCSP_NOCERTS;
break;
case OPT_RESP_KEY_ID:
rflags |= OCSP_RESPID_KEY;
break;
case OPT_NO_CERTS:
sign_flags |= OCSP_NOCERTS;
break;
case OPT_NO_SIGNATURE_VERIFY:
verify_flags |= OCSP_NOSIGS;
break;
case OPT_NO_CERT_VERIFY:
verify_flags |= OCSP_NOVERIFY;
break;
case OPT_NO_CHAIN:
verify_flags |= OCSP_NOCHAIN;
break;
case OPT_NO_CERT_CHECKS:
verify_flags |= OCSP_NOCHECKS;
break;
case OPT_NO_EXPLICIT:
verify_flags |= OCSP_NOEXPLICIT;
break;
case OPT_TRUST_OTHER:
verify_flags |= OCSP_TRUSTOTHER;
break;
case OPT_NO_INTERN:
verify_flags |= OCSP_NOINTERN;
break;
case OPT_BADSIG:
badsig = 1;
break;
case OPT_TEXT:
req_text = resp_text = 1;
break;
case OPT_REQ_TEXT:
req_text = 1;
break;
case OPT_RESP_TEXT:
resp_text = 1;
break;
case OPT_REQIN:
reqin = opt_arg();
break;
case OPT_RESPIN:
respin = opt_arg();
break;
case OPT_SIGNER:
signfile = opt_arg();
break;
case OPT_VAFILE:
verify_certfile = opt_arg();
verify_flags |= OCSP_TRUSTOTHER;
break;
case OPT_SIGN_OTHER:
sign_certfile = opt_arg();
break;
case OPT_VERIFY_OTHER:
verify_certfile = opt_arg();
break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_CAPATH:
CApath = opt_arg();
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto end;
vpmtouched++;
break;
case OPT_VALIDITY_PERIOD:
opt_long(opt_arg(), &nsec);
break;
case OPT_STATUS_AGE:
opt_long(opt_arg(), &maxage);
break;
case OPT_SIGNKEY:
keyfile = opt_arg();
break;
case OPT_REQOUT:
reqout = opt_arg();
break;
case OPT_RESPOUT:
respout = opt_arg();
break;
case OPT_PATH:
path = opt_arg();
break;
case OPT_ISSUER:
issuer = load_cert(opt_arg(), FORMAT_PEM, "issuer certificate");
if (issuer == NULL)
goto end;
if (issuers == NULL) {
if ((issuers = sk_X509_new_null()) == NULL)
goto end;
}
sk_X509_push(issuers, issuer);
break;
case OPT_CERT:
X509_free(cert);
cert = load_cert(opt_arg(), FORMAT_PEM, "certificate");
if (cert == NULL)
goto end;
if (cert_id_md == NULL)
cert_id_md = EVP_sha1();
if (!add_ocsp_cert(&req, cert, cert_id_md, issuer, ids))
goto end;
if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
goto end;
trailing_md = 0;
break;
case OPT_SERIAL:
if (cert_id_md == NULL)
cert_id_md = EVP_sha1();
if (!add_ocsp_serial(&req, opt_arg(), cert_id_md, issuer, ids))
goto end;
if (!sk_OPENSSL_STRING_push(reqnames, opt_arg()))
goto end;
trailing_md = 0;
break;
case OPT_INDEX:
ridx_filename = opt_arg();
break;
case OPT_CA:
rca_filename = opt_arg();
break;
case OPT_NMIN:
opt_int(opt_arg(), &nmin);
if (ndays == -1)
ndays = 0;
break;
case OPT_REQUEST:
opt_int(opt_arg(), &accept_count);
break;
case OPT_NDAYS:
ndays = atoi(opt_arg());
break;
case OPT_RSIGNER:
rsignfile = opt_arg();
break;
case OPT_RKEY:
rkeyfile = opt_arg();
break;
case OPT_ROTHER:
rcertfile = opt_arg();
break;
case OPT_RMD: /* Response MessageDigest */
if (!opt_md(opt_arg(), &rsign_md))
goto end;
break;
case OPT_RSIGOPT:
if (rsign_sigopts == NULL)
rsign_sigopts = sk_OPENSSL_STRING_new_null();
if (rsign_sigopts == NULL || !sk_OPENSSL_STRING_push(rsign_sigopts, opt_arg()))
goto end;
break;
case OPT_HEADER:
header = opt_arg();
value = strchr(header, '=');
if (value == NULL) {
BIO_printf(bio_err, "Missing = in header key=value\n");
goto opthelp;
}
*value++ = '\0';
if (!X509V3_add_value(header, value, &headers))
goto end;
break;
case OPT_MD:
if (trailing_md) {
BIO_printf(bio_err,
"%s: Digest must be before -cert or -serial\n",
prog);
goto opthelp;
}
if (!opt_md(opt_unknown(), &cert_id_md))
goto opthelp;
trailing_md = 1;
break;
case OPT_MULTI:
# ifdef OCSP_DAEMON
multi = atoi(opt_arg());
# endif
break;
}
}
if (trailing_md) {
BIO_printf(bio_err, "%s: Digest must be before -cert or -serial\n",
prog);
goto opthelp;
}
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
/* Have we anything to do? */
if (req == NULL && reqin == NULL
&& respin == NULL && !(port != NULL && ridx_filename != NULL))
goto opthelp;
out = bio_open_default(outfile, 'w', FORMAT_TEXT);
if (out == NULL)
goto end;
if (req == NULL && (add_nonce != 2))
add_nonce = 0;
if (req == NULL && reqin != NULL) {
derbio = bio_open_default(reqin, 'r', FORMAT_ASN1);
if (derbio == NULL)
goto end;
req = d2i_OCSP_REQUEST_bio(derbio, NULL);
BIO_free(derbio);
if (req == NULL) {
BIO_printf(bio_err, "Error reading OCSP request\n");
goto end;
}
}
if (req == NULL && port != NULL) {
acbio = init_responder(port);
if (acbio == NULL)
goto end;
}
if (rsignfile != NULL) {
if (rkeyfile == NULL)
rkeyfile = rsignfile;
rsigner = load_cert(rsignfile, FORMAT_PEM, "responder certificate");
if (rsigner == NULL) {
BIO_printf(bio_err, "Error loading responder certificate\n");
goto end;
}
if (!load_certs(rca_filename, &rca_cert, FORMAT_PEM,
NULL, "CA certificate"))
goto end;
if (rcertfile != NULL) {
if (!load_certs(rcertfile, &rother, FORMAT_PEM, NULL,
"responder other certificates"))
goto end;
}
rkey = load_key(rkeyfile, FORMAT_PEM, 0, NULL, NULL,
"responder private key");
if (rkey == NULL)
goto end;
}
if (ridx_filename != NULL
&& (rkey == NULL || rsigner == NULL || rca_cert == NULL)) {
BIO_printf(bio_err,
"Responder mode requires certificate, key, and CA.\n");
goto end;
}
if (ridx_filename != NULL) {
rdb = load_index(ridx_filename, NULL);
if (rdb == NULL || index_index(rdb) <= 0) {
ret = 1;
goto end;
}
}
# ifdef OCSP_DAEMON
if (multi && acbio != NULL)
spawn_loop();
if (acbio != NULL && req_timeout > 0)
signal(SIGALRM, sock_timeout);
#endif
if (acbio != NULL)
log_message(LOG_INFO, "waiting for OCSP client connections...");
redo_accept:
if (acbio != NULL) {
# ifdef OCSP_DAEMON
if (index_changed(rdb)) {
CA_DB *newrdb = load_index(ridx_filename, NULL);
if (newrdb != NULL && index_index(newrdb) > 0) {
free_index(rdb);
rdb = newrdb;
} else {
free_index(newrdb);
log_message(LOG_ERR, "error reloading updated index: %s",
ridx_filename);
}
}
# endif
req = NULL;
if (!do_responder(&req, &cbio, acbio, req_timeout))
goto redo_accept;
if (req == NULL) {
resp =
OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST,
NULL);
send_ocsp_response(cbio, resp);
goto done_resp;
}
}
if (req == NULL
&& (signfile != NULL || reqout != NULL
|| host != NULL || add_nonce || ridx_filename != NULL)) {
BIO_printf(bio_err, "Need an OCSP request for this operation!\n");
goto end;
}
- if (req != NULL && add_nonce)
- OCSP_request_add1_nonce(req, NULL, -1);
+ if (req != NULL && add_nonce) {
+ if (!OCSP_request_add1_nonce(req, NULL, -1))
+ goto end;
+ }
if (signfile != NULL) {
if (keyfile == NULL)
keyfile = signfile;
signer = load_cert(signfile, FORMAT_PEM, "signer certificate");
if (signer == NULL) {
BIO_printf(bio_err, "Error loading signer certificate\n");
goto end;
}
if (sign_certfile != NULL) {
if (!load_certs(sign_certfile, &sign_other, FORMAT_PEM, NULL,
"signer certificates"))
goto end;
}
key = load_key(keyfile, FORMAT_PEM, 0, NULL, NULL,
"signer private key");
if (key == NULL)
goto end;
if (!OCSP_request_sign
(req, signer, key, NULL, sign_other, sign_flags)) {
BIO_printf(bio_err, "Error signing OCSP request\n");
goto end;
}
}
if (req_text && req != NULL)
OCSP_REQUEST_print(out, req, 0);
if (reqout != NULL) {
derbio = bio_open_default(reqout, 'w', FORMAT_ASN1);
if (derbio == NULL)
goto end;
i2d_OCSP_REQUEST_bio(derbio, req);
BIO_free(derbio);
}
if (rdb != NULL) {
make_ocsp_response(bio_err, &resp, req, rdb, rca_cert, rsigner, rkey,
rsign_md, rsign_sigopts, rother, rflags, nmin, ndays, badsig);
if (cbio != NULL)
send_ocsp_response(cbio, resp);
} else if (host != NULL) {
# ifndef OPENSSL_NO_SOCK
resp = process_responder(req, host, path,
port, use_ssl, headers, req_timeout);
if (resp == NULL)
goto end;
# else
BIO_printf(bio_err,
"Error creating connect BIO - sockets not supported.\n");
goto end;
# endif
} else if (respin != NULL) {
derbio = bio_open_default(respin, 'r', FORMAT_ASN1);
if (derbio == NULL)
goto end;
resp = d2i_OCSP_RESPONSE_bio(derbio, NULL);
BIO_free(derbio);
if (resp == NULL) {
BIO_printf(bio_err, "Error reading OCSP response\n");
goto end;
}
} else {
ret = 0;
goto end;
}
done_resp:
if (respout != NULL) {
derbio = bio_open_default(respout, 'w', FORMAT_ASN1);
if (derbio == NULL)
goto end;
i2d_OCSP_RESPONSE_bio(derbio, resp);
BIO_free(derbio);
}
i = OCSP_response_status(resp);
if (i != OCSP_RESPONSE_STATUS_SUCCESSFUL) {
BIO_printf(out, "Responder Error: %s (%d)\n",
OCSP_response_status_str(i), i);
if (!ignore_err)
goto end;
}
if (resp_text)
OCSP_RESPONSE_print(out, resp, 0);
/* If running as responder don't verify our own response */
if (cbio != NULL) {
/* If not unlimited, see if we took all we should. */
if (accept_count != -1 && --accept_count <= 0) {
ret = 0;
goto end;
}
BIO_free_all(cbio);
cbio = NULL;
OCSP_REQUEST_free(req);
req = NULL;
OCSP_RESPONSE_free(resp);
resp = NULL;
goto redo_accept;
}
if (ridx_filename != NULL) {
ret = 0;
goto end;
}
if (store == NULL) {
store = setup_verify(CAfile, CApath, noCAfile, noCApath);
if (!store)
goto end;
}
if (vpmtouched)
X509_STORE_set1_param(store, vpm);
if (verify_certfile != NULL) {
if (!load_certs(verify_certfile, &verify_other, FORMAT_PEM, NULL,
"validator certificate"))
goto end;
}
bs = OCSP_response_get1_basic(resp);
if (bs == NULL) {
BIO_printf(bio_err, "Error parsing response\n");
goto end;
}
ret = 0;
if (!noverify) {
if (req != NULL && ((i = OCSP_check_nonce(req, bs)) <= 0)) {
if (i == -1)
BIO_printf(bio_err, "WARNING: no nonce in response\n");
else {
BIO_printf(bio_err, "Nonce Verify error\n");
ret = 1;
goto end;
}
}
i = OCSP_basic_verify(bs, verify_other, store, verify_flags);
if (i <= 0 && issuers) {
i = OCSP_basic_verify(bs, issuers, store, OCSP_TRUSTOTHER);
if (i > 0)
ERR_clear_error();
}
if (i <= 0) {
BIO_printf(bio_err, "Response Verify Failure\n");
ERR_print_errors(bio_err);
ret = 1;
} else {
BIO_printf(bio_err, "Response verify OK\n");
}
}
print_ocsp_summary(out, bs, req, reqnames, ids, nsec, maxage);
end:
ERR_print_errors(bio_err);
X509_free(signer);
X509_STORE_free(store);
X509_VERIFY_PARAM_free(vpm);
sk_OPENSSL_STRING_free(rsign_sigopts);
EVP_PKEY_free(key);
EVP_PKEY_free(rkey);
X509_free(cert);
sk_X509_pop_free(issuers, X509_free);
X509_free(rsigner);
sk_X509_pop_free(rca_cert, X509_free);
free_index(rdb);
BIO_free_all(cbio);
BIO_free_all(acbio);
BIO_free_all(out);
OCSP_REQUEST_free(req);
OCSP_RESPONSE_free(resp);
OCSP_BASICRESP_free(bs);
sk_OPENSSL_STRING_free(reqnames);
sk_OCSP_CERTID_free(ids);
sk_X509_pop_free(sign_other, X509_free);
sk_X509_pop_free(verify_other, X509_free);
sk_CONF_VALUE_pop_free(headers, X509V3_conf_free);
OPENSSL_free(thost);
OPENSSL_free(tport);
OPENSSL_free(tpath);
return ret;
}
static void
log_message(int level, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
# ifdef OCSP_DAEMON
if (multi) {
char buf[1024];
if (vsnprintf(buf, sizeof(buf), fmt, ap) > 0) {
syslog(level, "%s", buf);
}
if (level >= LOG_ERR)
ERR_print_errors_cb(print_syslog, &level);
}
# endif
if (!multi) {
BIO_printf(bio_err, "%s: ", prog);
BIO_vprintf(bio_err, fmt, ap);
BIO_printf(bio_err, "\n");
}
va_end(ap);
}
# ifdef OCSP_DAEMON
static int print_syslog(const char *str, size_t len, void *levPtr)
{
int level = *(int *)levPtr;
int ilen = (len > MAXERRLEN) ? MAXERRLEN : len;
syslog(level, "%.*s", ilen, str);
return ilen;
}
static int index_changed(CA_DB *rdb)
{
struct stat sb;
if (rdb != NULL && stat(rdb->dbfname, &sb) != -1) {
if (rdb->dbst.st_mtime != sb.st_mtime
|| rdb->dbst.st_ctime != sb.st_ctime
|| rdb->dbst.st_ino != sb.st_ino
|| rdb->dbst.st_dev != sb.st_dev) {
syslog(LOG_INFO, "index file changed, reloading");
return 1;
}
}
return 0;
}
static void killall(int ret, pid_t *kidpids)
{
int i;
for (i = 0; i < multi; ++i)
if (kidpids[i] != 0)
(void)kill(kidpids[i], SIGTERM);
OPENSSL_free(kidpids);
sleep(1);
exit(ret);
}
static int termsig = 0;
static void noteterm (int sig)
{
termsig = sig;
}
/*
* Loop spawning up to `multi` child processes, only child processes return
* from this function. The parent process loops until receiving a termination
* signal, kills extant children and exits without returning.
*/
static void spawn_loop(void)
{
pid_t *kidpids = NULL;
int status;
int procs = 0;
int i;
openlog(prog, LOG_PID, LOG_DAEMON);
if (setpgid(0, 0)) {
syslog(LOG_ERR, "fatal: error detaching from parent process group: %s",
strerror(errno));
exit(1);
}
kidpids = app_malloc(multi * sizeof(*kidpids), "child PID array");
for (i = 0; i < multi; ++i)
kidpids[i] = 0;
signal(SIGINT, noteterm);
signal(SIGTERM, noteterm);
while (termsig == 0) {
pid_t fpid;
/*
* Wait for a child to replace when we're at the limit.
* Slow down if a child exited abnormally or waitpid() < 0
*/
while (termsig == 0 && procs >= multi) {
if ((fpid = waitpid(-1, &status, 0)) > 0) {
for (i = 0; i < procs; ++i) {
if (kidpids[i] == fpid) {
kidpids[i] = 0;
--procs;
break;
}
}
if (i >= multi) {
syslog(LOG_ERR, "fatal: internal error: "
"no matching child slot for pid: %ld",
(long) fpid);
killall(1, kidpids);
}
if (status != 0) {
if (WIFEXITED(status))
syslog(LOG_WARNING, "child process: %ld, exit status: %d",
(long)fpid, WEXITSTATUS(status));
else if (WIFSIGNALED(status))
syslog(LOG_WARNING, "child process: %ld, term signal %d%s",
(long)fpid, WTERMSIG(status),
#ifdef WCOREDUMP
WCOREDUMP(status) ? " (core dumped)" :
#endif
"");
sleep(1);
}
break;
} else if (errno != EINTR) {
syslog(LOG_ERR, "fatal: waitpid(): %s", strerror(errno));
killall(1, kidpids);
}
}
if (termsig)
break;
switch(fpid = fork()) {
case -1: /* error */
/* System critically low on memory, pause and try again later */
sleep(30);
break;
case 0: /* child */
OPENSSL_free(kidpids);
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
if (termsig)
_exit(0);
if (RAND_poll() <= 0) {
syslog(LOG_ERR, "fatal: RAND_poll() failed");
_exit(1);
}
return;
default: /* parent */
for (i = 0; i < multi; ++i) {
if (kidpids[i] == 0) {
kidpids[i] = fpid;
procs++;
break;
}
}
if (i >= multi) {
syslog(LOG_ERR, "fatal: internal error: no free child slots");
killall(1, kidpids);
}
break;
}
}
/* The loop above can only break on termsig */
syslog(LOG_INFO, "terminating on signal: %d", termsig);
killall(0, kidpids);
}
# endif
static int add_ocsp_cert(OCSP_REQUEST **req, X509 *cert,
const EVP_MD *cert_id_md, X509 *issuer,
STACK_OF(OCSP_CERTID) *ids)
{
OCSP_CERTID *id;
if (issuer == NULL) {
BIO_printf(bio_err, "No issuer certificate specified\n");
return 0;
}
if (*req == NULL)
*req = OCSP_REQUEST_new();
if (*req == NULL)
goto err;
id = OCSP_cert_to_id(cert_id_md, cert, issuer);
if (id == NULL || !sk_OCSP_CERTID_push(ids, id))
goto err;
if (!OCSP_request_add0_id(*req, id))
goto err;
return 1;
err:
BIO_printf(bio_err, "Error Creating OCSP request\n");
return 0;
}
static int add_ocsp_serial(OCSP_REQUEST **req, char *serial,
const EVP_MD *cert_id_md, X509 *issuer,
STACK_OF(OCSP_CERTID) *ids)
{
OCSP_CERTID *id;
X509_NAME *iname;
ASN1_BIT_STRING *ikey;
ASN1_INTEGER *sno;
if (issuer == NULL) {
BIO_printf(bio_err, "No issuer certificate specified\n");
return 0;
}
if (*req == NULL)
*req = OCSP_REQUEST_new();
if (*req == NULL)
goto err;
iname = X509_get_subject_name(issuer);
ikey = X509_get0_pubkey_bitstr(issuer);
sno = s2i_ASN1_INTEGER(NULL, serial);
if (sno == NULL) {
BIO_printf(bio_err, "Error converting serial number %s\n", serial);
return 0;
}
id = OCSP_cert_id_new(cert_id_md, iname, ikey, sno);
ASN1_INTEGER_free(sno);
if (id == NULL || !sk_OCSP_CERTID_push(ids, id))
goto err;
if (!OCSP_request_add0_id(*req, id))
goto err;
return 1;
err:
BIO_printf(bio_err, "Error Creating OCSP request\n");
return 0;
}
static void print_ocsp_summary(BIO *out, OCSP_BASICRESP *bs, OCSP_REQUEST *req,
STACK_OF(OPENSSL_STRING) *names,
STACK_OF(OCSP_CERTID) *ids, long nsec,
long maxage)
{
OCSP_CERTID *id;
const char *name;
int i, status, reason;
ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd;
if (bs == NULL || req == NULL || !sk_OPENSSL_STRING_num(names)
|| !sk_OCSP_CERTID_num(ids))
return;
for (i = 0; i < sk_OCSP_CERTID_num(ids); i++) {
id = sk_OCSP_CERTID_value(ids, i);
name = sk_OPENSSL_STRING_value(names, i);
BIO_printf(out, "%s: ", name);
if (!OCSP_resp_find_status(bs, id, &status, &reason,
&rev, &thisupd, &nextupd)) {
BIO_puts(out, "ERROR: No Status found.\n");
continue;
}
/*
* Check validity: if invalid write to output BIO so we know which
* response this refers to.
*/
if (!OCSP_check_validity(thisupd, nextupd, nsec, maxage)) {
BIO_puts(out, "WARNING: Status times invalid.\n");
ERR_print_errors(out);
}
BIO_printf(out, "%s\n", OCSP_cert_status_str(status));
BIO_puts(out, "\tThis Update: ");
ASN1_GENERALIZEDTIME_print(out, thisupd);
BIO_puts(out, "\n");
if (nextupd) {
BIO_puts(out, "\tNext Update: ");
ASN1_GENERALIZEDTIME_print(out, nextupd);
BIO_puts(out, "\n");
}
if (status != V_OCSP_CERTSTATUS_REVOKED)
continue;
if (reason != -1)
BIO_printf(out, "\tReason: %s\n", OCSP_crl_reason_str(reason));
BIO_puts(out, "\tRevocation Time: ");
ASN1_GENERALIZEDTIME_print(out, rev);
BIO_puts(out, "\n");
}
}
static void make_ocsp_response(BIO *err, OCSP_RESPONSE **resp, OCSP_REQUEST *req,
CA_DB *db, STACK_OF(X509) *ca, X509 *rcert,
EVP_PKEY *rkey, const EVP_MD *rmd,
STACK_OF(OPENSSL_STRING) *sigopts,
STACK_OF(X509) *rother, unsigned long flags,
int nmin, int ndays, int badsig)
{
ASN1_TIME *thisupd = NULL, *nextupd = NULL;
OCSP_CERTID *cid;
OCSP_BASICRESP *bs = NULL;
int i, id_count;
EVP_MD_CTX *mctx = NULL;
EVP_PKEY_CTX *pkctx = NULL;
id_count = OCSP_request_onereq_count(req);
if (id_count <= 0) {
*resp =
OCSP_response_create(OCSP_RESPONSE_STATUS_MALFORMEDREQUEST, NULL);
goto end;
}
bs = OCSP_BASICRESP_new();
thisupd = X509_gmtime_adj(NULL, 0);
if (ndays != -1)
nextupd = X509_time_adj_ex(NULL, ndays, nmin * 60, NULL);
/* Examine each certificate id in the request */
for (i = 0; i < id_count; i++) {
OCSP_ONEREQ *one;
ASN1_INTEGER *serial;
char **inf;
int jj;
int found = 0;
ASN1_OBJECT *cert_id_md_oid;
const EVP_MD *cert_id_md;
one = OCSP_request_onereq_get0(req, i);
cid = OCSP_onereq_get0_id(one);
OCSP_id_get0_info(NULL, &cert_id_md_oid, NULL, NULL, cid);
cert_id_md = EVP_get_digestbyobj(cert_id_md_oid);
if (cert_id_md == NULL) {
*resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
NULL);
goto end;
}
for (jj = 0; jj < sk_X509_num(ca) && !found; jj++) {
X509 *ca_cert = sk_X509_value(ca, jj);
OCSP_CERTID *ca_id = OCSP_cert_to_id(cert_id_md, NULL, ca_cert);
if (OCSP_id_issuer_cmp(ca_id, cid) == 0)
found = 1;
OCSP_CERTID_free(ca_id);
}
if (!found) {
OCSP_basic_add1_status(bs, cid,
V_OCSP_CERTSTATUS_UNKNOWN,
0, NULL, thisupd, nextupd);
continue;
}
OCSP_id_get0_info(NULL, NULL, NULL, &serial, cid);
inf = lookup_serial(db, serial);
if (inf == NULL) {
OCSP_basic_add1_status(bs, cid,
V_OCSP_CERTSTATUS_UNKNOWN,
0, NULL, thisupd, nextupd);
} else if (inf[DB_type][0] == DB_TYPE_VAL) {
OCSP_basic_add1_status(bs, cid,
V_OCSP_CERTSTATUS_GOOD,
0, NULL, thisupd, nextupd);
} else if (inf[DB_type][0] == DB_TYPE_REV) {
ASN1_OBJECT *inst = NULL;
ASN1_TIME *revtm = NULL;
ASN1_GENERALIZEDTIME *invtm = NULL;
OCSP_SINGLERESP *single;
int reason = -1;
unpack_revinfo(&revtm, &reason, &inst, &invtm, inf[DB_rev_date]);
single = OCSP_basic_add1_status(bs, cid,
V_OCSP_CERTSTATUS_REVOKED,
reason, revtm, thisupd, nextupd);
if (invtm != NULL)
OCSP_SINGLERESP_add1_ext_i2d(single, NID_invalidity_date,
invtm, 0, 0);
else if (inst != NULL)
OCSP_SINGLERESP_add1_ext_i2d(single,
NID_hold_instruction_code, inst,
0, 0);
ASN1_OBJECT_free(inst);
ASN1_TIME_free(revtm);
ASN1_GENERALIZEDTIME_free(invtm);
}
}
OCSP_copy_nonce(bs, req);
mctx = EVP_MD_CTX_new();
if ( mctx == NULL || !EVP_DigestSignInit(mctx, &pkctx, rmd, NULL, rkey)) {
*resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, NULL);
goto end;
}
for (i = 0; i < sk_OPENSSL_STRING_num(sigopts); i++) {
char *sigopt = sk_OPENSSL_STRING_value(sigopts, i);
if (pkey_ctrl_string(pkctx, sigopt) <= 0) {
BIO_printf(err, "parameter error \"%s\"\n", sigopt);
ERR_print_errors(bio_err);
*resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR,
NULL);
goto end;
}
}
- OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags);
+ if (!OCSP_basic_sign_ctx(bs, rcert, mctx, rother, flags)) {
+ *resp = OCSP_response_create(OCSP_RESPONSE_STATUS_INTERNALERROR, bs);
+ goto end;
+ }
if (badsig) {
const ASN1_OCTET_STRING *sig = OCSP_resp_get0_signature(bs);
corrupt_signature(sig);
}
*resp = OCSP_response_create(OCSP_RESPONSE_STATUS_SUCCESSFUL, bs);
end:
EVP_MD_CTX_free(mctx);
ASN1_TIME_free(thisupd);
ASN1_TIME_free(nextupd);
OCSP_BASICRESP_free(bs);
}
static char **lookup_serial(CA_DB *db, ASN1_INTEGER *ser)
{
int i;
BIGNUM *bn = NULL;
char *itmp, *row[DB_NUMBER], **rrow;
for (i = 0; i < DB_NUMBER; i++)
row[i] = NULL;
bn = ASN1_INTEGER_to_BN(ser, NULL);
OPENSSL_assert(bn); /* FIXME: should report an error at this
* point and abort */
if (BN_is_zero(bn))
itmp = OPENSSL_strdup("00");
else
itmp = BN_bn2hex(bn);
row[DB_serial] = itmp;
BN_free(bn);
rrow = TXT_DB_get_by_index(db->db, DB_serial, row);
OPENSSL_free(itmp);
return rrow;
}
/* Quick and dirty OCSP server: read in and parse input request */
static BIO *init_responder(const char *port)
{
# ifdef OPENSSL_NO_SOCK
BIO_printf(bio_err,
"Error setting up accept BIO - sockets not supported.\n");
return NULL;
# else
BIO *acbio = NULL, *bufbio = NULL;
bufbio = BIO_new(BIO_f_buffer());
if (bufbio == NULL)
goto err;
acbio = BIO_new(BIO_s_accept());
if (acbio == NULL
|| BIO_set_bind_mode(acbio, BIO_BIND_REUSEADDR) < 0
|| BIO_set_accept_port(acbio, port) < 0) {
log_message(LOG_ERR, "Error setting up accept BIO");
goto err;
}
BIO_set_accept_bios(acbio, bufbio);
bufbio = NULL;
if (BIO_do_accept(acbio) <= 0) {
log_message(LOG_ERR, "Error starting accept");
goto err;
}
return acbio;
err:
BIO_free_all(acbio);
BIO_free(bufbio);
return NULL;
# endif
}
# ifndef OPENSSL_NO_SOCK
/*
* Decode %xx URL-decoding in-place. Ignores mal-formed sequences.
*/
static int urldecode(char *p)
{
unsigned char *out = (unsigned char *)p;
unsigned char *save = out;
for (; *p; p++) {
if (*p != '%')
*out++ = *p;
else if (isxdigit(_UC(p[1])) && isxdigit(_UC(p[2]))) {
/* Don't check, can't fail because of ixdigit() call. */
*out++ = (OPENSSL_hexchar2int(p[1]) << 4)
| OPENSSL_hexchar2int(p[2]);
p += 2;
}
else
return -1;
}
*out = '\0';
return (int)(out - save);
}
# endif
# ifdef OCSP_DAEMON
static void sock_timeout(int signum)
{
if (acfd != (int)INVALID_SOCKET)
(void)shutdown(acfd, SHUT_RD);
}
# endif
static int do_responder(OCSP_REQUEST **preq, BIO **pcbio, BIO *acbio,
int timeout)
{
# ifdef OPENSSL_NO_SOCK
return 0;
# else
int len;
OCSP_REQUEST *req = NULL;
char inbuf[2048], reqbuf[2048];
char *p, *q;
BIO *cbio = NULL, *getbio = NULL, *b64 = NULL;
const char *client;
*preq = NULL;
/* Connection loss before accept() is routine, ignore silently */
if (BIO_do_accept(acbio) <= 0)
return 0;
cbio = BIO_pop(acbio);
*pcbio = cbio;
client = BIO_get_peer_name(cbio);
# ifdef OCSP_DAEMON
if (timeout > 0) {
(void) BIO_get_fd(cbio, &acfd);
alarm(timeout);
}
# endif
/* Read the request line. */
len = BIO_gets(cbio, reqbuf, sizeof(reqbuf));
if (len <= 0)
goto out;
if (strncmp(reqbuf, "GET ", 4) == 0) {
/* Expecting GET {sp} /URL {sp} HTTP/1.x */
for (p = reqbuf + 4; *p == ' '; ++p)
continue;
if (*p != '/') {
log_message(LOG_INFO, "Invalid request -- bad URL: %s", client);
goto out;
}
p++;
/* Splice off the HTTP version identifier. */
for (q = p; *q; q++)
if (*q == ' ')
break;
if (strncmp(q, " HTTP/1.", 8) != 0) {
log_message(LOG_INFO,
"Invalid request -- bad HTTP version: %s", client);
goto out;
}
*q = '\0';
/*
* Skip "GET / HTTP..." requests often used by load-balancers
*/
if (p[1] == '\0')
goto out;
len = urldecode(p);
if (len <= 0) {
log_message(LOG_INFO,
"Invalid request -- bad URL encoding: %s", client);
goto out;
}
if ((getbio = BIO_new_mem_buf(p, len)) == NULL
|| (b64 = BIO_new(BIO_f_base64())) == NULL) {
log_message(LOG_ERR, "Could not allocate base64 bio: %s", client);
goto out;
}
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
getbio = BIO_push(b64, getbio);
} else if (strncmp(reqbuf, "POST ", 5) != 0) {
log_message(LOG_INFO, "Invalid request -- bad HTTP verb: %s", client);
goto out;
}
/* Read and skip past the headers. */
for (;;) {
len = BIO_gets(cbio, inbuf, sizeof(inbuf));
if (len <= 0)
goto out;
if ((inbuf[0] == '\r') || (inbuf[0] == '\n'))
break;
}
# ifdef OCSP_DAEMON
/* Clear alarm before we close the client socket */
alarm(0);
timeout = 0;
# endif
/* Try to read OCSP request */
if (getbio != NULL) {
req = d2i_OCSP_REQUEST_bio(getbio, NULL);
BIO_free_all(getbio);
} else {
req = d2i_OCSP_REQUEST_bio(cbio, NULL);
}
if (req == NULL)
log_message(LOG_ERR, "Error parsing OCSP request");
*preq = req;
out:
# ifdef OCSP_DAEMON
if (timeout > 0)
alarm(0);
acfd = (int)INVALID_SOCKET;
# endif
return 1;
# endif
}
static int send_ocsp_response(BIO *cbio, OCSP_RESPONSE *resp)
{
char http_resp[] =
"HTTP/1.0 200 OK\r\nContent-type: application/ocsp-response\r\n"
"Content-Length: %d\r\n\r\n";
if (cbio == NULL)
return 0;
BIO_printf(cbio, http_resp, i2d_OCSP_RESPONSE(resp, NULL));
i2d_OCSP_RESPONSE_bio(cbio, resp);
(void)BIO_flush(cbio);
return 1;
}
# ifndef OPENSSL_NO_SOCK
static OCSP_RESPONSE *query_responder(BIO *cbio, const char *host,
const char *path,
const STACK_OF(CONF_VALUE) *headers,
OCSP_REQUEST *req, int req_timeout)
{
int fd;
int rv;
int i;
int add_host = 1;
OCSP_REQ_CTX *ctx = NULL;
OCSP_RESPONSE *rsp = NULL;
fd_set confds;
struct timeval tv;
if (req_timeout != -1)
BIO_set_nbio(cbio, 1);
rv = BIO_do_connect(cbio);
if ((rv <= 0) && ((req_timeout == -1) || !BIO_should_retry(cbio))) {
BIO_puts(bio_err, "Error connecting BIO\n");
return NULL;
}
if (BIO_get_fd(cbio, &fd) < 0) {
BIO_puts(bio_err, "Can't get connection fd\n");
goto err;
}
if (req_timeout != -1 && rv <= 0) {
FD_ZERO(&confds);
openssl_fdset(fd, &confds);
tv.tv_usec = 0;
tv.tv_sec = req_timeout;
rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
if (rv == 0) {
BIO_puts(bio_err, "Timeout on connect\n");
return NULL;
}
}
ctx = OCSP_sendreq_new(cbio, path, NULL, -1);
if (ctx == NULL)
return NULL;
for (i = 0; i < sk_CONF_VALUE_num(headers); i++) {
CONF_VALUE *hdr = sk_CONF_VALUE_value(headers, i);
if (add_host == 1 && strcasecmp("host", hdr->name) == 0)
add_host = 0;
if (!OCSP_REQ_CTX_add1_header(ctx, hdr->name, hdr->value))
goto err;
}
if (add_host == 1 && OCSP_REQ_CTX_add1_header(ctx, "Host", host) == 0)
goto err;
if (!OCSP_REQ_CTX_set1_req(ctx, req))
goto err;
for (;;) {
rv = OCSP_sendreq_nbio(&rsp, ctx);
if (rv != -1)
break;
if (req_timeout == -1)
continue;
FD_ZERO(&confds);
openssl_fdset(fd, &confds);
tv.tv_usec = 0;
tv.tv_sec = req_timeout;
if (BIO_should_read(cbio)) {
rv = select(fd + 1, (void *)&confds, NULL, NULL, &tv);
} else if (BIO_should_write(cbio)) {
rv = select(fd + 1, NULL, (void *)&confds, NULL, &tv);
} else {
BIO_puts(bio_err, "Unexpected retry condition\n");
goto err;
}
if (rv == 0) {
BIO_puts(bio_err, "Timeout on request\n");
break;
}
if (rv == -1) {
BIO_puts(bio_err, "Select error\n");
break;
}
}
err:
OCSP_REQ_CTX_free(ctx);
return rsp;
}
OCSP_RESPONSE *process_responder(OCSP_REQUEST *req,
const char *host, const char *path,
const char *port, int use_ssl,
STACK_OF(CONF_VALUE) *headers,
int req_timeout)
{
BIO *cbio = NULL;
SSL_CTX *ctx = NULL;
OCSP_RESPONSE *resp = NULL;
cbio = BIO_new_connect(host);
if (cbio == NULL) {
BIO_printf(bio_err, "Error creating connect BIO\n");
goto end;
}
if (port != NULL)
BIO_set_conn_port(cbio, port);
if (use_ssl == 1) {
BIO *sbio;
ctx = SSL_CTX_new(TLS_client_method());
if (ctx == NULL) {
BIO_printf(bio_err, "Error creating SSL context.\n");
goto end;
}
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
sbio = BIO_new_ssl(ctx, 1);
cbio = BIO_push(sbio, cbio);
}
resp = query_responder(cbio, host, path, headers, req, req_timeout);
if (resp == NULL)
BIO_printf(bio_err, "Error querying OCSP responder\n");
end:
BIO_free_all(cbio);
SSL_CTX_free(ctx);
return resp;
}
# endif
#endif
diff --git a/apps/s_cb.c b/apps/s_cb.c
index d0e332a7088a..520323c8b05c 100644
--- a/apps/s_cb.c
+++ b/apps/s_cb.c
@@ -1,1481 +1,1537 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* callback functions used by s_client, s_server, and s_time */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for memcpy() and strcmp() */
#include "apps.h"
#include <openssl/err.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/bn.h>
#ifndef OPENSSL_NO_DH
# include <openssl/dh.h>
#endif
#include "s_apps.h"
#define COOKIE_SECRET_LENGTH 16
VERIFY_CB_ARGS verify_args = { -1, 0, X509_V_OK, 0 };
#ifndef OPENSSL_NO_SOCK
static unsigned char cookie_secret[COOKIE_SECRET_LENGTH];
static int cookie_initialized = 0;
#endif
static BIO *bio_keylog = NULL;
static const char *lookup(int val, const STRINT_PAIR* list, const char* def)
{
for ( ; list->name; ++list)
if (list->retval == val)
return list->name;
return def;
}
int verify_callback(int ok, X509_STORE_CTX *ctx)
{
X509 *err_cert;
int err, depth;
err_cert = X509_STORE_CTX_get_current_cert(ctx);
err = X509_STORE_CTX_get_error(ctx);
depth = X509_STORE_CTX_get_error_depth(ctx);
if (!verify_args.quiet || !ok) {
BIO_printf(bio_err, "depth=%d ", depth);
if (err_cert != NULL) {
X509_NAME_print_ex(bio_err,
X509_get_subject_name(err_cert),
0, get_nameopt());
BIO_puts(bio_err, "\n");
} else {
BIO_puts(bio_err, "<no cert>\n");
}
}
if (!ok) {
BIO_printf(bio_err, "verify error:num=%d:%s\n", err,
X509_verify_cert_error_string(err));
if (verify_args.depth < 0 || verify_args.depth >= depth) {
if (!verify_args.return_error)
ok = 1;
verify_args.error = err;
} else {
ok = 0;
verify_args.error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
}
}
switch (err) {
case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
BIO_puts(bio_err, "issuer= ");
X509_NAME_print_ex(bio_err, X509_get_issuer_name(err_cert),
0, get_nameopt());
BIO_puts(bio_err, "\n");
break;
case X509_V_ERR_CERT_NOT_YET_VALID:
case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
BIO_printf(bio_err, "notBefore=");
ASN1_TIME_print(bio_err, X509_get0_notBefore(err_cert));
BIO_printf(bio_err, "\n");
break;
case X509_V_ERR_CERT_HAS_EXPIRED:
case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
BIO_printf(bio_err, "notAfter=");
ASN1_TIME_print(bio_err, X509_get0_notAfter(err_cert));
BIO_printf(bio_err, "\n");
break;
case X509_V_ERR_NO_EXPLICIT_POLICY:
if (!verify_args.quiet)
policies_print(ctx);
break;
}
if (err == X509_V_OK && ok == 2 && !verify_args.quiet)
policies_print(ctx);
if (ok && !verify_args.quiet)
BIO_printf(bio_err, "verify return:%d\n", ok);
return ok;
}
int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
{
if (cert_file != NULL) {
if (SSL_CTX_use_certificate_file(ctx, cert_file,
SSL_FILETYPE_PEM) <= 0) {
BIO_printf(bio_err, "unable to get certificate from '%s'\n",
cert_file);
ERR_print_errors(bio_err);
return 0;
}
if (key_file == NULL)
key_file = cert_file;
if (SSL_CTX_use_PrivateKey_file(ctx, key_file, SSL_FILETYPE_PEM) <= 0) {
BIO_printf(bio_err, "unable to get private key from '%s'\n",
key_file);
ERR_print_errors(bio_err);
return 0;
}
/*
* If we are using DSA, we can copy the parameters from the private
* key
*/
/*
* Now we know that a key and cert have been set against the SSL
* context
*/
if (!SSL_CTX_check_private_key(ctx)) {
BIO_printf(bio_err,
"Private key does not match the certificate public key\n");
return 0;
}
}
return 1;
}
int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key,
STACK_OF(X509) *chain, int build_chain)
{
int chflags = chain ? SSL_BUILD_CHAIN_FLAG_CHECK : 0;
if (cert == NULL)
return 1;
if (SSL_CTX_use_certificate(ctx, cert) <= 0) {
BIO_printf(bio_err, "error setting certificate\n");
ERR_print_errors(bio_err);
return 0;
}
if (SSL_CTX_use_PrivateKey(ctx, key) <= 0) {
BIO_printf(bio_err, "error setting private key\n");
ERR_print_errors(bio_err);
return 0;
}
/*
* Now we know that a key and cert have been set against the SSL context
*/
if (!SSL_CTX_check_private_key(ctx)) {
BIO_printf(bio_err,
"Private key does not match the certificate public key\n");
return 0;
}
if (chain && !SSL_CTX_set1_chain(ctx, chain)) {
BIO_printf(bio_err, "error setting certificate chain\n");
ERR_print_errors(bio_err);
return 0;
}
if (build_chain && !SSL_CTX_build_cert_chain(ctx, chflags)) {
BIO_printf(bio_err, "error building certificate chain\n");
ERR_print_errors(bio_err);
return 0;
}
return 1;
}
static STRINT_PAIR cert_type_list[] = {
{"RSA sign", TLS_CT_RSA_SIGN},
{"DSA sign", TLS_CT_DSS_SIGN},
{"RSA fixed DH", TLS_CT_RSA_FIXED_DH},
{"DSS fixed DH", TLS_CT_DSS_FIXED_DH},
{"ECDSA sign", TLS_CT_ECDSA_SIGN},
{"RSA fixed ECDH", TLS_CT_RSA_FIXED_ECDH},
{"ECDSA fixed ECDH", TLS_CT_ECDSA_FIXED_ECDH},
{"GOST01 Sign", TLS_CT_GOST01_SIGN},
{NULL}
};
static void ssl_print_client_cert_types(BIO *bio, SSL *s)
{
const unsigned char *p;
int i;
int cert_type_num = SSL_get0_certificate_types(s, &p);
if (!cert_type_num)
return;
BIO_puts(bio, "Client Certificate Types: ");
for (i = 0; i < cert_type_num; i++) {
unsigned char cert_type = p[i];
const char *cname = lookup((int)cert_type, cert_type_list, NULL);
if (i)
BIO_puts(bio, ", ");
if (cname != NULL)
BIO_puts(bio, cname);
else
BIO_printf(bio, "UNKNOWN (%d),", cert_type);
}
BIO_puts(bio, "\n");
}
static const char *get_sigtype(int nid)
{
switch (nid) {
case EVP_PKEY_RSA:
return "RSA";
case EVP_PKEY_RSA_PSS:
return "RSA-PSS";
case EVP_PKEY_DSA:
return "DSA";
case EVP_PKEY_EC:
return "ECDSA";
case NID_ED25519:
return "Ed25519";
case NID_ED448:
return "Ed448";
case NID_id_GostR3410_2001:
return "gost2001";
case NID_id_GostR3410_2012_256:
return "gost2012_256";
case NID_id_GostR3410_2012_512:
return "gost2012_512";
default:
return NULL;
}
}
static int do_print_sigalgs(BIO *out, SSL *s, int shared)
{
int i, nsig, client;
client = SSL_is_server(s) ? 0 : 1;
if (shared)
nsig = SSL_get_shared_sigalgs(s, 0, NULL, NULL, NULL, NULL, NULL);
else
nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
if (nsig == 0)
return 1;
if (shared)
BIO_puts(out, "Shared ");
if (client)
BIO_puts(out, "Requested ");
BIO_puts(out, "Signature Algorithms: ");
for (i = 0; i < nsig; i++) {
int hash_nid, sign_nid;
unsigned char rhash, rsign;
const char *sstr = NULL;
if (shared)
SSL_get_shared_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
&rsign, &rhash);
else
SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL, &rsign, &rhash);
if (i)
BIO_puts(out, ":");
sstr = get_sigtype(sign_nid);
if (sstr)
BIO_printf(out, "%s", sstr);
else
BIO_printf(out, "0x%02X", (int)rsign);
if (hash_nid != NID_undef)
BIO_printf(out, "+%s", OBJ_nid2sn(hash_nid));
else if (sstr == NULL)
BIO_printf(out, "+0x%02X", (int)rhash);
}
BIO_puts(out, "\n");
return 1;
}
int ssl_print_sigalgs(BIO *out, SSL *s)
{
int nid;
if (!SSL_is_server(s))
ssl_print_client_cert_types(out, s);
do_print_sigalgs(out, s, 0);
do_print_sigalgs(out, s, 1);
if (SSL_get_peer_signature_nid(s, &nid) && nid != NID_undef)
BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(nid));
if (SSL_get_peer_signature_type_nid(s, &nid))
BIO_printf(out, "Peer signature type: %s\n", get_sigtype(nid));
return 1;
}
#ifndef OPENSSL_NO_EC
int ssl_print_point_formats(BIO *out, SSL *s)
{
int i, nformats;
const char *pformats;
nformats = SSL_get0_ec_point_formats(s, &pformats);
if (nformats <= 0)
return 1;
BIO_puts(out, "Supported Elliptic Curve Point Formats: ");
for (i = 0; i < nformats; i++, pformats++) {
if (i)
BIO_puts(out, ":");
switch (*pformats) {
case TLSEXT_ECPOINTFORMAT_uncompressed:
BIO_puts(out, "uncompressed");
break;
case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime:
BIO_puts(out, "ansiX962_compressed_prime");
break;
case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2:
BIO_puts(out, "ansiX962_compressed_char2");
break;
default:
BIO_printf(out, "unknown(%d)", (int)*pformats);
break;
}
}
BIO_puts(out, "\n");
return 1;
}
int ssl_print_groups(BIO *out, SSL *s, int noshared)
{
int i, ngroups, *groups, nid;
const char *gname;
ngroups = SSL_get1_groups(s, NULL);
if (ngroups <= 0)
return 1;
groups = app_malloc(ngroups * sizeof(int), "groups to print");
SSL_get1_groups(s, groups);
BIO_puts(out, "Supported Elliptic Groups: ");
for (i = 0; i < ngroups; i++) {
if (i)
BIO_puts(out, ":");
nid = groups[i];
/* If unrecognised print out hex version */
if (nid & TLSEXT_nid_unknown) {
BIO_printf(out, "0x%04X", nid & 0xFFFF);
} else {
/* TODO(TLS1.3): Get group name here */
/* Use NIST name for curve if it exists */
gname = EC_curve_nid2nist(nid);
if (gname == NULL)
gname = OBJ_nid2sn(nid);
BIO_printf(out, "%s", gname);
}
}
OPENSSL_free(groups);
if (noshared) {
BIO_puts(out, "\n");
return 1;
}
BIO_puts(out, "\nShared Elliptic groups: ");
ngroups = SSL_get_shared_group(s, -1);
for (i = 0; i < ngroups; i++) {
if (i)
BIO_puts(out, ":");
nid = SSL_get_shared_group(s, i);
/* TODO(TLS1.3): Convert for DH groups */
gname = EC_curve_nid2nist(nid);
if (gname == NULL)
gname = OBJ_nid2sn(nid);
BIO_printf(out, "%s", gname);
}
if (ngroups == 0)
BIO_puts(out, "NONE");
BIO_puts(out, "\n");
return 1;
}
#endif
int ssl_print_tmp_key(BIO *out, SSL *s)
{
EVP_PKEY *key;
if (!SSL_get_peer_tmp_key(s, &key))
return 1;
BIO_puts(out, "Server Temp Key: ");
switch (EVP_PKEY_id(key)) {
case EVP_PKEY_RSA:
BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_bits(key));
break;
case EVP_PKEY_DH:
BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key));
break;
#ifndef OPENSSL_NO_EC
case EVP_PKEY_EC:
{
EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key);
int nid;
const char *cname;
nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
EC_KEY_free(ec);
cname = EC_curve_nid2nist(nid);
if (cname == NULL)
cname = OBJ_nid2sn(nid);
BIO_printf(out, "ECDH, %s, %d bits\n", cname, EVP_PKEY_bits(key));
}
break;
#endif
default:
BIO_printf(out, "%s, %d bits\n", OBJ_nid2sn(EVP_PKEY_id(key)),
EVP_PKEY_bits(key));
}
EVP_PKEY_free(key);
return 1;
}
long bio_dump_callback(BIO *bio, int cmd, const char *argp,
int argi, long argl, long ret)
{
BIO *out;
out = (BIO *)BIO_get_callback_arg(bio);
if (out == NULL)
return ret;
if (cmd == (BIO_CB_READ | BIO_CB_RETURN)) {
BIO_printf(out, "read from %p [%p] (%lu bytes => %ld (0x%lX))\n",
(void *)bio, (void *)argp, (unsigned long)argi, ret, ret);
BIO_dump(out, argp, (int)ret);
return ret;
} else if (cmd == (BIO_CB_WRITE | BIO_CB_RETURN)) {
BIO_printf(out, "write to %p [%p] (%lu bytes => %ld (0x%lX))\n",
(void *)bio, (void *)argp, (unsigned long)argi, ret, ret);
BIO_dump(out, argp, (int)ret);
}
return ret;
}
void apps_ssl_info_callback(const SSL *s, int where, int ret)
{
const char *str;
int w;
w = where & ~SSL_ST_MASK;
if (w & SSL_ST_CONNECT)
str = "SSL_connect";
else if (w & SSL_ST_ACCEPT)
str = "SSL_accept";
else
str = "undefined";
if (where & SSL_CB_LOOP) {
BIO_printf(bio_err, "%s:%s\n", str, SSL_state_string_long(s));
} else if (where & SSL_CB_ALERT) {
str = (where & SSL_CB_READ) ? "read" : "write";
BIO_printf(bio_err, "SSL3 alert %s:%s:%s\n",
str,
SSL_alert_type_string_long(ret),
SSL_alert_desc_string_long(ret));
} else if (where & SSL_CB_EXIT) {
if (ret == 0)
BIO_printf(bio_err, "%s:failed in %s\n",
str, SSL_state_string_long(s));
else if (ret < 0)
BIO_printf(bio_err, "%s:error in %s\n",
str, SSL_state_string_long(s));
}
}
static STRINT_PAIR ssl_versions[] = {
{"SSL 3.0", SSL3_VERSION},
{"TLS 1.0", TLS1_VERSION},
{"TLS 1.1", TLS1_1_VERSION},
{"TLS 1.2", TLS1_2_VERSION},
{"TLS 1.3", TLS1_3_VERSION},
{"DTLS 1.0", DTLS1_VERSION},
{"DTLS 1.0 (bad)", DTLS1_BAD_VER},
{NULL}
};
static STRINT_PAIR alert_types[] = {
{" close_notify", 0},
{" end_of_early_data", 1},
{" unexpected_message", 10},
{" bad_record_mac", 20},
{" decryption_failed", 21},
{" record_overflow", 22},
{" decompression_failure", 30},
{" handshake_failure", 40},
{" bad_certificate", 42},
{" unsupported_certificate", 43},
{" certificate_revoked", 44},
{" certificate_expired", 45},
{" certificate_unknown", 46},
{" illegal_parameter", 47},
{" unknown_ca", 48},
{" access_denied", 49},
{" decode_error", 50},
{" decrypt_error", 51},
{" export_restriction", 60},
{" protocol_version", 70},
{" insufficient_security", 71},
{" internal_error", 80},
{" inappropriate_fallback", 86},
{" user_canceled", 90},
{" no_renegotiation", 100},
{" missing_extension", 109},
{" unsupported_extension", 110},
{" certificate_unobtainable", 111},
{" unrecognized_name", 112},
{" bad_certificate_status_response", 113},
{" bad_certificate_hash_value", 114},
{" unknown_psk_identity", 115},
{" certificate_required", 116},
{NULL}
};
static STRINT_PAIR handshakes[] = {
{", HelloRequest", SSL3_MT_HELLO_REQUEST},
{", ClientHello", SSL3_MT_CLIENT_HELLO},
{", ServerHello", SSL3_MT_SERVER_HELLO},
{", HelloVerifyRequest", DTLS1_MT_HELLO_VERIFY_REQUEST},
{", NewSessionTicket", SSL3_MT_NEWSESSION_TICKET},
{", EndOfEarlyData", SSL3_MT_END_OF_EARLY_DATA},
{", EncryptedExtensions", SSL3_MT_ENCRYPTED_EXTENSIONS},
{", Certificate", SSL3_MT_CERTIFICATE},
{", ServerKeyExchange", SSL3_MT_SERVER_KEY_EXCHANGE},
{", CertificateRequest", SSL3_MT_CERTIFICATE_REQUEST},
{", ServerHelloDone", SSL3_MT_SERVER_DONE},
{", CertificateVerify", SSL3_MT_CERTIFICATE_VERIFY},
{", ClientKeyExchange", SSL3_MT_CLIENT_KEY_EXCHANGE},
{", Finished", SSL3_MT_FINISHED},
{", CertificateUrl", SSL3_MT_CERTIFICATE_URL},
{", CertificateStatus", SSL3_MT_CERTIFICATE_STATUS},
{", SupplementalData", SSL3_MT_SUPPLEMENTAL_DATA},
{", KeyUpdate", SSL3_MT_KEY_UPDATE},
#ifndef OPENSSL_NO_NEXTPROTONEG
{", NextProto", SSL3_MT_NEXT_PROTO},
#endif
{", MessageHash", SSL3_MT_MESSAGE_HASH},
{NULL}
};
void msg_cb(int write_p, int version, int content_type, const void *buf,
size_t len, SSL *ssl, void *arg)
{
BIO *bio = arg;
const char *str_write_p = write_p ? ">>>" : "<<<";
const char *str_version = lookup(version, ssl_versions, "???");
const char *str_content_type = "", *str_details1 = "", *str_details2 = "";
const unsigned char* bp = buf;
if (version == SSL3_VERSION ||
version == TLS1_VERSION ||
version == TLS1_1_VERSION ||
version == TLS1_2_VERSION ||
version == TLS1_3_VERSION ||
version == DTLS1_VERSION || version == DTLS1_BAD_VER) {
switch (content_type) {
case 20:
str_content_type = ", ChangeCipherSpec";
break;
case 21:
str_content_type = ", Alert";
str_details1 = ", ???";
if (len == 2) {
switch (bp[0]) {
case 1:
str_details1 = ", warning";
break;
case 2:
str_details1 = ", fatal";
break;
}
str_details2 = lookup((int)bp[1], alert_types, " ???");
}
break;
case 22:
str_content_type = ", Handshake";
str_details1 = "???";
if (len > 0)
str_details1 = lookup((int)bp[0], handshakes, "???");
break;
case 23:
str_content_type = ", ApplicationData";
break;
#ifndef OPENSSL_NO_HEARTBEATS
case 24:
str_details1 = ", Heartbeat";
if (len > 0) {
switch (bp[0]) {
case 1:
str_details1 = ", HeartbeatRequest";
break;
case 2:
str_details1 = ", HeartbeatResponse";
break;
}
}
break;
#endif
}
}
BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version,
str_content_type, (unsigned long)len, str_details1,
str_details2);
if (len > 0) {
size_t num, i;
BIO_printf(bio, " ");
num = len;
for (i = 0; i < num; i++) {
if (i % 16 == 0 && i > 0)
BIO_printf(bio, "\n ");
BIO_printf(bio, " %02x", ((const unsigned char *)buf)[i]);
}
if (i < len)
BIO_printf(bio, " ...");
BIO_printf(bio, "\n");
}
(void)BIO_flush(bio);
}
static STRINT_PAIR tlsext_types[] = {
{"server name", TLSEXT_TYPE_server_name},
{"max fragment length", TLSEXT_TYPE_max_fragment_length},
{"client certificate URL", TLSEXT_TYPE_client_certificate_url},
{"trusted CA keys", TLSEXT_TYPE_trusted_ca_keys},
{"truncated HMAC", TLSEXT_TYPE_truncated_hmac},
{"status request", TLSEXT_TYPE_status_request},
{"user mapping", TLSEXT_TYPE_user_mapping},
{"client authz", TLSEXT_TYPE_client_authz},
{"server authz", TLSEXT_TYPE_server_authz},
{"cert type", TLSEXT_TYPE_cert_type},
{"supported_groups", TLSEXT_TYPE_supported_groups},
{"EC point formats", TLSEXT_TYPE_ec_point_formats},
{"SRP", TLSEXT_TYPE_srp},
{"signature algorithms", TLSEXT_TYPE_signature_algorithms},
{"use SRTP", TLSEXT_TYPE_use_srtp},
{"heartbeat", TLSEXT_TYPE_heartbeat},
{"session ticket", TLSEXT_TYPE_session_ticket},
{"renegotiation info", TLSEXT_TYPE_renegotiate},
{"signed certificate timestamps", TLSEXT_TYPE_signed_certificate_timestamp},
{"TLS padding", TLSEXT_TYPE_padding},
#ifdef TLSEXT_TYPE_next_proto_neg
{"next protocol", TLSEXT_TYPE_next_proto_neg},
#endif
#ifdef TLSEXT_TYPE_encrypt_then_mac
{"encrypt-then-mac", TLSEXT_TYPE_encrypt_then_mac},
#endif
#ifdef TLSEXT_TYPE_application_layer_protocol_negotiation
{"application layer protocol negotiation",
TLSEXT_TYPE_application_layer_protocol_negotiation},
#endif
#ifdef TLSEXT_TYPE_extended_master_secret
{"extended master secret", TLSEXT_TYPE_extended_master_secret},
#endif
{"key share", TLSEXT_TYPE_key_share},
{"supported versions", TLSEXT_TYPE_supported_versions},
{"psk", TLSEXT_TYPE_psk},
{"psk kex modes", TLSEXT_TYPE_psk_kex_modes},
{"certificate authorities", TLSEXT_TYPE_certificate_authorities},
{"post handshake auth", TLSEXT_TYPE_post_handshake_auth},
{NULL}
};
+/* from rfc8446 4.2.3. + gost (https://tools.ietf.org/id/draft-smyshlyaev-tls12-gost-suites-04.html) */
+static STRINT_PAIR signature_tls13_scheme_list[] = {
+ {"rsa_pkcs1_sha1", 0x0201 /* TLSEXT_SIGALG_rsa_pkcs1_sha1 */},
+ {"ecdsa_sha1", 0x0203 /* TLSEXT_SIGALG_ecdsa_sha1 */},
+/* {"rsa_pkcs1_sha224", 0x0301 TLSEXT_SIGALG_rsa_pkcs1_sha224}, not in rfc8446 */
+/* {"ecdsa_sha224", 0x0303 TLSEXT_SIGALG_ecdsa_sha224} not in rfc8446 */
+ {"rsa_pkcs1_sha256", 0x0401 /* TLSEXT_SIGALG_rsa_pkcs1_sha256 */},
+ {"ecdsa_secp256r1_sha256", 0x0403 /* TLSEXT_SIGALG_ecdsa_secp256r1_sha256 */},
+ {"rsa_pkcs1_sha384", 0x0501 /* TLSEXT_SIGALG_rsa_pkcs1_sha384 */},
+ {"ecdsa_secp384r1_sha384", 0x0503 /* TLSEXT_SIGALG_ecdsa_secp384r1_sha384 */},
+ {"rsa_pkcs1_sha512", 0x0601 /* TLSEXT_SIGALG_rsa_pkcs1_sha512 */},
+ {"ecdsa_secp521r1_sha512", 0x0603 /* TLSEXT_SIGALG_ecdsa_secp521r1_sha512 */},
+ {"rsa_pss_rsae_sha256", 0x0804 /* TLSEXT_SIGALG_rsa_pss_rsae_sha256 */},
+ {"rsa_pss_rsae_sha384", 0x0805 /* TLSEXT_SIGALG_rsa_pss_rsae_sha384 */},
+ {"rsa_pss_rsae_sha512", 0x0806 /* TLSEXT_SIGALG_rsa_pss_rsae_sha512 */},
+ {"ed25519", 0x0807 /* TLSEXT_SIGALG_ed25519 */},
+ {"ed448", 0x0808 /* TLSEXT_SIGALG_ed448 */},
+ {"rsa_pss_pss_sha256", 0x0809 /* TLSEXT_SIGALG_rsa_pss_pss_sha256 */},
+ {"rsa_pss_pss_sha384", 0x080a /* TLSEXT_SIGALG_rsa_pss_pss_sha384 */},
+ {"rsa_pss_pss_sha512", 0x080b /* TLSEXT_SIGALG_rsa_pss_pss_sha512 */},
+ {"gostr34102001", 0xeded /* TLSEXT_SIGALG_gostr34102001_gostr3411 */},
+ {"gostr34102012_256", 0xeeee /* TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 */},
+ {"gostr34102012_512", 0xefef /* TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 */},
+ {NULL}
+};
+
+/* from rfc5246 7.4.1.4.1. */
+static STRINT_PAIR signature_tls12_alg_list[] = {
+ {"anonymous", TLSEXT_signature_anonymous /* 0 */},
+ {"RSA", TLSEXT_signature_rsa /* 1 */},
+ {"DSA", TLSEXT_signature_dsa /* 2 */},
+ {"ECDSA", TLSEXT_signature_ecdsa /* 3 */},
+ {NULL}
+};
+
+/* from rfc5246 7.4.1.4.1. */
+static STRINT_PAIR signature_tls12_hash_list[] = {
+ {"none", TLSEXT_hash_none /* 0 */},
+ {"MD5", TLSEXT_hash_md5 /* 1 */},
+ {"SHA1", TLSEXT_hash_sha1 /* 2 */},
+ {"SHA224", TLSEXT_hash_sha224 /* 3 */},
+ {"SHA256", TLSEXT_hash_sha256 /* 4 */},
+ {"SHA384", TLSEXT_hash_sha384 /* 5 */},
+ {"SHA512", TLSEXT_hash_sha512 /* 6 */},
+ {NULL}
+};
+
void tlsext_cb(SSL *s, int client_server, int type,
const unsigned char *data, int len, void *arg)
{
BIO *bio = arg;
const char *extname = lookup(type, tlsext_types, "unknown");
BIO_printf(bio, "TLS %s extension \"%s\" (id=%d), len=%d\n",
client_server ? "server" : "client", extname, type, len);
BIO_dump(bio, (const char *)data, len);
(void)BIO_flush(bio);
}
#ifndef OPENSSL_NO_SOCK
int generate_cookie_callback(SSL *ssl, unsigned char *cookie,
unsigned int *cookie_len)
{
unsigned char *buffer;
size_t length = 0;
unsigned short port;
BIO_ADDR *lpeer = NULL, *peer = NULL;
/* Initialize a random secret */
if (!cookie_initialized) {
if (RAND_bytes(cookie_secret, COOKIE_SECRET_LENGTH) <= 0) {
BIO_printf(bio_err, "error setting random cookie secret\n");
return 0;
}
cookie_initialized = 1;
}
if (SSL_is_dtls(ssl)) {
lpeer = peer = BIO_ADDR_new();
if (peer == NULL) {
BIO_printf(bio_err, "memory full\n");
return 0;
}
/* Read peer information */
(void)BIO_dgram_get_peer(SSL_get_rbio(ssl), peer);
} else {
peer = ourpeer;
}
/* Create buffer with peer's address and port */
if (!BIO_ADDR_rawaddress(peer, NULL, &length)) {
BIO_printf(bio_err, "Failed getting peer address\n");
return 0;
}
OPENSSL_assert(length != 0);
port = BIO_ADDR_rawport(peer);
length += sizeof(port);
buffer = app_malloc(length, "cookie generate buffer");
memcpy(buffer, &port, sizeof(port));
BIO_ADDR_rawaddress(peer, buffer + sizeof(port), NULL);
/* Calculate HMAC of buffer using the secret */
HMAC(EVP_sha1(), cookie_secret, COOKIE_SECRET_LENGTH,
buffer, length, cookie, cookie_len);
OPENSSL_free(buffer);
BIO_ADDR_free(lpeer);
return 1;
}
int verify_cookie_callback(SSL *ssl, const unsigned char *cookie,
unsigned int cookie_len)
{
unsigned char result[EVP_MAX_MD_SIZE];
unsigned int resultlength;
/* Note: we check cookie_initialized because if it's not,
* it cannot be valid */
if (cookie_initialized
&& generate_cookie_callback(ssl, result, &resultlength)
&& cookie_len == resultlength
&& memcmp(result, cookie, resultlength) == 0)
return 1;
return 0;
}
int generate_stateless_cookie_callback(SSL *ssl, unsigned char *cookie,
size_t *cookie_len)
{
unsigned int temp;
int res = generate_cookie_callback(ssl, cookie, &temp);
*cookie_len = temp;
return res;
}
int verify_stateless_cookie_callback(SSL *ssl, const unsigned char *cookie,
size_t cookie_len)
{
return verify_cookie_callback(ssl, cookie, cookie_len);
}
#endif
/*
* Example of extended certificate handling. Where the standard support of
* one certificate per algorithm is not sufficient an application can decide
* which certificate(s) to use at runtime based on whatever criteria it deems
* appropriate.
*/
/* Linked list of certificates, keys and chains */
struct ssl_excert_st {
int certform;
const char *certfile;
int keyform;
const char *keyfile;
const char *chainfile;
X509 *cert;
EVP_PKEY *key;
STACK_OF(X509) *chain;
int build_chain;
struct ssl_excert_st *next, *prev;
};
static STRINT_PAIR chain_flags[] = {
{"Overall Validity", CERT_PKEY_VALID},
{"Sign with EE key", CERT_PKEY_SIGN},
{"EE signature", CERT_PKEY_EE_SIGNATURE},
{"CA signature", CERT_PKEY_CA_SIGNATURE},
{"EE key parameters", CERT_PKEY_EE_PARAM},
{"CA key parameters", CERT_PKEY_CA_PARAM},
{"Explicitly sign with EE key", CERT_PKEY_EXPLICIT_SIGN},
{"Issuer Name", CERT_PKEY_ISSUER_NAME},
{"Certificate Type", CERT_PKEY_CERT_TYPE},
{NULL}
};
static void print_chain_flags(SSL *s, int flags)
{
STRINT_PAIR *pp;
for (pp = chain_flags; pp->name; ++pp)
BIO_printf(bio_err, "\t%s: %s\n",
pp->name,
(flags & pp->retval) ? "OK" : "NOT OK");
BIO_printf(bio_err, "\tSuite B: ");
if (SSL_set_cert_flags(s, 0) & SSL_CERT_FLAG_SUITEB_128_LOS)
BIO_puts(bio_err, flags & CERT_PKEY_SUITEB ? "OK\n" : "NOT OK\n");
else
BIO_printf(bio_err, "not tested\n");
}
/*
* Very basic selection callback: just use any certificate chain reported as
* valid. More sophisticated could prioritise according to local policy.
*/
static int set_cert_cb(SSL *ssl, void *arg)
{
int i, rv;
SSL_EXCERT *exc = arg;
#ifdef CERT_CB_TEST_RETRY
static int retry_cnt;
if (retry_cnt < 5) {
retry_cnt++;
BIO_printf(bio_err,
"Certificate callback retry test: count %d\n",
retry_cnt);
return -1;
}
#endif
SSL_certs_clear(ssl);
if (exc == NULL)
return 1;
/*
* Go to end of list and traverse backwards since we prepend newer
* entries this retains the original order.
*/
while (exc->next != NULL)
exc = exc->next;
i = 0;
while (exc != NULL) {
i++;
rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain);
BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i);
X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0,
get_nameopt());
BIO_puts(bio_err, "\n");
print_chain_flags(ssl, rv);
if (rv & CERT_PKEY_VALID) {
if (!SSL_use_certificate(ssl, exc->cert)
|| !SSL_use_PrivateKey(ssl, exc->key)) {
return 0;
}
/*
* NB: we wouldn't normally do this as it is not efficient
* building chains on each connection better to cache the chain
* in advance.
*/
if (exc->build_chain) {
if (!SSL_build_cert_chain(ssl, 0))
return 0;
} else if (exc->chain != NULL) {
SSL_set1_chain(ssl, exc->chain);
}
}
exc = exc->prev;
}
return 1;
}
void ssl_ctx_set_excert(SSL_CTX *ctx, SSL_EXCERT *exc)
{
SSL_CTX_set_cert_cb(ctx, set_cert_cb, exc);
}
static int ssl_excert_prepend(SSL_EXCERT **pexc)
{
SSL_EXCERT *exc = app_malloc(sizeof(*exc), "prepend cert");
memset(exc, 0, sizeof(*exc));
exc->next = *pexc;
*pexc = exc;
if (exc->next) {
exc->certform = exc->next->certform;
exc->keyform = exc->next->keyform;
exc->next->prev = exc;
} else {
exc->certform = FORMAT_PEM;
exc->keyform = FORMAT_PEM;
}
return 1;
}
void ssl_excert_free(SSL_EXCERT *exc)
{
SSL_EXCERT *curr;
if (exc == NULL)
return;
while (exc) {
X509_free(exc->cert);
EVP_PKEY_free(exc->key);
sk_X509_pop_free(exc->chain, X509_free);
curr = exc;
exc = exc->next;
OPENSSL_free(curr);
}
}
int load_excert(SSL_EXCERT **pexc)
{
SSL_EXCERT *exc = *pexc;
if (exc == NULL)
return 1;
/* If nothing in list, free and set to NULL */
if (exc->certfile == NULL && exc->next == NULL) {
ssl_excert_free(exc);
*pexc = NULL;
return 1;
}
for (; exc; exc = exc->next) {
if (exc->certfile == NULL) {
BIO_printf(bio_err, "Missing filename\n");
return 0;
}
exc->cert = load_cert(exc->certfile, exc->certform,
"Server Certificate");
if (exc->cert == NULL)
return 0;
if (exc->keyfile != NULL) {
exc->key = load_key(exc->keyfile, exc->keyform,
0, NULL, NULL, "Server Key");
} else {
exc->key = load_key(exc->certfile, exc->certform,
0, NULL, NULL, "Server Key");
}
if (exc->key == NULL)
return 0;
if (exc->chainfile != NULL) {
if (!load_certs(exc->chainfile, &exc->chain, FORMAT_PEM, NULL,
"Server Chain"))
return 0;
}
}
return 1;
}
enum range { OPT_X_ENUM };
int args_excert(int opt, SSL_EXCERT **pexc)
{
SSL_EXCERT *exc = *pexc;
assert(opt > OPT_X__FIRST);
assert(opt < OPT_X__LAST);
if (exc == NULL) {
if (!ssl_excert_prepend(&exc)) {
BIO_printf(bio_err, " %s: Error initialising xcert\n",
opt_getprog());
goto err;
}
*pexc = exc;
}
switch ((enum range)opt) {
case OPT_X__FIRST:
case OPT_X__LAST:
return 0;
case OPT_X_CERT:
if (exc->certfile != NULL && !ssl_excert_prepend(&exc)) {
BIO_printf(bio_err, "%s: Error adding xcert\n", opt_getprog());
goto err;
}
*pexc = exc;
exc->certfile = opt_arg();
break;
case OPT_X_KEY:
if (exc->keyfile != NULL) {
BIO_printf(bio_err, "%s: Key already specified\n", opt_getprog());
goto err;
}
exc->keyfile = opt_arg();
break;
case OPT_X_CHAIN:
if (exc->chainfile != NULL) {
BIO_printf(bio_err, "%s: Chain already specified\n",
opt_getprog());
goto err;
}
exc->chainfile = opt_arg();
break;
case OPT_X_CHAIN_BUILD:
exc->build_chain = 1;
break;
case OPT_X_CERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->certform))
return 0;
break;
case OPT_X_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &exc->keyform))
return 0;
break;
}
return 1;
err:
ERR_print_errors(bio_err);
ssl_excert_free(exc);
*pexc = NULL;
return 0;
}
static void print_raw_cipherlist(SSL *s)
{
const unsigned char *rlist;
static const unsigned char scsv_id[] = { 0, 0xFF };
size_t i, rlistlen, num;
if (!SSL_is_server(s))
return;
num = SSL_get0_raw_cipherlist(s, NULL);
OPENSSL_assert(num == 2);
rlistlen = SSL_get0_raw_cipherlist(s, &rlist);
BIO_puts(bio_err, "Client cipher list: ");
for (i = 0; i < rlistlen; i += num, rlist += num) {
const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist);
if (i)
BIO_puts(bio_err, ":");
if (c != NULL) {
BIO_puts(bio_err, SSL_CIPHER_get_name(c));
} else if (memcmp(rlist, scsv_id, num) == 0) {
BIO_puts(bio_err, "SCSV");
} else {
size_t j;
BIO_puts(bio_err, "0x");
for (j = 0; j < num; j++)
BIO_printf(bio_err, "%02X", rlist[j]);
}
}
BIO_puts(bio_err, "\n");
}
/*
* Hex encoder for TLSA RRdata, not ':' delimited.
*/
static char *hexencode(const unsigned char *data, size_t len)
{
static const char *hex = "0123456789abcdef";
char *out;
char *cp;
size_t outlen = 2 * len + 1;
int ilen = (int) outlen;
if (outlen < len || ilen < 0 || outlen != (size_t)ilen) {
BIO_printf(bio_err, "%s: %zu-byte buffer too large to hexencode\n",
opt_getprog(), len);
exit(1);
}
cp = out = app_malloc(ilen, "TLSA hex data buffer");
while (len-- > 0) {
*cp++ = hex[(*data >> 4) & 0x0f];
*cp++ = hex[*data++ & 0x0f];
}
*cp = '\0';
return out;
}
void print_verify_detail(SSL *s, BIO *bio)
{
int mdpth;
EVP_PKEY *mspki;
long verify_err = SSL_get_verify_result(s);
if (verify_err == X509_V_OK) {
const char *peername = SSL_get0_peername(s);
BIO_printf(bio, "Verification: OK\n");
if (peername != NULL)
BIO_printf(bio, "Verified peername: %s\n", peername);
} else {
const char *reason = X509_verify_cert_error_string(verify_err);
BIO_printf(bio, "Verification error: %s\n", reason);
}
if ((mdpth = SSL_get0_dane_authority(s, NULL, &mspki)) >= 0) {
uint8_t usage, selector, mtype;
const unsigned char *data = NULL;
size_t dlen = 0;
char *hexdata;
mdpth = SSL_get0_dane_tlsa(s, &usage, &selector, &mtype, &data, &dlen);
/*
* The TLSA data field can be quite long when it is a certificate,
* public key or even a SHA2-512 digest. Because the initial octets of
* ASN.1 certificates and public keys contain mostly boilerplate OIDs
* and lengths, we show the last 12 bytes of the data instead, as these
* are more likely to distinguish distinct TLSA records.
*/
#define TLSA_TAIL_SIZE 12
if (dlen > TLSA_TAIL_SIZE)
hexdata = hexencode(data + dlen - TLSA_TAIL_SIZE, TLSA_TAIL_SIZE);
else
hexdata = hexencode(data, dlen);
BIO_printf(bio, "DANE TLSA %d %d %d %s%s %s at depth %d\n",
usage, selector, mtype,
(dlen > TLSA_TAIL_SIZE) ? "..." : "", hexdata,
(mspki != NULL) ? "signed the certificate" :
mdpth ? "matched TA certificate" : "matched EE certificate",
mdpth);
OPENSSL_free(hexdata);
}
}
void print_ssl_summary(SSL *s)
{
const SSL_CIPHER *c;
X509 *peer;
BIO_printf(bio_err, "Protocol version: %s\n", SSL_get_version(s));
print_raw_cipherlist(s);
c = SSL_get_current_cipher(s);
BIO_printf(bio_err, "Ciphersuite: %s\n", SSL_CIPHER_get_name(c));
do_print_sigalgs(bio_err, s, 0);
peer = SSL_get_peer_certificate(s);
if (peer != NULL) {
int nid;
BIO_puts(bio_err, "Peer certificate: ");
X509_NAME_print_ex(bio_err, X509_get_subject_name(peer),
0, get_nameopt());
BIO_puts(bio_err, "\n");
if (SSL_get_peer_signature_nid(s, &nid))
BIO_printf(bio_err, "Hash used: %s\n", OBJ_nid2sn(nid));
if (SSL_get_peer_signature_type_nid(s, &nid))
BIO_printf(bio_err, "Signature type: %s\n", get_sigtype(nid));
print_verify_detail(s, bio_err);
} else {
BIO_puts(bio_err, "No peer certificate\n");
}
X509_free(peer);
#ifndef OPENSSL_NO_EC
ssl_print_point_formats(bio_err, s);
if (SSL_is_server(s))
ssl_print_groups(bio_err, s, 1);
else
ssl_print_tmp_key(bio_err, s);
#else
if (!SSL_is_server(s))
ssl_print_tmp_key(bio_err, s);
#endif
}
int config_ctx(SSL_CONF_CTX *cctx, STACK_OF(OPENSSL_STRING) *str,
SSL_CTX *ctx)
{
int i;
SSL_CONF_CTX_set_ssl_ctx(cctx, ctx);
for (i = 0; i < sk_OPENSSL_STRING_num(str); i += 2) {
const char *flag = sk_OPENSSL_STRING_value(str, i);
const char *arg = sk_OPENSSL_STRING_value(str, i + 1);
if (SSL_CONF_cmd(cctx, flag, arg) <= 0) {
if (arg != NULL)
BIO_printf(bio_err, "Error with command: \"%s %s\"\n",
flag, arg);
else
BIO_printf(bio_err, "Error with command: \"%s\"\n", flag);
ERR_print_errors(bio_err);
return 0;
}
}
if (!SSL_CONF_CTX_finish(cctx)) {
BIO_puts(bio_err, "Error finishing context\n");
ERR_print_errors(bio_err);
return 0;
}
return 1;
}
static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls)
{
X509_CRL *crl;
int i;
for (i = 0; i < sk_X509_CRL_num(crls); i++) {
crl = sk_X509_CRL_value(crls, i);
X509_STORE_add_crl(st, crl);
}
return 1;
}
int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download)
{
X509_STORE *st;
st = SSL_CTX_get_cert_store(ctx);
add_crls_store(st, crls);
if (crl_download)
store_setup_crl_download(st);
return 1;
}
int ssl_load_stores(SSL_CTX *ctx,
const char *vfyCApath, const char *vfyCAfile,
const char *chCApath, const char *chCAfile,
STACK_OF(X509_CRL) *crls, int crl_download)
{
X509_STORE *vfy = NULL, *ch = NULL;
int rv = 0;
if (vfyCApath != NULL || vfyCAfile != NULL) {
vfy = X509_STORE_new();
if (vfy == NULL)
goto err;
if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath))
goto err;
add_crls_store(vfy, crls);
SSL_CTX_set1_verify_cert_store(ctx, vfy);
if (crl_download)
store_setup_crl_download(vfy);
}
if (chCApath != NULL || chCAfile != NULL) {
ch = X509_STORE_new();
if (ch == NULL)
goto err;
if (!X509_STORE_load_locations(ch, chCAfile, chCApath))
goto err;
SSL_CTX_set1_chain_cert_store(ctx, ch);
}
rv = 1;
err:
X509_STORE_free(vfy);
X509_STORE_free(ch);
return rv;
}
/* Verbose print out of security callback */
typedef struct {
BIO *out;
int verbose;
int (*old_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid,
void *other, void *ex);
} security_debug_ex;
static STRINT_PAIR callback_types[] = {
{"Supported Ciphersuite", SSL_SECOP_CIPHER_SUPPORTED},
{"Shared Ciphersuite", SSL_SECOP_CIPHER_SHARED},
{"Check Ciphersuite", SSL_SECOP_CIPHER_CHECK},
#ifndef OPENSSL_NO_DH
{"Temp DH key bits", SSL_SECOP_TMP_DH},
#endif
{"Supported Curve", SSL_SECOP_CURVE_SUPPORTED},
{"Shared Curve", SSL_SECOP_CURVE_SHARED},
{"Check Curve", SSL_SECOP_CURVE_CHECK},
- {"Supported Signature Algorithm digest", SSL_SECOP_SIGALG_SUPPORTED},
- {"Shared Signature Algorithm digest", SSL_SECOP_SIGALG_SHARED},
- {"Check Signature Algorithm digest", SSL_SECOP_SIGALG_CHECK},
+ {"Supported Signature Algorithm", SSL_SECOP_SIGALG_SUPPORTED},
+ {"Shared Signature Algorithm", SSL_SECOP_SIGALG_SHARED},
+ {"Check Signature Algorithm", SSL_SECOP_SIGALG_CHECK},
{"Signature Algorithm mask", SSL_SECOP_SIGALG_MASK},
{"Certificate chain EE key", SSL_SECOP_EE_KEY},
{"Certificate chain CA key", SSL_SECOP_CA_KEY},
{"Peer Chain EE key", SSL_SECOP_PEER_EE_KEY},
{"Peer Chain CA key", SSL_SECOP_PEER_CA_KEY},
{"Certificate chain CA digest", SSL_SECOP_CA_MD},
{"Peer chain CA digest", SSL_SECOP_PEER_CA_MD},
{"SSL compression", SSL_SECOP_COMPRESSION},
{"Session ticket", SSL_SECOP_TICKET},
{NULL}
};
static int security_callback_debug(const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid,
void *other, void *ex)
{
security_debug_ex *sdb = ex;
int rv, show_bits = 1, cert_md = 0;
const char *nm;
+ int show_nm;
rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
if (rv == 1 && sdb->verbose < 2)
return 1;
BIO_puts(sdb->out, "Security callback: ");
nm = lookup(op, callback_types, NULL);
+ show_nm = nm != NULL;
switch (op) {
case SSL_SECOP_TICKET:
case SSL_SECOP_COMPRESSION:
show_bits = 0;
- nm = NULL;
+ show_nm = 0;
break;
case SSL_SECOP_VERSION:
BIO_printf(sdb->out, "Version=%s", lookup(nid, ssl_versions, "???"));
show_bits = 0;
- nm = NULL;
+ show_nm = 0;
break;
case SSL_SECOP_CA_MD:
case SSL_SECOP_PEER_CA_MD:
cert_md = 1;
break;
+ case SSL_SECOP_SIGALG_SUPPORTED:
+ case SSL_SECOP_SIGALG_SHARED:
+ case SSL_SECOP_SIGALG_CHECK:
+ case SSL_SECOP_SIGALG_MASK:
+ show_nm = 0;
+ break;
}
- if (nm != NULL)
+ if (show_nm)
BIO_printf(sdb->out, "%s=", nm);
switch (op & SSL_SECOP_OTHER_TYPE) {
case SSL_SECOP_OTHER_CIPHER:
BIO_puts(sdb->out, SSL_CIPHER_get_name(other));
break;
#ifndef OPENSSL_NO_EC
case SSL_SECOP_OTHER_CURVE:
{
const char *cname;
cname = EC_curve_nid2nist(nid);
if (cname == NULL)
cname = OBJ_nid2sn(nid);
BIO_puts(sdb->out, cname);
}
break;
#endif
#ifndef OPENSSL_NO_DH
case SSL_SECOP_OTHER_DH:
{
DH *dh = other;
BIO_printf(sdb->out, "%d", DH_bits(dh));
break;
}
#endif
case SSL_SECOP_OTHER_CERT:
{
if (cert_md) {
int sig_nid = X509_get_signature_nid(other);
BIO_puts(sdb->out, OBJ_nid2sn(sig_nid));
} else {
EVP_PKEY *pkey = X509_get0_pubkey(other);
const char *algname = "";
EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL,
&algname, EVP_PKEY_get0_asn1(pkey));
BIO_printf(sdb->out, "%s, bits=%d",
algname, EVP_PKEY_bits(pkey));
}
break;
}
case SSL_SECOP_OTHER_SIGALG:
{
const unsigned char *salg = other;
const char *sname = NULL;
- switch (salg[1]) {
- case TLSEXT_signature_anonymous:
- sname = "anonymous";
- break;
- case TLSEXT_signature_rsa:
- sname = "RSA";
- break;
- case TLSEXT_signature_dsa:
- sname = "DSA";
- break;
- case TLSEXT_signature_ecdsa:
- sname = "ECDSA";
- break;
- }
+ int raw_sig_code = (salg[0] << 8) + salg[1]; /* always big endian (msb, lsb) */
+ /* raw_sig_code: signature_scheme from tls1.3, or signature_and_hash from tls1.2 */
- BIO_puts(sdb->out, OBJ_nid2sn(nid));
- if (sname)
- BIO_printf(sdb->out, ", algorithm=%s", sname);
+ if (nm != NULL)
+ BIO_printf(sdb->out, "%s", nm);
else
- BIO_printf(sdb->out, ", algid=%d", salg[1]);
- break;
+ BIO_printf(sdb->out, "s_cb.c:security_callback_debug op=0x%x", op);
+
+ sname = lookup(raw_sig_code, signature_tls13_scheme_list, NULL);
+ if (sname != NULL) {
+ BIO_printf(sdb->out, " scheme=%s", sname);
+ } else {
+ int alg_code = salg[1];
+ int hash_code = salg[0];
+ const char *alg_str = lookup(alg_code, signature_tls12_alg_list, NULL);
+ const char *hash_str = lookup(hash_code, signature_tls12_hash_list, NULL);
+
+ if (alg_str != NULL && hash_str != NULL)
+ BIO_printf(sdb->out, " digest=%s, algorithm=%s", hash_str, alg_str);
+ else
+ BIO_printf(sdb->out, " scheme=unknown(0x%04x)", raw_sig_code);
+ }
}
}
if (show_bits)
BIO_printf(sdb->out, ", security bits=%d", bits);
BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no");
return rv;
}
void ssl_ctx_security_debug(SSL_CTX *ctx, int verbose)
{
static security_debug_ex sdb;
sdb.out = bio_err;
sdb.verbose = verbose;
sdb.old_cb = SSL_CTX_get_security_callback(ctx);
SSL_CTX_set_security_callback(ctx, security_callback_debug);
SSL_CTX_set0_security_ex_data(ctx, &sdb);
}
static void keylog_callback(const SSL *ssl, const char *line)
{
if (bio_keylog == NULL) {
BIO_printf(bio_err, "Keylog callback is invoked without valid file!\n");
return;
}
/*
* There might be concurrent writers to the keylog file, so we must ensure
* that the given line is written at once.
*/
BIO_printf(bio_keylog, "%s\n", line);
(void)BIO_flush(bio_keylog);
}
int set_keylog_file(SSL_CTX *ctx, const char *keylog_file)
{
/* Close any open files */
BIO_free_all(bio_keylog);
bio_keylog = NULL;
if (ctx == NULL || keylog_file == NULL) {
/* Keylogging is disabled, OK. */
return 0;
}
/*
* Append rather than write in order to allow concurrent modification.
* Furthermore, this preserves existing keylog files which is useful when
* the tool is run multiple times.
*/
bio_keylog = BIO_new_file(keylog_file, "a");
if (bio_keylog == NULL) {
BIO_printf(bio_err, "Error writing keylog file %s\n", keylog_file);
return 1;
}
/* Write a header for seekable, empty files (this excludes pipes). */
if (BIO_tell(bio_keylog) == 0) {
BIO_puts(bio_keylog,
"# SSL/TLS secrets log file, generated by OpenSSL\n");
(void)BIO_flush(bio_keylog);
}
SSL_CTX_set_keylog_callback(ctx, keylog_callback);
return 0;
}
void print_ca_names(BIO *bio, SSL *s)
{
const char *cs = SSL_is_server(s) ? "server" : "client";
const STACK_OF(X509_NAME) *sk = SSL_get0_peer_CA_list(s);
int i;
if (sk == NULL || sk_X509_NAME_num(sk) == 0) {
BIO_printf(bio, "---\nNo %s certificate CA names sent\n", cs);
return;
}
BIO_printf(bio, "---\nAcceptable %s certificate CA names\n",cs);
for (i = 0; i < sk_X509_NAME_num(sk); i++) {
X509_NAME_print_ex(bio, sk_X509_NAME_value(sk, i), 0, get_nameopt());
BIO_write(bio, "\n", 1);
}
}
diff --git a/apps/s_client.c b/apps/s_client.c
index 4dd6e2fef4e4..b85339a0b870 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -1,3544 +1,3544 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2005 Nokia. All rights reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <openssl/e_os2.h>
#ifndef OPENSSL_NO_SOCK
/*
* With IPv6, it looks like Digital has mixed up the proper order of
* recursive header file inclusion, resulting in the compiler complaining
* that u_int isn't defined, but only if _POSIX_C_SOURCE is defined, which is
* needed to have fileno() declared correctly... So let's define u_int
*/
#if defined(OPENSSL_SYS_VMS_DECC) && !defined(__U_INT)
# define __U_INT
typedef unsigned int u_int;
#endif
#include "apps.h"
#include "progs.h"
#include <openssl/x509.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/rand.h>
#include <openssl/ocsp.h>
#include <openssl/bn.h>
#include <openssl/async.h>
#ifndef OPENSSL_NO_SRP
# include <openssl/srp.h>
#endif
#ifndef OPENSSL_NO_CT
# include <openssl/ct.h>
#endif
#include "s_apps.h"
#include "timeouts.h"
#include "internal/sockets.h"
#if defined(__has_feature)
# if __has_feature(memory_sanitizer)
# include <sanitizer/msan_interface.h>
# endif
#endif
#undef BUFSIZZ
#define BUFSIZZ 1024*8
#define S_CLIENT_IRC_READ_TIMEOUT 8
static char *prog;
static int c_debug = 0;
static int c_showcerts = 0;
static char *keymatexportlabel = NULL;
static int keymatexportlen = 20;
static BIO *bio_c_out = NULL;
static int c_quiet = 0;
static char *sess_out = NULL;
static SSL_SESSION *psksess = NULL;
static void print_stuff(BIO *berr, SSL *con, int full);
#ifndef OPENSSL_NO_OCSP
static int ocsp_resp_cb(SSL *s, void *arg);
#endif
static int ldap_ExtendedResponse_parse(const char *buf, long rem);
static int is_dNS_name(const char *host);
static int saved_errno;
static void save_errno(void)
{
saved_errno = errno;
errno = 0;
}
static int restore_errno(void)
{
int ret = errno;
errno = saved_errno;
return ret;
}
static void do_ssl_shutdown(SSL *ssl)
{
int ret;
do {
/* We only do unidirectional shutdown */
ret = SSL_shutdown(ssl);
if (ret < 0) {
switch (SSL_get_error(ssl, ret)) {
case SSL_ERROR_WANT_READ:
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_ASYNC:
case SSL_ERROR_WANT_ASYNC_JOB:
/* We just do busy waiting. Nothing clever */
continue;
}
ret = 0;
}
} while (ret < 0);
}
/* Default PSK identity and key */
static char *psk_identity = "Client_identity";
#ifndef OPENSSL_NO_PSK
static unsigned int psk_client_cb(SSL *ssl, const char *hint, char *identity,
unsigned int max_identity_len,
unsigned char *psk,
unsigned int max_psk_len)
{
int ret;
long key_len;
unsigned char *key;
if (c_debug)
BIO_printf(bio_c_out, "psk_client_cb\n");
if (!hint) {
/* no ServerKeyExchange message */
if (c_debug)
BIO_printf(bio_c_out,
"NULL received PSK identity hint, continuing anyway\n");
} else if (c_debug) {
BIO_printf(bio_c_out, "Received PSK identity hint '%s'\n", hint);
}
/*
* lookup PSK identity and PSK key based on the given identity hint here
*/
ret = BIO_snprintf(identity, max_identity_len, "%s", psk_identity);
if (ret < 0 || (unsigned int)ret > max_identity_len)
goto out_err;
if (c_debug)
BIO_printf(bio_c_out, "created identity '%s' len=%d\n", identity,
ret);
/* convert the PSK key to binary */
key = OPENSSL_hexstr2buf(psk_key, &key_len);
if (key == NULL) {
BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
psk_key);
return 0;
}
if (max_psk_len > INT_MAX || key_len > (long)max_psk_len) {
BIO_printf(bio_err,
"psk buffer of callback is too small (%d) for key (%ld)\n",
max_psk_len, key_len);
OPENSSL_free(key);
return 0;
}
memcpy(psk, key, key_len);
OPENSSL_free(key);
if (c_debug)
BIO_printf(bio_c_out, "created PSK len=%ld\n", key_len);
return key_len;
out_err:
if (c_debug)
BIO_printf(bio_err, "Error in PSK client callback\n");
return 0;
}
#endif
const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
const unsigned char tls13_aes256gcmsha384_id[] = { 0x13, 0x02 };
static int psk_use_session_cb(SSL *s, const EVP_MD *md,
const unsigned char **id, size_t *idlen,
SSL_SESSION **sess)
{
SSL_SESSION *usesess = NULL;
const SSL_CIPHER *cipher = NULL;
if (psksess != NULL) {
SSL_SESSION_up_ref(psksess);
usesess = psksess;
} else {
long key_len;
unsigned char *key = OPENSSL_hexstr2buf(psk_key, &key_len);
if (key == NULL) {
BIO_printf(bio_err, "Could not convert PSK key '%s' to buffer\n",
psk_key);
return 0;
}
/* We default to SHA-256 */
cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
if (cipher == NULL) {
BIO_printf(bio_err, "Error finding suitable ciphersuite\n");
OPENSSL_free(key);
return 0;
}
usesess = SSL_SESSION_new();
if (usesess == NULL
|| !SSL_SESSION_set1_master_key(usesess, key, key_len)
|| !SSL_SESSION_set_cipher(usesess, cipher)
|| !SSL_SESSION_set_protocol_version(usesess, TLS1_3_VERSION)) {
OPENSSL_free(key);
goto err;
}
OPENSSL_free(key);
}
cipher = SSL_SESSION_get0_cipher(usesess);
if (cipher == NULL)
goto err;
if (md != NULL && SSL_CIPHER_get_handshake_digest(cipher) != md) {
/* PSK not usable, ignore it */
*id = NULL;
*idlen = 0;
*sess = NULL;
SSL_SESSION_free(usesess);
} else {
*sess = usesess;
*id = (unsigned char *)psk_identity;
*idlen = strlen(psk_identity);
}
return 1;
err:
SSL_SESSION_free(usesess);
return 0;
}
/* This is a context that we pass to callbacks */
typedef struct tlsextctx_st {
BIO *biodebug;
int ack;
} tlsextctx;
static int ssl_servername_cb(SSL *s, int *ad, void *arg)
{
tlsextctx *p = (tlsextctx *) arg;
const char *hn = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
if (SSL_get_servername_type(s) != -1)
p->ack = !SSL_session_reused(s) && hn != NULL;
else
BIO_printf(bio_err, "Can't use SSL_get_servername\n");
return SSL_TLSEXT_ERR_OK;
}
#ifndef OPENSSL_NO_SRP
/* This is a context that we pass to all callbacks */
typedef struct srp_arg_st {
char *srppassin;
char *srplogin;
int msg; /* copy from c_msg */
int debug; /* copy from c_debug */
int amp; /* allow more groups */
int strength; /* minimal size for N */
} SRP_ARG;
# define SRP_NUMBER_ITERATIONS_FOR_PRIME 64
static int srp_Verify_N_and_g(const BIGNUM *N, const BIGNUM *g)
{
BN_CTX *bn_ctx = BN_CTX_new();
BIGNUM *p = BN_new();
BIGNUM *r = BN_new();
int ret =
g != NULL && N != NULL && bn_ctx != NULL && BN_is_odd(N) &&
BN_is_prime_ex(N, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 &&
p != NULL && BN_rshift1(p, N) &&
/* p = (N-1)/2 */
BN_is_prime_ex(p, SRP_NUMBER_ITERATIONS_FOR_PRIME, bn_ctx, NULL) == 1 &&
r != NULL &&
/* verify g^((N-1)/2) == -1 (mod N) */
BN_mod_exp(r, g, p, N, bn_ctx) &&
BN_add_word(r, 1) && BN_cmp(r, N) == 0;
BN_free(r);
BN_free(p);
BN_CTX_free(bn_ctx);
return ret;
}
/*-
* This callback is used here for two purposes:
* - extended debugging
* - making some primality tests for unknown groups
* The callback is only called for a non default group.
*
* An application does not need the call back at all if
* only the standard groups are used. In real life situations,
* client and server already share well known groups,
* thus there is no need to verify them.
* Furthermore, in case that a server actually proposes a group that
* is not one of those defined in RFC 5054, it is more appropriate
* to add the group to a static list and then compare since
* primality tests are rather cpu consuming.
*/
static int ssl_srp_verify_param_cb(SSL *s, void *arg)
{
SRP_ARG *srp_arg = (SRP_ARG *)arg;
BIGNUM *N = NULL, *g = NULL;
if (((N = SSL_get_srp_N(s)) == NULL) || ((g = SSL_get_srp_g(s)) == NULL))
return 0;
if (srp_arg->debug || srp_arg->msg || srp_arg->amp == 1) {
BIO_printf(bio_err, "SRP parameters:\n");
BIO_printf(bio_err, "\tN=");
BN_print(bio_err, N);
BIO_printf(bio_err, "\n\tg=");
BN_print(bio_err, g);
BIO_printf(bio_err, "\n");
}
if (SRP_check_known_gN_param(g, N))
return 1;
if (srp_arg->amp == 1) {
if (srp_arg->debug)
BIO_printf(bio_err,
"SRP param N and g are not known params, going to check deeper.\n");
/*
* The srp_moregroups is a real debugging feature. Implementors
* should rather add the value to the known ones. The minimal size
* has already been tested.
*/
if (BN_num_bits(g) <= BN_BITS && srp_Verify_N_and_g(N, g))
return 1;
}
BIO_printf(bio_err, "SRP param N and g rejected.\n");
return 0;
}
# define PWD_STRLEN 1024
static char *ssl_give_srp_client_pwd_cb(SSL *s, void *arg)
{
SRP_ARG *srp_arg = (SRP_ARG *)arg;
char *pass = app_malloc(PWD_STRLEN + 1, "SRP password buffer");
PW_CB_DATA cb_tmp;
int l;
cb_tmp.password = (char *)srp_arg->srppassin;
cb_tmp.prompt_info = "SRP user";
if ((l = password_callback(pass, PWD_STRLEN, 0, &cb_tmp)) < 0) {
BIO_printf(bio_err, "Can't read Password\n");
OPENSSL_free(pass);
return NULL;
}
*(pass + l) = '\0';
return pass;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
/* This the context that we pass to next_proto_cb */
typedef struct tlsextnextprotoctx_st {
unsigned char *data;
size_t len;
int status;
} tlsextnextprotoctx;
static tlsextnextprotoctx next_proto;
static int next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
void *arg)
{
tlsextnextprotoctx *ctx = arg;
if (!c_quiet) {
/* We can assume that |in| is syntactically valid. */
unsigned i;
BIO_printf(bio_c_out, "Protocols advertised by server: ");
for (i = 0; i < inlen;) {
if (i)
BIO_write(bio_c_out, ", ", 2);
BIO_write(bio_c_out, &in[i + 1], in[i]);
i += in[i] + 1;
}
BIO_write(bio_c_out, "\n", 1);
}
ctx->status =
SSL_select_next_proto(out, outlen, in, inlen, ctx->data, ctx->len);
return SSL_TLSEXT_ERR_OK;
}
#endif /* ndef OPENSSL_NO_NEXTPROTONEG */
static int serverinfo_cli_parse_cb(SSL *s, unsigned int ext_type,
const unsigned char *in, size_t inlen,
int *al, void *arg)
{
char pem_name[100];
unsigned char ext_buf[4 + 65536];
/* Reconstruct the type/len fields prior to extension data */
inlen &= 0xffff; /* for formal memcmpy correctness */
ext_buf[0] = (unsigned char)(ext_type >> 8);
ext_buf[1] = (unsigned char)(ext_type);
ext_buf[2] = (unsigned char)(inlen >> 8);
ext_buf[3] = (unsigned char)(inlen);
memcpy(ext_buf + 4, in, inlen);
BIO_snprintf(pem_name, sizeof(pem_name), "SERVERINFO FOR EXTENSION %d",
ext_type);
PEM_write_bio(bio_c_out, pem_name, "", ext_buf, 4 + inlen);
return 1;
}
/*
* Hex decoder that tolerates optional whitespace. Returns number of bytes
* produced, advances inptr to end of input string.
*/
static ossl_ssize_t hexdecode(const char **inptr, void *result)
{
unsigned char **out = (unsigned char **)result;
const char *in = *inptr;
unsigned char *ret = app_malloc(strlen(in) / 2, "hexdecode");
unsigned char *cp = ret;
uint8_t byte;
int nibble = 0;
if (ret == NULL)
return -1;
for (byte = 0; *in; ++in) {
int x;
if (isspace(_UC(*in)))
continue;
x = OPENSSL_hexchar2int(*in);
if (x < 0) {
OPENSSL_free(ret);
return 0;
}
byte |= (char)x;
if ((nibble ^= 1) == 0) {
*cp++ = byte;
byte = 0;
} else {
byte <<= 4;
}
}
if (nibble != 0) {
OPENSSL_free(ret);
return 0;
}
*inptr = in;
return cp - (*out = ret);
}
/*
* Decode unsigned 0..255, returns 1 on success, <= 0 on failure. Advances
* inptr to next field skipping leading whitespace.
*/
static ossl_ssize_t checked_uint8(const char **inptr, void *out)
{
uint8_t *result = (uint8_t *)out;
const char *in = *inptr;
char *endp;
long v;
int e;
save_errno();
v = strtol(in, &endp, 10);
e = restore_errno();
if (((v == LONG_MIN || v == LONG_MAX) && e == ERANGE) ||
endp == in || !isspace(_UC(*endp)) ||
v != (*result = (uint8_t) v)) {
return -1;
}
for (in = endp; isspace(_UC(*in)); ++in)
continue;
*inptr = in;
return 1;
}
struct tlsa_field {
void *var;
const char *name;
ossl_ssize_t (*parser)(const char **, void *);
};
static int tlsa_import_rr(SSL *con, const char *rrdata)
{
/* Not necessary to re-init these values; the "parsers" do that. */
static uint8_t usage;
static uint8_t selector;
static uint8_t mtype;
static unsigned char *data;
static struct tlsa_field tlsa_fields[] = {
{ &usage, "usage", checked_uint8 },
{ &selector, "selector", checked_uint8 },
{ &mtype, "mtype", checked_uint8 },
{ &data, "data", hexdecode },
{ NULL, }
};
struct tlsa_field *f;
int ret;
const char *cp = rrdata;
ossl_ssize_t len = 0;
for (f = tlsa_fields; f->var; ++f) {
/* Returns number of bytes produced, advances cp to next field */
if ((len = f->parser(&cp, f->var)) <= 0) {
BIO_printf(bio_err, "%s: warning: bad TLSA %s field in: %s\n",
prog, f->name, rrdata);
return 0;
}
}
/* The data field is last, so len is its length */
ret = SSL_dane_tlsa_add(con, usage, selector, mtype, data, len);
OPENSSL_free(data);
if (ret == 0) {
ERR_print_errors(bio_err);
BIO_printf(bio_err, "%s: warning: unusable TLSA rrdata: %s\n",
prog, rrdata);
return 0;
}
if (ret < 0) {
ERR_print_errors(bio_err);
BIO_printf(bio_err, "%s: warning: error loading TLSA rrdata: %s\n",
prog, rrdata);
return 0;
}
return ret;
}
static int tlsa_import_rrset(SSL *con, STACK_OF(OPENSSL_STRING) *rrset)
{
int num = sk_OPENSSL_STRING_num(rrset);
int count = 0;
int i;
for (i = 0; i < num; ++i) {
char *rrdata = sk_OPENSSL_STRING_value(rrset, i);
if (tlsa_import_rr(con, rrdata) > 0)
++count;
}
return count > 0;
}
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_4, OPT_6, OPT_HOST, OPT_PORT, OPT_CONNECT, OPT_BIND, OPT_UNIX,
OPT_XMPPHOST, OPT_VERIFY, OPT_NAMEOPT,
OPT_CERT, OPT_CRL, OPT_CRL_DOWNLOAD, OPT_SESS_OUT, OPT_SESS_IN,
OPT_CERTFORM, OPT_CRLFORM, OPT_VERIFY_RET_ERROR, OPT_VERIFY_QUIET,
OPT_BRIEF, OPT_PREXIT, OPT_CRLF, OPT_QUIET, OPT_NBIO,
OPT_SSL_CLIENT_ENGINE, OPT_IGN_EOF, OPT_NO_IGN_EOF,
OPT_DEBUG, OPT_TLSEXTDEBUG, OPT_STATUS, OPT_WDEBUG,
OPT_MSG, OPT_MSGFILE, OPT_ENGINE, OPT_TRACE, OPT_SECURITY_DEBUG,
OPT_SECURITY_DEBUG_VERBOSE, OPT_SHOWCERTS, OPT_NBIO_TEST, OPT_STATE,
OPT_PSK_IDENTITY, OPT_PSK, OPT_PSK_SESS,
#ifndef OPENSSL_NO_SRP
OPT_SRPUSER, OPT_SRPPASS, OPT_SRP_STRENGTH, OPT_SRP_LATEUSER,
OPT_SRP_MOREGROUPS,
#endif
OPT_SSL3, OPT_SSL_CONFIG,
OPT_TLS1_3, OPT_TLS1_2, OPT_TLS1_1, OPT_TLS1, OPT_DTLS, OPT_DTLS1,
OPT_DTLS1_2, OPT_SCTP, OPT_TIMEOUT, OPT_MTU, OPT_KEYFORM, OPT_PASS,
OPT_CERT_CHAIN, OPT_CAPATH, OPT_NOCAPATH, OPT_CHAINCAPATH, OPT_VERIFYCAPATH,
OPT_KEY, OPT_RECONNECT, OPT_BUILD_CHAIN, OPT_CAFILE, OPT_NOCAFILE,
OPT_CHAINCAFILE, OPT_VERIFYCAFILE, OPT_NEXTPROTONEG, OPT_ALPN,
OPT_SERVERINFO, OPT_STARTTLS, OPT_SERVERNAME, OPT_NOSERVERNAME, OPT_ASYNC,
OPT_USE_SRTP, OPT_KEYMATEXPORT, OPT_KEYMATEXPORTLEN, OPT_PROTOHOST,
OPT_MAXFRAGLEN, OPT_MAX_SEND_FRAG, OPT_SPLIT_SEND_FRAG, OPT_MAX_PIPELINES,
OPT_READ_BUF, OPT_KEYLOG_FILE, OPT_EARLY_DATA, OPT_REQCAFILE,
OPT_V_ENUM,
OPT_X_ENUM,
OPT_S_ENUM,
OPT_FALLBACKSCSV, OPT_NOCMDS, OPT_PROXY, OPT_DANE_TLSA_DOMAIN,
#ifndef OPENSSL_NO_CT
OPT_CT, OPT_NOCT, OPT_CTLOG_FILE,
#endif
OPT_DANE_TLSA_RRDATA, OPT_DANE_EE_NO_NAME,
OPT_ENABLE_PHA,
OPT_SCTP_LABEL_BUG,
OPT_R_ENUM
} OPTION_CHOICE;
const OPTIONS s_client_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"host", OPT_HOST, 's', "Use -connect instead"},
{"port", OPT_PORT, 'p', "Use -connect instead"},
{"connect", OPT_CONNECT, 's',
"TCP/IP where to connect (default is :" PORT ")"},
{"bind", OPT_BIND, 's', "bind local address for connection"},
{"proxy", OPT_PROXY, 's',
"Connect to via specified proxy to the real server"},
#ifdef AF_UNIX
{"unix", OPT_UNIX, 's', "Connect over the specified Unix-domain socket"},
#endif
{"4", OPT_4, '-', "Use IPv4 only"},
#ifdef AF_INET6
{"6", OPT_6, '-', "Use IPv6 only"},
#endif
{"verify", OPT_VERIFY, 'p', "Turn on peer certificate verification"},
{"cert", OPT_CERT, '<', "Certificate file to use, PEM format assumed"},
{"certform", OPT_CERTFORM, 'F',
"Certificate format (PEM or DER) PEM default"},
{"nameopt", OPT_NAMEOPT, 's', "Various certificate name options"},
{"key", OPT_KEY, 's', "Private key file to use, if not in -cert file"},
{"keyform", OPT_KEYFORM, 'E', "Key format (PEM, DER or engine) PEM default"},
{"pass", OPT_PASS, 's', "Private key file pass phrase source"},
{"CApath", OPT_CAPATH, '/', "PEM format directory of CA's"},
{"CAfile", OPT_CAFILE, '<', "PEM format file of CA's"},
{"no-CAfile", OPT_NOCAFILE, '-',
"Do not load the default certificates file"},
{"no-CApath", OPT_NOCAPATH, '-',
"Do not load certificates from the default certificates directory"},
{"requestCAfile", OPT_REQCAFILE, '<',
"PEM format file of CA names to send to the server"},
{"dane_tlsa_domain", OPT_DANE_TLSA_DOMAIN, 's', "DANE TLSA base domain"},
{"dane_tlsa_rrdata", OPT_DANE_TLSA_RRDATA, 's',
"DANE TLSA rrdata presentation form"},
{"dane_ee_no_namechecks", OPT_DANE_EE_NO_NAME, '-',
"Disable name checks when matching DANE-EE(3) TLSA records"},
{"reconnect", OPT_RECONNECT, '-',
"Drop and re-make the connection with the same Session-ID"},
{"showcerts", OPT_SHOWCERTS, '-',
"Show all certificates sent by the server"},
{"debug", OPT_DEBUG, '-', "Extra output"},
{"msg", OPT_MSG, '-', "Show protocol messages"},
{"msgfile", OPT_MSGFILE, '>',
"File to send output of -msg or -trace, instead of stdout"},
{"nbio_test", OPT_NBIO_TEST, '-', "More ssl protocol testing"},
{"state", OPT_STATE, '-', "Print the ssl states"},
{"crlf", OPT_CRLF, '-', "Convert LF from terminal into CRLF"},
{"quiet", OPT_QUIET, '-', "No s_client output"},
{"ign_eof", OPT_IGN_EOF, '-', "Ignore input eof (default when -quiet)"},
{"no_ign_eof", OPT_NO_IGN_EOF, '-', "Don't ignore input eof"},
{"starttls", OPT_STARTTLS, 's',
"Use the appropriate STARTTLS command before starting TLS"},
{"xmpphost", OPT_XMPPHOST, 's',
"Alias of -name option for \"-starttls xmpp[-server]\""},
OPT_R_OPTIONS,
{"sess_out", OPT_SESS_OUT, '>', "File to write SSL session to"},
{"sess_in", OPT_SESS_IN, '<', "File to read SSL session from"},
#ifndef OPENSSL_NO_SRTP
{"use_srtp", OPT_USE_SRTP, 's',
"Offer SRTP key management with a colon-separated profile list"},
#endif
{"keymatexport", OPT_KEYMATEXPORT, 's',
"Export keying material using label"},
{"keymatexportlen", OPT_KEYMATEXPORTLEN, 'p',
"Export len bytes of keying material (default 20)"},
{"maxfraglen", OPT_MAXFRAGLEN, 'p',
"Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)"},
{"fallback_scsv", OPT_FALLBACKSCSV, '-', "Send the fallback SCSV"},
{"name", OPT_PROTOHOST, 's',
"Hostname to use for \"-starttls lmtp\", \"-starttls smtp\" or \"-starttls xmpp[-server]\""},
{"CRL", OPT_CRL, '<', "CRL file to use"},
{"crl_download", OPT_CRL_DOWNLOAD, '-', "Download CRL from distribution points"},
{"CRLform", OPT_CRLFORM, 'F', "CRL format (PEM or DER) PEM is default"},
{"verify_return_error", OPT_VERIFY_RET_ERROR, '-',
"Close connection on verification error"},
{"verify_quiet", OPT_VERIFY_QUIET, '-', "Restrict verify output to errors"},
{"brief", OPT_BRIEF, '-',
"Restrict output to brief summary of connection parameters"},
{"prexit", OPT_PREXIT, '-',
"Print session information when the program exits"},
{"security_debug", OPT_SECURITY_DEBUG, '-',
"Enable security debug messages"},
{"security_debug_verbose", OPT_SECURITY_DEBUG_VERBOSE, '-',
"Output more security debug output"},
{"cert_chain", OPT_CERT_CHAIN, '<',
"Certificate chain file (in PEM format)"},
{"chainCApath", OPT_CHAINCAPATH, '/',
"Use dir as certificate store path to build CA certificate chain"},
{"verifyCApath", OPT_VERIFYCAPATH, '/',
"Use dir as certificate store path to verify CA certificate"},
{"build_chain", OPT_BUILD_CHAIN, '-', "Build certificate chain"},
{"chainCAfile", OPT_CHAINCAFILE, '<',
"CA file for certificate chain (PEM format)"},
{"verifyCAfile", OPT_VERIFYCAFILE, '<',
"CA file for certificate verification (PEM format)"},
{"nocommands", OPT_NOCMDS, '-', "Do not use interactive command letters"},
{"servername", OPT_SERVERNAME, 's',
"Set TLS extension servername (SNI) in ClientHello (default)"},
{"noservername", OPT_NOSERVERNAME, '-',
"Do not send the server name (SNI) extension in the ClientHello"},
{"tlsextdebug", OPT_TLSEXTDEBUG, '-',
"Hex dump of all TLS extensions received"},
#ifndef OPENSSL_NO_OCSP
{"status", OPT_STATUS, '-', "Request certificate status from server"},
#endif
{"serverinfo", OPT_SERVERINFO, 's',
"types Send empty ClientHello extensions (comma-separated numbers)"},
{"alpn", OPT_ALPN, 's',
"Enable ALPN extension, considering named protocols supported (comma-separated list)"},
{"async", OPT_ASYNC, '-', "Support asynchronous operation"},
{"ssl_config", OPT_SSL_CONFIG, 's', "Use specified configuration file"},
{"max_send_frag", OPT_MAX_SEND_FRAG, 'p', "Maximum Size of send frames "},
{"split_send_frag", OPT_SPLIT_SEND_FRAG, 'p',
"Size used to split data for encrypt pipelines"},
{"max_pipelines", OPT_MAX_PIPELINES, 'p',
"Maximum number of encrypt/decrypt pipelines to be used"},
{"read_buf", OPT_READ_BUF, 'p',
"Default read buffer size to be used for connections"},
OPT_S_OPTIONS,
OPT_V_OPTIONS,
OPT_X_OPTIONS,
#ifndef OPENSSL_NO_SSL3
{"ssl3", OPT_SSL3, '-', "Just use SSLv3"},
#endif
#ifndef OPENSSL_NO_TLS1
{"tls1", OPT_TLS1, '-', "Just use TLSv1"},
#endif
#ifndef OPENSSL_NO_TLS1_1
{"tls1_1", OPT_TLS1_1, '-', "Just use TLSv1.1"},
#endif
#ifndef OPENSSL_NO_TLS1_2
{"tls1_2", OPT_TLS1_2, '-', "Just use TLSv1.2"},
#endif
#ifndef OPENSSL_NO_TLS1_3
{"tls1_3", OPT_TLS1_3, '-', "Just use TLSv1.3"},
#endif
#ifndef OPENSSL_NO_DTLS
{"dtls", OPT_DTLS, '-', "Use any version of DTLS"},
{"timeout", OPT_TIMEOUT, '-',
"Enable send/receive timeout on DTLS connections"},
{"mtu", OPT_MTU, 'p', "Set the link layer MTU"},
#endif
#ifndef OPENSSL_NO_DTLS1
{"dtls1", OPT_DTLS1, '-', "Just use DTLSv1"},
#endif
#ifndef OPENSSL_NO_DTLS1_2
{"dtls1_2", OPT_DTLS1_2, '-', "Just use DTLSv1.2"},
#endif
#ifndef OPENSSL_NO_SCTP
{"sctp", OPT_SCTP, '-', "Use SCTP"},
{"sctp_label_bug", OPT_SCTP_LABEL_BUG, '-', "Enable SCTP label length bug"},
#endif
#ifndef OPENSSL_NO_SSL_TRACE
{"trace", OPT_TRACE, '-', "Show trace output of protocol messages"},
#endif
#ifdef WATT32
{"wdebug", OPT_WDEBUG, '-', "WATT-32 tcp debugging"},
#endif
{"nbio", OPT_NBIO, '-', "Use non-blocking IO"},
{"psk_identity", OPT_PSK_IDENTITY, 's', "PSK identity"},
{"psk", OPT_PSK, 's', "PSK in hex (without 0x)"},
{"psk_session", OPT_PSK_SESS, '<', "File to read PSK SSL session from"},
#ifndef OPENSSL_NO_SRP
{"srpuser", OPT_SRPUSER, 's', "SRP authentication for 'user'"},
{"srppass", OPT_SRPPASS, 's', "Password for 'user'"},
{"srp_lateuser", OPT_SRP_LATEUSER, '-',
"SRP username into second ClientHello message"},
{"srp_moregroups", OPT_SRP_MOREGROUPS, '-',
"Tolerate other than the known g N values."},
{"srp_strength", OPT_SRP_STRENGTH, 'p', "Minimal length in bits for N"},
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
{"nextprotoneg", OPT_NEXTPROTONEG, 's',
"Enable NPN extension, considering named protocols supported (comma-separated list)"},
#endif
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
{"ssl_client_engine", OPT_SSL_CLIENT_ENGINE, 's',
"Specify engine to be used for client certificate operations"},
#endif
#ifndef OPENSSL_NO_CT
{"ct", OPT_CT, '-', "Request and parse SCTs (also enables OCSP stapling)"},
{"noct", OPT_NOCT, '-', "Do not request or parse SCTs (default)"},
{"ctlogfile", OPT_CTLOG_FILE, '<', "CT log list CONF file"},
#endif
{"keylogfile", OPT_KEYLOG_FILE, '>', "Write TLS secrets to file"},
{"early_data", OPT_EARLY_DATA, '<', "File to send as early data"},
{"enable_pha", OPT_ENABLE_PHA, '-', "Enable post-handshake-authentication"},
{NULL, OPT_EOF, 0x00, NULL}
};
typedef enum PROTOCOL_choice {
PROTO_OFF,
PROTO_SMTP,
PROTO_POP3,
PROTO_IMAP,
PROTO_FTP,
PROTO_TELNET,
PROTO_XMPP,
PROTO_XMPP_SERVER,
PROTO_CONNECT,
PROTO_IRC,
PROTO_MYSQL,
PROTO_POSTGRES,
PROTO_LMTP,
PROTO_NNTP,
PROTO_SIEVE,
PROTO_LDAP
} PROTOCOL_CHOICE;
static const OPT_PAIR services[] = {
{"smtp", PROTO_SMTP},
{"pop3", PROTO_POP3},
{"imap", PROTO_IMAP},
{"ftp", PROTO_FTP},
{"xmpp", PROTO_XMPP},
{"xmpp-server", PROTO_XMPP_SERVER},
{"telnet", PROTO_TELNET},
{"irc", PROTO_IRC},
{"mysql", PROTO_MYSQL},
{"postgres", PROTO_POSTGRES},
{"lmtp", PROTO_LMTP},
{"nntp", PROTO_NNTP},
{"sieve", PROTO_SIEVE},
{"ldap", PROTO_LDAP},
{NULL, 0}
};
#define IS_INET_FLAG(o) \
(o == OPT_4 || o == OPT_6 || o == OPT_HOST || o == OPT_PORT || o == OPT_CONNECT)
#define IS_UNIX_FLAG(o) (o == OPT_UNIX)
#define IS_PROT_FLAG(o) \
(o == OPT_SSL3 || o == OPT_TLS1 || o == OPT_TLS1_1 || o == OPT_TLS1_2 \
|| o == OPT_TLS1_3 || o == OPT_DTLS || o == OPT_DTLS1 || o == OPT_DTLS1_2)
/* Free |*dest| and optionally set it to a copy of |source|. */
static void freeandcopy(char **dest, const char *source)
{
OPENSSL_free(*dest);
*dest = NULL;
if (source != NULL)
*dest = OPENSSL_strdup(source);
}
static int new_session_cb(SSL *s, SSL_SESSION *sess)
{
if (sess_out != NULL) {
BIO *stmp = BIO_new_file(sess_out, "w");
if (stmp == NULL) {
BIO_printf(bio_err, "Error writing session file %s\n", sess_out);
} else {
PEM_write_bio_SSL_SESSION(stmp, sess);
BIO_free(stmp);
}
}
/*
* Session data gets dumped on connection for TLSv1.2 and below, and on
* arrival of the NewSessionTicket for TLSv1.3.
*/
if (SSL_version(s) == TLS1_3_VERSION) {
BIO_printf(bio_c_out,
"---\nPost-Handshake New Session Ticket arrived:\n");
SSL_SESSION_print(bio_c_out, sess);
BIO_printf(bio_c_out, "---\n");
}
/*
* We always return a "fail" response so that the session gets freed again
* because we haven't used the reference.
*/
return 0;
}
int s_client_main(int argc, char **argv)
{
BIO *sbio;
EVP_PKEY *key = NULL;
SSL *con = NULL;
SSL_CTX *ctx = NULL;
STACK_OF(X509) *chain = NULL;
X509 *cert = NULL;
X509_VERIFY_PARAM *vpm = NULL;
SSL_EXCERT *exc = NULL;
SSL_CONF_CTX *cctx = NULL;
STACK_OF(OPENSSL_STRING) *ssl_args = NULL;
char *dane_tlsa_domain = NULL;
STACK_OF(OPENSSL_STRING) *dane_tlsa_rrset = NULL;
int dane_ee_no_name = 0;
STACK_OF(X509_CRL) *crls = NULL;
const SSL_METHOD *meth = TLS_client_method();
const char *CApath = NULL, *CAfile = NULL;
char *cbuf = NULL, *sbuf = NULL;
char *mbuf = NULL, *proxystr = NULL, *connectstr = NULL, *bindstr = NULL;
char *cert_file = NULL, *key_file = NULL, *chain_file = NULL;
char *chCApath = NULL, *chCAfile = NULL, *host = NULL;
char *port = OPENSSL_strdup(PORT);
char *bindhost = NULL, *bindport = NULL;
char *passarg = NULL, *pass = NULL, *vfyCApath = NULL, *vfyCAfile = NULL;
char *ReqCAfile = NULL;
char *sess_in = NULL, *crl_file = NULL, *p;
const char *protohost = NULL;
struct timeval timeout, *timeoutp;
fd_set readfds, writefds;
int noCApath = 0, noCAfile = 0;
int build_chain = 0, cbuf_len, cbuf_off, cert_format = FORMAT_PEM;
int key_format = FORMAT_PEM, crlf = 0, full_log = 1, mbuf_len = 0;
int prexit = 0;
int sdebug = 0;
int reconnect = 0, verify = SSL_VERIFY_NONE, vpmtouched = 0;
int ret = 1, in_init = 1, i, nbio_test = 0, s = -1, k, width, state = 0;
int sbuf_len, sbuf_off, cmdletters = 1;
int socket_family = AF_UNSPEC, socket_type = SOCK_STREAM, protocol = 0;
int starttls_proto = PROTO_OFF, crl_format = FORMAT_PEM, crl_download = 0;
int write_tty, read_tty, write_ssl, read_ssl, tty_on, ssl_pending;
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
int at_eof = 0;
#endif
int read_buf_len = 0;
int fallback_scsv = 0;
OPTION_CHOICE o;
#ifndef OPENSSL_NO_DTLS
int enable_timeouts = 0;
long socket_mtu = 0;
#endif
#ifndef OPENSSL_NO_ENGINE
ENGINE *ssl_client_engine = NULL;
#endif
ENGINE *e = NULL;
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
struct timeval tv;
#endif
const char *servername = NULL;
int noservername = 0;
const char *alpn_in = NULL;
tlsextctx tlsextcbp = { NULL, 0 };
const char *ssl_config = NULL;
#define MAX_SI_TYPES 100
unsigned short serverinfo_types[MAX_SI_TYPES];
int serverinfo_count = 0, start = 0, len;
#ifndef OPENSSL_NO_NEXTPROTONEG
const char *next_proto_neg_in = NULL;
#endif
#ifndef OPENSSL_NO_SRP
char *srppass = NULL;
int srp_lateuser = 0;
SRP_ARG srp_arg = { NULL, NULL, 0, 0, 0, 1024 };
#endif
#ifndef OPENSSL_NO_SRTP
char *srtp_profiles = NULL;
#endif
#ifndef OPENSSL_NO_CT
char *ctlog_file = NULL;
int ct_validation = 0;
#endif
int min_version = 0, max_version = 0, prot_opt = 0, no_prot_opt = 0;
int async = 0;
unsigned int max_send_fragment = 0;
unsigned int split_send_fragment = 0, max_pipelines = 0;
enum { use_inet, use_unix, use_unknown } connect_type = use_unknown;
int count4or6 = 0;
uint8_t maxfraglen = 0;
int c_nbio = 0, c_msg = 0, c_ign_eof = 0, c_brief = 0;
int c_tlsextdebug = 0;
#ifndef OPENSSL_NO_OCSP
int c_status_req = 0;
#endif
BIO *bio_c_msg = NULL;
const char *keylog_file = NULL, *early_data_file = NULL;
#ifndef OPENSSL_NO_DTLS
int isdtls = 0;
#endif
char *psksessf = NULL;
int enable_pha = 0;
#ifndef OPENSSL_NO_SCTP
int sctp_label_bug = 0;
#endif
FD_ZERO(&readfds);
FD_ZERO(&writefds);
/* Known false-positive of MemorySanitizer. */
#if defined(__has_feature)
# if __has_feature(memory_sanitizer)
__msan_unpoison(&readfds, sizeof(readfds));
__msan_unpoison(&writefds, sizeof(writefds));
# endif
#endif
prog = opt_progname(argv[0]);
c_quiet = 0;
c_debug = 0;
c_showcerts = 0;
c_nbio = 0;
vpm = X509_VERIFY_PARAM_new();
cctx = SSL_CONF_CTX_new();
if (vpm == NULL || cctx == NULL) {
BIO_printf(bio_err, "%s: out of memory\n", prog);
goto end;
}
cbuf = app_malloc(BUFSIZZ, "cbuf");
sbuf = app_malloc(BUFSIZZ, "sbuf");
mbuf = app_malloc(BUFSIZZ, "mbuf");
SSL_CONF_CTX_set_flags(cctx, SSL_CONF_FLAG_CLIENT | SSL_CONF_FLAG_CMDLINE);
prog = opt_init(argc, argv, s_client_options);
while ((o = opt_next()) != OPT_EOF) {
/* Check for intermixing flags. */
if (connect_type == use_unix && IS_INET_FLAG(o)) {
BIO_printf(bio_err,
"%s: Intermixed protocol flags (unix and internet domains)\n",
prog);
goto end;
}
if (connect_type == use_inet && IS_UNIX_FLAG(o)) {
BIO_printf(bio_err,
"%s: Intermixed protocol flags (internet and unix domains)\n",
prog);
goto end;
}
if (IS_PROT_FLAG(o) && ++prot_opt > 1) {
BIO_printf(bio_err, "Cannot supply multiple protocol flags\n");
goto end;
}
if (IS_NO_PROT_FLAG(o))
no_prot_opt++;
if (prot_opt == 1 && no_prot_opt) {
BIO_printf(bio_err,
"Cannot supply both a protocol flag and '-no_<prot>'\n");
goto end;
}
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(s_client_options);
ret = 0;
goto end;
case OPT_4:
connect_type = use_inet;
socket_family = AF_INET;
count4or6++;
break;
#ifdef AF_INET6
case OPT_6:
connect_type = use_inet;
socket_family = AF_INET6;
count4or6++;
break;
#endif
case OPT_HOST:
connect_type = use_inet;
freeandcopy(&host, opt_arg());
break;
case OPT_PORT:
connect_type = use_inet;
freeandcopy(&port, opt_arg());
break;
case OPT_CONNECT:
connect_type = use_inet;
freeandcopy(&connectstr, opt_arg());
break;
case OPT_BIND:
freeandcopy(&bindstr, opt_arg());
break;
case OPT_PROXY:
proxystr = opt_arg();
starttls_proto = PROTO_CONNECT;
break;
#ifdef AF_UNIX
case OPT_UNIX:
connect_type = use_unix;
socket_family = AF_UNIX;
freeandcopy(&host, opt_arg());
break;
#endif
case OPT_XMPPHOST:
/* fall through, since this is an alias */
case OPT_PROTOHOST:
protohost = opt_arg();
break;
case OPT_VERIFY:
verify = SSL_VERIFY_PEER;
verify_args.depth = atoi(opt_arg());
if (!c_quiet)
BIO_printf(bio_err, "verify depth is %d\n", verify_args.depth);
break;
case OPT_CERT:
cert_file = opt_arg();
break;
case OPT_NAMEOPT:
if (!set_nameopt(opt_arg()))
goto end;
break;
case OPT_CRL:
crl_file = opt_arg();
break;
case OPT_CRL_DOWNLOAD:
crl_download = 1;
break;
case OPT_SESS_OUT:
sess_out = opt_arg();
break;
case OPT_SESS_IN:
sess_in = opt_arg();
break;
case OPT_CERTFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &cert_format))
goto opthelp;
break;
case OPT_CRLFORM:
if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &crl_format))
goto opthelp;
break;
case OPT_VERIFY_RET_ERROR:
verify = SSL_VERIFY_PEER;
verify_args.return_error = 1;
break;
case OPT_VERIFY_QUIET:
verify_args.quiet = 1;
break;
case OPT_BRIEF:
c_brief = verify_args.quiet = c_quiet = 1;
break;
case OPT_S_CASES:
if (ssl_args == NULL)
ssl_args = sk_OPENSSL_STRING_new_null();
if (ssl_args == NULL
|| !sk_OPENSSL_STRING_push(ssl_args, opt_flag())
|| !sk_OPENSSL_STRING_push(ssl_args, opt_arg())) {
BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
goto end;
}
break;
case OPT_V_CASES:
if (!opt_verify(o, vpm))
goto end;
vpmtouched++;
break;
case OPT_X_CASES:
if (!args_excert(o, &exc))
goto end;
break;
case OPT_PREXIT:
prexit = 1;
break;
case OPT_CRLF:
crlf = 1;
break;
case OPT_QUIET:
c_quiet = c_ign_eof = 1;
break;
case OPT_NBIO:
c_nbio = 1;
break;
case OPT_NOCMDS:
cmdletters = 0;
break;
case OPT_ENGINE:
e = setup_engine(opt_arg(), 1);
break;
case OPT_SSL_CLIENT_ENGINE:
#ifndef OPENSSL_NO_ENGINE
ssl_client_engine = ENGINE_by_id(opt_arg());
if (ssl_client_engine == NULL) {
BIO_printf(bio_err, "Error getting client auth engine\n");
goto opthelp;
}
#endif
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_IGN_EOF:
c_ign_eof = 1;
break;
case OPT_NO_IGN_EOF:
c_ign_eof = 0;
break;
case OPT_DEBUG:
c_debug = 1;
break;
case OPT_TLSEXTDEBUG:
c_tlsextdebug = 1;
break;
case OPT_STATUS:
#ifndef OPENSSL_NO_OCSP
c_status_req = 1;
#endif
break;
case OPT_WDEBUG:
#ifdef WATT32
dbug_init();
#endif
break;
case OPT_MSG:
c_msg = 1;
break;
case OPT_MSGFILE:
bio_c_msg = BIO_new_file(opt_arg(), "w");
break;
case OPT_TRACE:
#ifndef OPENSSL_NO_SSL_TRACE
c_msg = 2;
#endif
break;
case OPT_SECURITY_DEBUG:
sdebug = 1;
break;
case OPT_SECURITY_DEBUG_VERBOSE:
sdebug = 2;
break;
case OPT_SHOWCERTS:
c_showcerts = 1;
break;
case OPT_NBIO_TEST:
nbio_test = 1;
break;
case OPT_STATE:
state = 1;
break;
case OPT_PSK_IDENTITY:
psk_identity = opt_arg();
break;
case OPT_PSK:
for (p = psk_key = opt_arg(); *p; p++) {
if (isxdigit(_UC(*p)))
continue;
BIO_printf(bio_err, "Not a hex number '%s'\n", psk_key);
goto end;
}
break;
case OPT_PSK_SESS:
psksessf = opt_arg();
break;
#ifndef OPENSSL_NO_SRP
case OPT_SRPUSER:
srp_arg.srplogin = opt_arg();
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
break;
case OPT_SRPPASS:
srppass = opt_arg();
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
break;
case OPT_SRP_STRENGTH:
srp_arg.strength = atoi(opt_arg());
BIO_printf(bio_err, "SRP minimal length for N is %d\n",
srp_arg.strength);
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
break;
case OPT_SRP_LATEUSER:
srp_lateuser = 1;
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
break;
case OPT_SRP_MOREGROUPS:
srp_arg.amp = 1;
if (min_version < TLS1_VERSION)
min_version = TLS1_VERSION;
break;
#endif
case OPT_SSL_CONFIG:
ssl_config = opt_arg();
break;
case OPT_SSL3:
min_version = SSL3_VERSION;
max_version = SSL3_VERSION;
break;
case OPT_TLS1_3:
min_version = TLS1_3_VERSION;
max_version = TLS1_3_VERSION;
break;
case OPT_TLS1_2:
min_version = TLS1_2_VERSION;
max_version = TLS1_2_VERSION;
break;
case OPT_TLS1_1:
min_version = TLS1_1_VERSION;
max_version = TLS1_1_VERSION;
break;
case OPT_TLS1:
min_version = TLS1_VERSION;
max_version = TLS1_VERSION;
break;
case OPT_DTLS:
#ifndef OPENSSL_NO_DTLS
meth = DTLS_client_method();
socket_type = SOCK_DGRAM;
isdtls = 1;
#endif
break;
case OPT_DTLS1:
#ifndef OPENSSL_NO_DTLS1
meth = DTLS_client_method();
min_version = DTLS1_VERSION;
max_version = DTLS1_VERSION;
socket_type = SOCK_DGRAM;
isdtls = 1;
#endif
break;
case OPT_DTLS1_2:
#ifndef OPENSSL_NO_DTLS1_2
meth = DTLS_client_method();
min_version = DTLS1_2_VERSION;
max_version = DTLS1_2_VERSION;
socket_type = SOCK_DGRAM;
isdtls = 1;
#endif
break;
case OPT_SCTP:
#ifndef OPENSSL_NO_SCTP
protocol = IPPROTO_SCTP;
#endif
break;
case OPT_SCTP_LABEL_BUG:
#ifndef OPENSSL_NO_SCTP
sctp_label_bug = 1;
#endif
break;
case OPT_TIMEOUT:
#ifndef OPENSSL_NO_DTLS
enable_timeouts = 1;
#endif
break;
case OPT_MTU:
#ifndef OPENSSL_NO_DTLS
socket_mtu = atol(opt_arg());
#endif
break;
case OPT_FALLBACKSCSV:
fallback_scsv = 1;
break;
case OPT_KEYFORM:
if (!opt_format(opt_arg(), OPT_FMT_PDE, &key_format))
goto opthelp;
break;
case OPT_PASS:
passarg = opt_arg();
break;
case OPT_CERT_CHAIN:
chain_file = opt_arg();
break;
case OPT_KEY:
key_file = opt_arg();
break;
case OPT_RECONNECT:
reconnect = 5;
break;
case OPT_CAPATH:
CApath = opt_arg();
break;
case OPT_NOCAPATH:
noCApath = 1;
break;
case OPT_CHAINCAPATH:
chCApath = opt_arg();
break;
case OPT_VERIFYCAPATH:
vfyCApath = opt_arg();
break;
case OPT_BUILD_CHAIN:
build_chain = 1;
break;
case OPT_REQCAFILE:
ReqCAfile = opt_arg();
break;
case OPT_CAFILE:
CAfile = opt_arg();
break;
case OPT_NOCAFILE:
noCAfile = 1;
break;
#ifndef OPENSSL_NO_CT
case OPT_NOCT:
ct_validation = 0;
break;
case OPT_CT:
ct_validation = 1;
break;
case OPT_CTLOG_FILE:
ctlog_file = opt_arg();
break;
#endif
case OPT_CHAINCAFILE:
chCAfile = opt_arg();
break;
case OPT_VERIFYCAFILE:
vfyCAfile = opt_arg();
break;
case OPT_DANE_TLSA_DOMAIN:
dane_tlsa_domain = opt_arg();
break;
case OPT_DANE_TLSA_RRDATA:
if (dane_tlsa_rrset == NULL)
dane_tlsa_rrset = sk_OPENSSL_STRING_new_null();
if (dane_tlsa_rrset == NULL ||
!sk_OPENSSL_STRING_push(dane_tlsa_rrset, opt_arg())) {
BIO_printf(bio_err, "%s: Memory allocation failure\n", prog);
goto end;
}
break;
case OPT_DANE_EE_NO_NAME:
dane_ee_no_name = 1;
break;
case OPT_NEXTPROTONEG:
#ifndef OPENSSL_NO_NEXTPROTONEG
next_proto_neg_in = opt_arg();
#endif
break;
case OPT_ALPN:
alpn_in = opt_arg();
break;
case OPT_SERVERINFO:
p = opt_arg();
len = strlen(p);
for (start = 0, i = 0; i <= len; ++i) {
if (i == len || p[i] == ',') {
serverinfo_types[serverinfo_count] = atoi(p + start);
if (++serverinfo_count == MAX_SI_TYPES)
break;
start = i + 1;
}
}
break;
case OPT_STARTTLS:
if (!opt_pair(opt_arg(), services, &starttls_proto))
goto end;
break;
case OPT_SERVERNAME:
servername = opt_arg();
break;
case OPT_NOSERVERNAME:
noservername = 1;
break;
case OPT_USE_SRTP:
#ifndef OPENSSL_NO_SRTP
srtp_profiles = opt_arg();
#endif
break;
case OPT_KEYMATEXPORT:
keymatexportlabel = opt_arg();
break;
case OPT_KEYMATEXPORTLEN:
keymatexportlen = atoi(opt_arg());
break;
case OPT_ASYNC:
async = 1;
break;
case OPT_MAXFRAGLEN:
len = atoi(opt_arg());
switch (len) {
case 512:
maxfraglen = TLSEXT_max_fragment_length_512;
break;
case 1024:
maxfraglen = TLSEXT_max_fragment_length_1024;
break;
case 2048:
maxfraglen = TLSEXT_max_fragment_length_2048;
break;
case 4096:
maxfraglen = TLSEXT_max_fragment_length_4096;
break;
default:
BIO_printf(bio_err,
"%s: Max Fragment Len %u is out of permitted values",
prog, len);
goto opthelp;
}
break;
case OPT_MAX_SEND_FRAG:
max_send_fragment = atoi(opt_arg());
break;
case OPT_SPLIT_SEND_FRAG:
split_send_fragment = atoi(opt_arg());
break;
case OPT_MAX_PIPELINES:
max_pipelines = atoi(opt_arg());
break;
case OPT_READ_BUF:
read_buf_len = atoi(opt_arg());
break;
case OPT_KEYLOG_FILE:
keylog_file = opt_arg();
break;
case OPT_EARLY_DATA:
early_data_file = opt_arg();
break;
case OPT_ENABLE_PHA:
enable_pha = 1;
break;
}
}
if (count4or6 >= 2) {
BIO_printf(bio_err, "%s: Can't use both -4 and -6\n", prog);
goto opthelp;
}
if (noservername) {
if (servername != NULL) {
BIO_printf(bio_err,
"%s: Can't use -servername and -noservername together\n",
prog);
goto opthelp;
}
if (dane_tlsa_domain != NULL) {
BIO_printf(bio_err,
"%s: Can't use -dane_tlsa_domain and -noservername together\n",
prog);
goto opthelp;
}
}
argc = opt_num_rest();
if (argc == 1) {
/* If there's a positional argument, it's the equivalent of
* OPT_CONNECT.
* Don't allow -connect and a separate argument.
*/
if (connectstr != NULL) {
BIO_printf(bio_err,
"%s: must not provide both -connect option and target parameter\n",
prog);
goto opthelp;
}
connect_type = use_inet;
freeandcopy(&connectstr, *opt_rest());
} else if (argc != 0) {
goto opthelp;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
if (min_version == TLS1_3_VERSION && next_proto_neg_in != NULL) {
BIO_printf(bio_err, "Cannot supply -nextprotoneg with TLSv1.3\n");
goto opthelp;
}
#endif
if (proxystr != NULL) {
int res;
char *tmp_host = host, *tmp_port = port;
if (connectstr == NULL) {
BIO_printf(bio_err, "%s: -proxy requires use of -connect or target parameter\n", prog);
goto opthelp;
}
res = BIO_parse_hostserv(proxystr, &host, &port, BIO_PARSE_PRIO_HOST);
if (tmp_host != host)
OPENSSL_free(tmp_host);
if (tmp_port != port)
OPENSSL_free(tmp_port);
if (!res) {
BIO_printf(bio_err,
"%s: -proxy argument malformed or ambiguous\n", prog);
goto end;
}
} else {
int res = 1;
char *tmp_host = host, *tmp_port = port;
if (connectstr != NULL)
res = BIO_parse_hostserv(connectstr, &host, &port,
BIO_PARSE_PRIO_HOST);
if (tmp_host != host)
OPENSSL_free(tmp_host);
if (tmp_port != port)
OPENSSL_free(tmp_port);
if (!res) {
BIO_printf(bio_err,
"%s: -connect argument or target parameter malformed or ambiguous\n",
prog);
goto end;
}
}
if (bindstr != NULL) {
int res;
res = BIO_parse_hostserv(bindstr, &bindhost, &bindport,
BIO_PARSE_PRIO_HOST);
if (!res) {
BIO_printf(bio_err,
"%s: -bind argument parameter malformed or ambiguous\n",
prog);
goto end;
}
}
#ifdef AF_UNIX
if (socket_family == AF_UNIX && socket_type != SOCK_STREAM) {
BIO_printf(bio_err,
"Can't use unix sockets and datagrams together\n");
goto end;
}
#endif
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP) {
if (socket_type != SOCK_DGRAM) {
BIO_printf(bio_err, "Can't use -sctp without DTLS\n");
goto end;
}
/* SCTP is unusual. It uses DTLS over a SOCK_STREAM protocol */
socket_type = SOCK_STREAM;
}
#endif
#if !defined(OPENSSL_NO_NEXTPROTONEG)
next_proto.status = -1;
if (next_proto_neg_in) {
next_proto.data =
next_protos_parse(&next_proto.len, next_proto_neg_in);
if (next_proto.data == NULL) {
BIO_printf(bio_err, "Error parsing -nextprotoneg argument\n");
goto end;
}
} else
next_proto.data = NULL;
#endif
if (!app_passwd(passarg, NULL, &pass, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
if (key_file == NULL)
key_file = cert_file;
if (key_file != NULL) {
key = load_key(key_file, key_format, 0, pass, e,
"client certificate private key file");
if (key == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (cert_file != NULL) {
cert = load_cert(cert_file, cert_format, "client certificate file");
if (cert == NULL) {
ERR_print_errors(bio_err);
goto end;
}
}
if (chain_file != NULL) {
if (!load_certs(chain_file, &chain, FORMAT_PEM, NULL,
"client certificate chain"))
goto end;
}
if (crl_file != NULL) {
X509_CRL *crl;
crl = load_crl(crl_file, crl_format);
if (crl == NULL) {
BIO_puts(bio_err, "Error loading CRL\n");
ERR_print_errors(bio_err);
goto end;
}
crls = sk_X509_CRL_new_null();
if (crls == NULL || !sk_X509_CRL_push(crls, crl)) {
BIO_puts(bio_err, "Error adding CRL\n");
ERR_print_errors(bio_err);
X509_CRL_free(crl);
goto end;
}
}
if (!load_excert(&exc))
goto end;
if (bio_c_out == NULL) {
if (c_quiet && !c_debug) {
bio_c_out = BIO_new(BIO_s_null());
if (c_msg && bio_c_msg == NULL)
bio_c_msg = dup_bio_out(FORMAT_TEXT);
} else if (bio_c_out == NULL)
bio_c_out = dup_bio_out(FORMAT_TEXT);
}
#ifndef OPENSSL_NO_SRP
if (!app_passwd(srppass, NULL, &srp_arg.srppassin, NULL)) {
BIO_printf(bio_err, "Error getting password\n");
goto end;
}
#endif
ctx = SSL_CTX_new(meth);
if (ctx == NULL) {
ERR_print_errors(bio_err);
goto end;
}
SSL_CTX_clear_mode(ctx, SSL_MODE_AUTO_RETRY);
if (sdebug)
ssl_ctx_security_debug(ctx, sdebug);
if (!config_ctx(cctx, ssl_args, ctx))
goto end;
if (ssl_config != NULL) {
if (SSL_CTX_config(ctx, ssl_config) == 0) {
BIO_printf(bio_err, "Error using configuration \"%s\"\n",
ssl_config);
ERR_print_errors(bio_err);
goto end;
}
}
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP && sctp_label_bug == 1)
SSL_CTX_set_mode(ctx, SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG);
#endif
if (min_version != 0
&& SSL_CTX_set_min_proto_version(ctx, min_version) == 0)
goto end;
if (max_version != 0
&& SSL_CTX_set_max_proto_version(ctx, max_version) == 0)
goto end;
if (vpmtouched && !SSL_CTX_set1_param(ctx, vpm)) {
BIO_printf(bio_err, "Error setting verify params\n");
ERR_print_errors(bio_err);
goto end;
}
if (async) {
SSL_CTX_set_mode(ctx, SSL_MODE_ASYNC);
}
if (max_send_fragment > 0
&& !SSL_CTX_set_max_send_fragment(ctx, max_send_fragment)) {
BIO_printf(bio_err, "%s: Max send fragment size %u is out of permitted range\n",
prog, max_send_fragment);
goto end;
}
if (split_send_fragment > 0
&& !SSL_CTX_set_split_send_fragment(ctx, split_send_fragment)) {
BIO_printf(bio_err, "%s: Split send fragment size %u is out of permitted range\n",
prog, split_send_fragment);
goto end;
}
if (max_pipelines > 0
&& !SSL_CTX_set_max_pipelines(ctx, max_pipelines)) {
BIO_printf(bio_err, "%s: Max pipelines %u is out of permitted range\n",
prog, max_pipelines);
goto end;
}
if (read_buf_len > 0) {
SSL_CTX_set_default_read_buffer_len(ctx, read_buf_len);
}
if (maxfraglen > 0
&& !SSL_CTX_set_tlsext_max_fragment_length(ctx, maxfraglen)) {
BIO_printf(bio_err,
"%s: Max Fragment Length code %u is out of permitted values"
"\n", prog, maxfraglen);
goto end;
}
if (!ssl_load_stores(ctx, vfyCApath, vfyCAfile, chCApath, chCAfile,
crls, crl_download)) {
BIO_printf(bio_err, "Error loading store locations\n");
ERR_print_errors(bio_err);
goto end;
}
if (ReqCAfile != NULL) {
STACK_OF(X509_NAME) *nm = sk_X509_NAME_new_null();
if (nm == NULL || !SSL_add_file_cert_subjects_to_stack(nm, ReqCAfile)) {
sk_X509_NAME_pop_free(nm, X509_NAME_free);
BIO_printf(bio_err, "Error loading CA names\n");
ERR_print_errors(bio_err);
goto end;
}
SSL_CTX_set0_CA_list(ctx, nm);
}
#ifndef OPENSSL_NO_ENGINE
if (ssl_client_engine) {
if (!SSL_CTX_set_client_cert_engine(ctx, ssl_client_engine)) {
BIO_puts(bio_err, "Error setting client auth engine\n");
ERR_print_errors(bio_err);
ENGINE_free(ssl_client_engine);
goto end;
}
ENGINE_free(ssl_client_engine);
}
#endif
#ifndef OPENSSL_NO_PSK
if (psk_key != NULL) {
if (c_debug)
BIO_printf(bio_c_out, "PSK key given, setting client callback\n");
SSL_CTX_set_psk_client_callback(ctx, psk_client_cb);
}
#endif
if (psksessf != NULL) {
BIO *stmp = BIO_new_file(psksessf, "r");
if (stmp == NULL) {
BIO_printf(bio_err, "Can't open PSK session file %s\n", psksessf);
ERR_print_errors(bio_err);
goto end;
}
psksess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
BIO_free(stmp);
if (psksess == NULL) {
BIO_printf(bio_err, "Can't read PSK session file %s\n", psksessf);
ERR_print_errors(bio_err);
goto end;
}
}
if (psk_key != NULL || psksess != NULL)
SSL_CTX_set_psk_use_session_callback(ctx, psk_use_session_cb);
#ifndef OPENSSL_NO_SRTP
if (srtp_profiles != NULL) {
/* Returns 0 on success! */
if (SSL_CTX_set_tlsext_use_srtp(ctx, srtp_profiles) != 0) {
BIO_printf(bio_err, "Error setting SRTP profile\n");
ERR_print_errors(bio_err);
goto end;
}
}
#endif
if (exc != NULL)
ssl_ctx_set_excert(ctx, exc);
#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (next_proto.data != NULL)
SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &next_proto);
#endif
if (alpn_in) {
size_t alpn_len;
unsigned char *alpn = next_protos_parse(&alpn_len, alpn_in);
if (alpn == NULL) {
BIO_printf(bio_err, "Error parsing -alpn argument\n");
goto end;
}
/* Returns 0 on success! */
if (SSL_CTX_set_alpn_protos(ctx, alpn, alpn_len) != 0) {
BIO_printf(bio_err, "Error setting ALPN\n");
goto end;
}
OPENSSL_free(alpn);
}
for (i = 0; i < serverinfo_count; i++) {
if (!SSL_CTX_add_client_custom_ext(ctx,
serverinfo_types[i],
NULL, NULL, NULL,
serverinfo_cli_parse_cb, NULL)) {
BIO_printf(bio_err,
"Warning: Unable to add custom extension %u, skipping\n",
serverinfo_types[i]);
}
}
if (state)
SSL_CTX_set_info_callback(ctx, apps_ssl_info_callback);
#ifndef OPENSSL_NO_CT
/* Enable SCT processing, without early connection termination */
if (ct_validation &&
!SSL_CTX_enable_ct(ctx, SSL_CT_VALIDATION_PERMISSIVE)) {
ERR_print_errors(bio_err);
goto end;
}
if (!ctx_set_ctlog_list_file(ctx, ctlog_file)) {
if (ct_validation) {
ERR_print_errors(bio_err);
goto end;
}
/*
* If CT validation is not enabled, the log list isn't needed so don't
* show errors or abort. We try to load it regardless because then we
* can show the names of the logs any SCTs came from (SCTs may be seen
* even with validation disabled).
*/
ERR_clear_error();
}
#endif
SSL_CTX_set_verify(ctx, verify, verify_callback);
if (!ctx_set_verify_locations(ctx, CAfile, CApath, noCAfile, noCApath)) {
ERR_print_errors(bio_err);
goto end;
}
ssl_ctx_add_crls(ctx, crls, crl_download);
if (!set_cert_key_stuff(ctx, cert, key, chain, build_chain))
goto end;
if (!noservername) {
tlsextcbp.biodebug = bio_err;
SSL_CTX_set_tlsext_servername_callback(ctx, ssl_servername_cb);
SSL_CTX_set_tlsext_servername_arg(ctx, &tlsextcbp);
}
# ifndef OPENSSL_NO_SRP
if (srp_arg.srplogin) {
if (!srp_lateuser && !SSL_CTX_set_srp_username(ctx, srp_arg.srplogin)) {
BIO_printf(bio_err, "Unable to set SRP username\n");
goto end;
}
srp_arg.msg = c_msg;
srp_arg.debug = c_debug;
SSL_CTX_set_srp_cb_arg(ctx, &srp_arg);
SSL_CTX_set_srp_client_pwd_callback(ctx, ssl_give_srp_client_pwd_cb);
SSL_CTX_set_srp_strength(ctx, srp_arg.strength);
if (c_msg || c_debug || srp_arg.amp == 0)
SSL_CTX_set_srp_verify_param_callback(ctx,
ssl_srp_verify_param_cb);
}
# endif
if (dane_tlsa_domain != NULL) {
if (SSL_CTX_dane_enable(ctx) <= 0) {
BIO_printf(bio_err,
"%s: Error enabling DANE TLSA authentication.\n",
prog);
ERR_print_errors(bio_err);
goto end;
}
}
/*
* In TLSv1.3 NewSessionTicket messages arrive after the handshake and can
* come at any time. Therefore we use a callback to write out the session
* when we know about it. This approach works for < TLSv1.3 as well.
*/
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT
| SSL_SESS_CACHE_NO_INTERNAL_STORE);
SSL_CTX_sess_set_new_cb(ctx, new_session_cb);
if (set_keylog_file(ctx, keylog_file))
goto end;
con = SSL_new(ctx);
if (con == NULL)
goto end;
if (enable_pha)
SSL_set_post_handshake_auth(con, 1);
if (sess_in != NULL) {
SSL_SESSION *sess;
BIO *stmp = BIO_new_file(sess_in, "r");
if (stmp == NULL) {
BIO_printf(bio_err, "Can't open session file %s\n", sess_in);
ERR_print_errors(bio_err);
goto end;
}
sess = PEM_read_bio_SSL_SESSION(stmp, NULL, 0, NULL);
BIO_free(stmp);
if (sess == NULL) {
BIO_printf(bio_err, "Can't open session file %s\n", sess_in);
ERR_print_errors(bio_err);
goto end;
}
if (!SSL_set_session(con, sess)) {
BIO_printf(bio_err, "Can't set session\n");
ERR_print_errors(bio_err);
goto end;
}
SSL_SESSION_free(sess);
}
if (fallback_scsv)
SSL_set_mode(con, SSL_MODE_SEND_FALLBACK_SCSV);
if (!noservername && (servername != NULL || dane_tlsa_domain == NULL)) {
if (servername == NULL) {
if(host == NULL || is_dNS_name(host))
servername = (host == NULL) ? "localhost" : host;
}
if (servername != NULL && !SSL_set_tlsext_host_name(con, servername)) {
BIO_printf(bio_err, "Unable to set TLS servername extension.\n");
ERR_print_errors(bio_err);
goto end;
}
}
if (dane_tlsa_domain != NULL) {
if (SSL_dane_enable(con, dane_tlsa_domain) <= 0) {
BIO_printf(bio_err, "%s: Error enabling DANE TLSA "
"authentication.\n", prog);
ERR_print_errors(bio_err);
goto end;
}
if (dane_tlsa_rrset == NULL) {
BIO_printf(bio_err, "%s: DANE TLSA authentication requires at "
"least one -dane_tlsa_rrdata option.\n", prog);
goto end;
}
if (tlsa_import_rrset(con, dane_tlsa_rrset) <= 0) {
BIO_printf(bio_err, "%s: Failed to import any TLSA "
"records.\n", prog);
goto end;
}
if (dane_ee_no_name)
SSL_dane_set_flags(con, DANE_FLAG_NO_DANE_EE_NAMECHECKS);
} else if (dane_tlsa_rrset != NULL) {
BIO_printf(bio_err, "%s: DANE TLSA authentication requires the "
"-dane_tlsa_domain option.\n", prog);
goto end;
}
re_start:
if (init_client(&s, host, port, bindhost, bindport, socket_family,
socket_type, protocol) == 0) {
BIO_printf(bio_err, "connect:errno=%d\n", get_last_socket_error());
BIO_closesocket(s);
goto end;
}
BIO_printf(bio_c_out, "CONNECTED(%08X)\n", s);
if (c_nbio) {
if (!BIO_socket_nbio(s, 1)) {
ERR_print_errors(bio_err);
goto end;
}
BIO_printf(bio_c_out, "Turned on non blocking io\n");
}
#ifndef OPENSSL_NO_DTLS
if (isdtls) {
union BIO_sock_info_u peer_info;
#ifndef OPENSSL_NO_SCTP
if (protocol == IPPROTO_SCTP)
sbio = BIO_new_dgram_sctp(s, BIO_NOCLOSE);
else
#endif
sbio = BIO_new_dgram(s, BIO_NOCLOSE);
if ((peer_info.addr = BIO_ADDR_new()) == NULL) {
BIO_printf(bio_err, "memory allocation failure\n");
BIO_closesocket(s);
goto end;
}
if (!BIO_sock_info(s, BIO_SOCK_INFO_ADDRESS, &peer_info)) {
BIO_printf(bio_err, "getsockname:errno=%d\n",
get_last_socket_error());
BIO_ADDR_free(peer_info.addr);
BIO_closesocket(s);
goto end;
}
(void)BIO_ctrl_set_connected(sbio, peer_info.addr);
BIO_ADDR_free(peer_info.addr);
peer_info.addr = NULL;
if (enable_timeouts) {
timeout.tv_sec = 0;
timeout.tv_usec = DGRAM_RCV_TIMEOUT;
BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_RECV_TIMEOUT, 0, &timeout);
timeout.tv_sec = 0;
timeout.tv_usec = DGRAM_SND_TIMEOUT;
BIO_ctrl(sbio, BIO_CTRL_DGRAM_SET_SEND_TIMEOUT, 0, &timeout);
}
if (socket_mtu) {
if (socket_mtu < DTLS_get_link_min_mtu(con)) {
BIO_printf(bio_err, "MTU too small. Must be at least %ld\n",
DTLS_get_link_min_mtu(con));
BIO_free(sbio);
goto shut;
}
SSL_set_options(con, SSL_OP_NO_QUERY_MTU);
if (!DTLS_set_link_mtu(con, socket_mtu)) {
BIO_printf(bio_err, "Failed to set MTU\n");
BIO_free(sbio);
goto shut;
}
} else {
/* want to do MTU discovery */
BIO_ctrl(sbio, BIO_CTRL_DGRAM_MTU_DISCOVER, 0, NULL);
}
} else
#endif /* OPENSSL_NO_DTLS */
sbio = BIO_new_socket(s, BIO_NOCLOSE);
if (nbio_test) {
BIO *test;
test = BIO_new(BIO_f_nbio_test());
sbio = BIO_push(test, sbio);
}
if (c_debug) {
BIO_set_callback(sbio, bio_dump_callback);
BIO_set_callback_arg(sbio, (char *)bio_c_out);
}
if (c_msg) {
#ifndef OPENSSL_NO_SSL_TRACE
if (c_msg == 2)
SSL_set_msg_callback(con, SSL_trace);
else
#endif
SSL_set_msg_callback(con, msg_cb);
SSL_set_msg_callback_arg(con, bio_c_msg ? bio_c_msg : bio_c_out);
}
if (c_tlsextdebug) {
SSL_set_tlsext_debug_callback(con, tlsext_cb);
SSL_set_tlsext_debug_arg(con, bio_c_out);
}
#ifndef OPENSSL_NO_OCSP
if (c_status_req) {
SSL_set_tlsext_status_type(con, TLSEXT_STATUSTYPE_ocsp);
SSL_CTX_set_tlsext_status_cb(ctx, ocsp_resp_cb);
SSL_CTX_set_tlsext_status_arg(ctx, bio_c_out);
}
#endif
SSL_set_bio(con, sbio, sbio);
SSL_set_connect_state(con);
/* ok, lets connect */
if (fileno_stdin() > SSL_get_fd(con))
width = fileno_stdin() + 1;
else
width = SSL_get_fd(con) + 1;
read_tty = 1;
write_tty = 0;
tty_on = 0;
read_ssl = 1;
write_ssl = 1;
cbuf_len = 0;
cbuf_off = 0;
sbuf_len = 0;
sbuf_off = 0;
switch ((PROTOCOL_CHOICE) starttls_proto) {
case PROTO_OFF:
break;
case PROTO_LMTP:
case PROTO_SMTP:
{
/*
* This is an ugly hack that does a lot of assumptions. We do
* have to handle multi-line responses which may come in a single
* packet or not. We therefore have to use BIO_gets() which does
* need a buffering BIO. So during the initial chitchat we do
* push a buffering BIO into the chain that is removed again
* later on to not disturb the rest of the s_client operation.
*/
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
/* Wait for multi-line response to end from LMTP or SMTP */
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
} while (mbuf_len > 3 && mbuf[3] == '-');
if (protohost == NULL)
protohost = "mail.example.com";
if (starttls_proto == (int)PROTO_LMTP)
BIO_printf(fbio, "LHLO %s\r\n", protohost);
else
BIO_printf(fbio, "EHLO %s\r\n", protohost);
(void)BIO_flush(fbio);
/*
* Wait for multi-line response to end LHLO LMTP or EHLO SMTP
* response.
*/
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
if (strstr(mbuf, "STARTTLS"))
foundit = 1;
} while (mbuf_len > 3 && mbuf[3] == '-');
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
if (!foundit)
BIO_printf(bio_err,
"Didn't find STARTTLS in server response,"
" trying anyway...\n");
BIO_printf(sbio, "STARTTLS\r\n");
BIO_read(sbio, sbuf, BUFSIZZ);
}
break;
case PROTO_POP3:
{
BIO_read(sbio, mbuf, BUFSIZZ);
BIO_printf(sbio, "STLS\r\n");
mbuf_len = BIO_read(sbio, sbuf, BUFSIZZ);
if (mbuf_len < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto end;
}
}
break;
case PROTO_IMAP:
{
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
BIO_gets(fbio, mbuf, BUFSIZZ);
/* STARTTLS command requires CAPABILITY... */
BIO_printf(fbio, ". CAPABILITY\r\n");
(void)BIO_flush(fbio);
/* wait for multi-line CAPABILITY response */
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
if (strstr(mbuf, "STARTTLS"))
foundit = 1;
}
while (mbuf_len > 3 && mbuf[0] != '.');
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
if (!foundit)
BIO_printf(bio_err,
"Didn't find STARTTLS in server response,"
" trying anyway...\n");
BIO_printf(sbio, ". STARTTLS\r\n");
BIO_read(sbio, sbuf, BUFSIZZ);
}
break;
case PROTO_FTP:
{
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
/* wait for multi-line response to end from FTP */
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
}
- while (mbuf_len > 3 && mbuf[3] == '-');
+ while (mbuf_len > 3 && (!isdigit(mbuf[0]) || !isdigit(mbuf[1]) || !isdigit(mbuf[2]) || mbuf[3] != ' '));
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
BIO_printf(sbio, "AUTH TLS\r\n");
BIO_read(sbio, sbuf, BUFSIZZ);
}
break;
case PROTO_XMPP:
case PROTO_XMPP_SERVER:
{
int seen = 0;
BIO_printf(sbio, "<stream:stream "
"xmlns:stream='http://etherx.jabber.org/streams' "
"xmlns='jabber:%s' to='%s' version='1.0'>",
starttls_proto == PROTO_XMPP ? "client" : "server",
protohost ? protohost : host);
seen = BIO_read(sbio, mbuf, BUFSIZZ);
if (seen < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto end;
}
mbuf[seen] = '\0';
while (!strstr
(mbuf, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'")
&& !strstr(mbuf,
"<starttls xmlns=\"urn:ietf:params:xml:ns:xmpp-tls\""))
{
seen = BIO_read(sbio, mbuf, BUFSIZZ);
if (seen <= 0)
goto shut;
mbuf[seen] = '\0';
}
BIO_printf(sbio,
"<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
seen = BIO_read(sbio, sbuf, BUFSIZZ);
if (seen < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto shut;
}
sbuf[seen] = '\0';
if (!strstr(sbuf, "<proceed"))
goto shut;
mbuf[0] = '\0';
}
break;
case PROTO_TELNET:
{
static const unsigned char tls_do[] = {
/* IAC DO START_TLS */
255, 253, 46
};
static const unsigned char tls_will[] = {
/* IAC WILL START_TLS */
255, 251, 46
};
static const unsigned char tls_follows[] = {
/* IAC SB START_TLS FOLLOWS IAC SE */
255, 250, 46, 1, 255, 240
};
int bytes;
/* Telnet server should demand we issue START_TLS */
bytes = BIO_read(sbio, mbuf, BUFSIZZ);
if (bytes != 3 || memcmp(mbuf, tls_do, 3) != 0)
goto shut;
/* Agree to issue START_TLS and send the FOLLOWS sub-command */
BIO_write(sbio, tls_will, 3);
BIO_write(sbio, tls_follows, 6);
(void)BIO_flush(sbio);
/* Telnet server also sent the FOLLOWS sub-command */
bytes = BIO_read(sbio, mbuf, BUFSIZZ);
if (bytes != 6 || memcmp(mbuf, tls_follows, 6) != 0)
goto shut;
}
break;
case PROTO_CONNECT:
{
enum {
error_proto, /* Wrong protocol, not even HTTP */
error_connect, /* CONNECT failed */
success
} foundit = error_connect;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
BIO_printf(fbio, "CONNECT %s HTTP/1.0\r\n\r\n", connectstr);
(void)BIO_flush(fbio);
/*
* The first line is the HTTP response. According to RFC 7230,
* it's formated exactly like this:
*
* HTTP/d.d ddd Reason text\r\n
*/
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
if (mbuf_len < (int)strlen("HTTP/1.0 200")) {
BIO_printf(bio_err,
"%s: HTTP CONNECT failed, insufficient response "
"from proxy (got %d octets)\n", prog, mbuf_len);
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
goto shut;
}
if (mbuf[8] != ' ') {
BIO_printf(bio_err,
"%s: HTTP CONNECT failed, incorrect response "
"from proxy\n", prog);
foundit = error_proto;
} else if (mbuf[9] != '2') {
BIO_printf(bio_err, "%s: HTTP CONNECT failed: %s ", prog,
&mbuf[9]);
} else {
foundit = success;
}
if (foundit != error_proto) {
/* Read past all following headers */
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
} while (mbuf_len > 2);
}
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
if (foundit != success) {
goto shut;
}
}
break;
case PROTO_IRC:
{
int numeric;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
BIO_printf(fbio, "STARTTLS\r\n");
(void)BIO_flush(fbio);
width = SSL_get_fd(con) + 1;
do {
numeric = 0;
FD_ZERO(&readfds);
openssl_fdset(SSL_get_fd(con), &readfds);
timeout.tv_sec = S_CLIENT_IRC_READ_TIMEOUT;
timeout.tv_usec = 0;
/*
* If the IRCd doesn't respond within
* S_CLIENT_IRC_READ_TIMEOUT seconds, assume
* it doesn't support STARTTLS. Many IRCds
* will not give _any_ sort of response to a
* STARTTLS command when it's not supported.
*/
if (!BIO_get_buffer_num_lines(fbio)
&& !BIO_pending(fbio)
&& !BIO_pending(sbio)
&& select(width, (void *)&readfds, NULL, NULL,
&timeout) < 1) {
BIO_printf(bio_err,
"Timeout waiting for response (%d seconds).\n",
S_CLIENT_IRC_READ_TIMEOUT);
break;
}
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
if (mbuf_len < 1 || sscanf(mbuf, "%*s %d", &numeric) != 1)
break;
/* :example.net 451 STARTTLS :You have not registered */
/* :example.net 421 STARTTLS :Unknown command */
if ((numeric == 451 || numeric == 421)
&& strstr(mbuf, "STARTTLS") != NULL) {
BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf);
break;
}
if (numeric == 691) {
BIO_printf(bio_err, "STARTTLS negotiation failed: ");
ERR_print_errors(bio_err);
break;
}
} while (numeric != 670);
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
if (numeric != 670) {
BIO_printf(bio_err, "Server does not support STARTTLS.\n");
ret = 1;
goto shut;
}
}
break;
case PROTO_MYSQL:
{
/* SSL request packet */
static const unsigned char ssl_req[] = {
/* payload_length, sequence_id */
0x20, 0x00, 0x00, 0x01,
/* payload */
/* capability flags, CLIENT_SSL always set */
0x85, 0xae, 0x7f, 0x00,
/* max-packet size */
0x00, 0x00, 0x00, 0x01,
/* character set */
0x21,
/* string[23] reserved (all [0]) */
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
int bytes = 0;
int ssl_flg = 0x800;
int pos;
const unsigned char *packet = (const unsigned char *)sbuf;
/* Receiving Initial Handshake packet. */
bytes = BIO_read(sbio, (void *)packet, BUFSIZZ);
if (bytes < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto shut;
/* Packet length[3], Packet number[1] + minimum payload[17] */
} else if (bytes < 21) {
BIO_printf(bio_err, "MySQL packet too short.\n");
goto shut;
} else if (bytes != (4 + packet[0] +
(packet[1] << 8) +
(packet[2] << 16))) {
BIO_printf(bio_err, "MySQL packet length does not match.\n");
goto shut;
/* protocol version[1] */
} else if (packet[4] != 0xA) {
BIO_printf(bio_err,
"Only MySQL protocol version 10 is supported.\n");
goto shut;
}
pos = 5;
/* server version[string+NULL] */
for (;;) {
if (pos >= bytes) {
BIO_printf(bio_err, "Cannot confirm server version. ");
goto shut;
} else if (packet[pos++] == '\0') {
break;
}
}
/* make sure we have at least 15 bytes left in the packet */
if (pos + 15 > bytes) {
BIO_printf(bio_err,
"MySQL server handshake packet is broken.\n");
goto shut;
}
pos += 12; /* skip over conn id[4] + SALT[8] */
if (packet[pos++] != '\0') { /* verify filler */
BIO_printf(bio_err,
"MySQL packet is broken.\n");
goto shut;
}
/* capability flags[2] */
if (!((packet[pos] + (packet[pos + 1] << 8)) & ssl_flg)) {
BIO_printf(bio_err, "MySQL server does not support SSL.\n");
goto shut;
}
/* Sending SSL Handshake packet. */
BIO_write(sbio, ssl_req, sizeof(ssl_req));
(void)BIO_flush(sbio);
}
break;
case PROTO_POSTGRES:
{
static const unsigned char ssl_request[] = {
/* Length SSLRequest */
0, 0, 0, 8, 4, 210, 22, 47
};
int bytes;
/* Send SSLRequest packet */
BIO_write(sbio, ssl_request, 8);
(void)BIO_flush(sbio);
/* Reply will be a single S if SSL is enabled */
bytes = BIO_read(sbio, sbuf, BUFSIZZ);
if (bytes != 1 || sbuf[0] != 'S')
goto shut;
}
break;
case PROTO_NNTP:
{
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
BIO_gets(fbio, mbuf, BUFSIZZ);
/* STARTTLS command requires CAPABILITIES... */
BIO_printf(fbio, "CAPABILITIES\r\n");
(void)BIO_flush(fbio);
/* wait for multi-line CAPABILITIES response */
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
if (strstr(mbuf, "STARTTLS"))
foundit = 1;
} while (mbuf_len > 1 && mbuf[0] != '.');
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
if (!foundit)
BIO_printf(bio_err,
"Didn't find STARTTLS in server response,"
" trying anyway...\n");
BIO_printf(sbio, "STARTTLS\r\n");
mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
if (mbuf_len < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto end;
}
mbuf[mbuf_len] = '\0';
if (strstr(mbuf, "382") == NULL) {
BIO_printf(bio_err, "STARTTLS failed: %s", mbuf);
goto shut;
}
}
break;
case PROTO_SIEVE:
{
int foundit = 0;
BIO *fbio = BIO_new(BIO_f_buffer());
BIO_push(fbio, sbio);
/* wait for multi-line response to end from Sieve */
do {
mbuf_len = BIO_gets(fbio, mbuf, BUFSIZZ);
/*
* According to RFC 5804 § 1.7, capability
* is case-insensitive, make it uppercase
*/
if (mbuf_len > 1 && mbuf[0] == '"') {
make_uppercase(mbuf);
if (strncmp(mbuf, "\"STARTTLS\"", 10) == 0)
foundit = 1;
}
} while (mbuf_len > 1 && mbuf[0] == '"');
(void)BIO_flush(fbio);
BIO_pop(fbio);
BIO_free(fbio);
if (!foundit)
BIO_printf(bio_err,
"Didn't find STARTTLS in server response,"
" trying anyway...\n");
BIO_printf(sbio, "STARTTLS\r\n");
mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
if (mbuf_len < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto end;
}
mbuf[mbuf_len] = '\0';
if (mbuf_len < 2) {
BIO_printf(bio_err, "STARTTLS failed: %s", mbuf);
goto shut;
}
/*
* According to RFC 5804 § 2.2, response codes are case-
* insensitive, make it uppercase but preserve the response.
*/
strncpy(sbuf, mbuf, 2);
make_uppercase(sbuf);
if (strncmp(sbuf, "OK", 2) != 0) {
BIO_printf(bio_err, "STARTTLS not supported: %s", mbuf);
goto shut;
}
}
break;
case PROTO_LDAP:
{
/* StartTLS Operation according to RFC 4511 */
static char ldap_tls_genconf[] = "asn1=SEQUENCE:LDAPMessage\n"
"[LDAPMessage]\n"
"messageID=INTEGER:1\n"
"extendedReq=EXPLICIT:23A,IMPLICIT:0C,"
"FORMAT:ASCII,OCT:1.3.6.1.4.1.1466.20037\n";
long errline = -1;
char *genstr = NULL;
int result = -1;
ASN1_TYPE *atyp = NULL;
BIO *ldapbio = BIO_new(BIO_s_mem());
CONF *cnf = NCONF_new(NULL);
if (cnf == NULL) {
BIO_free(ldapbio);
goto end;
}
BIO_puts(ldapbio, ldap_tls_genconf);
if (NCONF_load_bio(cnf, ldapbio, &errline) <= 0) {
BIO_free(ldapbio);
NCONF_free(cnf);
if (errline <= 0) {
BIO_printf(bio_err, "NCONF_load_bio failed\n");
goto end;
} else {
BIO_printf(bio_err, "Error on line %ld\n", errline);
goto end;
}
}
BIO_free(ldapbio);
genstr = NCONF_get_string(cnf, "default", "asn1");
if (genstr == NULL) {
NCONF_free(cnf);
BIO_printf(bio_err, "NCONF_get_string failed\n");
goto end;
}
atyp = ASN1_generate_nconf(genstr, cnf);
if (atyp == NULL) {
NCONF_free(cnf);
BIO_printf(bio_err, "ASN1_generate_nconf failed\n");
goto end;
}
NCONF_free(cnf);
/* Send SSLRequest packet */
BIO_write(sbio, atyp->value.sequence->data,
atyp->value.sequence->length);
(void)BIO_flush(sbio);
ASN1_TYPE_free(atyp);
mbuf_len = BIO_read(sbio, mbuf, BUFSIZZ);
if (mbuf_len < 0) {
BIO_printf(bio_err, "BIO_read failed\n");
goto end;
}
result = ldap_ExtendedResponse_parse(mbuf, mbuf_len);
if (result < 0) {
BIO_printf(bio_err, "ldap_ExtendedResponse_parse failed\n");
goto shut;
} else if (result > 0) {
BIO_printf(bio_err, "STARTTLS failed, LDAP Result Code: %i\n",
result);
goto shut;
}
mbuf_len = 0;
}
break;
}
if (early_data_file != NULL
&& ((SSL_get0_session(con) != NULL
&& SSL_SESSION_get_max_early_data(SSL_get0_session(con)) > 0)
|| (psksess != NULL
&& SSL_SESSION_get_max_early_data(psksess) > 0))) {
BIO *edfile = BIO_new_file(early_data_file, "r");
size_t readbytes, writtenbytes;
int finish = 0;
if (edfile == NULL) {
BIO_printf(bio_err, "Cannot open early data file\n");
goto shut;
}
while (!finish) {
if (!BIO_read_ex(edfile, cbuf, BUFSIZZ, &readbytes))
finish = 1;
while (!SSL_write_early_data(con, cbuf, readbytes, &writtenbytes)) {
switch (SSL_get_error(con, 0)) {
case SSL_ERROR_WANT_WRITE:
case SSL_ERROR_WANT_ASYNC:
case SSL_ERROR_WANT_READ:
/* Just keep trying - busy waiting */
continue;
default:
BIO_printf(bio_err, "Error writing early data\n");
BIO_free(edfile);
ERR_print_errors(bio_err);
goto shut;
}
}
}
BIO_free(edfile);
}
for (;;) {
FD_ZERO(&readfds);
FD_ZERO(&writefds);
if (SSL_is_dtls(con) && DTLSv1_get_timeout(con, &timeout))
timeoutp = &timeout;
else
timeoutp = NULL;
if (!SSL_is_init_finished(con) && SSL_total_renegotiations(con) == 0
&& SSL_get_key_update_type(con) == SSL_KEY_UPDATE_NONE) {
in_init = 1;
tty_on = 0;
} else {
tty_on = 1;
if (in_init) {
in_init = 0;
if (c_brief) {
BIO_puts(bio_err, "CONNECTION ESTABLISHED\n");
print_ssl_summary(con);
}
print_stuff(bio_c_out, con, full_log);
if (full_log > 0)
full_log--;
if (starttls_proto) {
BIO_write(bio_err, mbuf, mbuf_len);
/* We don't need to know any more */
if (!reconnect)
starttls_proto = PROTO_OFF;
}
if (reconnect) {
reconnect--;
BIO_printf(bio_c_out,
"drop connection and then reconnect\n");
do_ssl_shutdown(con);
SSL_set_connect_state(con);
BIO_closesocket(SSL_get_fd(con));
goto re_start;
}
}
}
ssl_pending = read_ssl && SSL_has_pending(con);
if (!ssl_pending) {
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
if (tty_on) {
/*
* Note that select() returns when read _would not block_,
* and EOF satisfies that. To avoid a CPU-hogging loop,
* set the flag so we exit.
*/
if (read_tty && !at_eof)
openssl_fdset(fileno_stdin(), &readfds);
#if !defined(OPENSSL_SYS_VMS)
if (write_tty)
openssl_fdset(fileno_stdout(), &writefds);
#endif
}
if (read_ssl)
openssl_fdset(SSL_get_fd(con), &readfds);
if (write_ssl)
openssl_fdset(SSL_get_fd(con), &writefds);
#else
if (!tty_on || !write_tty) {
if (read_ssl)
openssl_fdset(SSL_get_fd(con), &readfds);
if (write_ssl)
openssl_fdset(SSL_get_fd(con), &writefds);
}
#endif
/*
* Note: under VMS with SOCKETSHR the second parameter is
* currently of type (int *) whereas under other systems it is
* (void *) if you don't have a cast it will choke the compiler:
* if you do have a cast then you can either go for (int *) or
* (void *).
*/
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS)
/*
* Under Windows/DOS we make the assumption that we can always
* write to the tty: therefore if we need to write to the tty we
* just fall through. Otherwise we timeout the select every
* second and see if there are any keypresses. Note: this is a
* hack, in a proper Windows application we wouldn't do this.
*/
i = 0;
if (!write_tty) {
if (read_tty) {
tv.tv_sec = 1;
tv.tv_usec = 0;
i = select(width, (void *)&readfds, (void *)&writefds,
NULL, &tv);
if (!i && (!has_stdin_waiting() || !read_tty))
continue;
} else
i = select(width, (void *)&readfds, (void *)&writefds,
NULL, timeoutp);
}
#else
i = select(width, (void *)&readfds, (void *)&writefds,
NULL, timeoutp);
#endif
if (i < 0) {
BIO_printf(bio_err, "bad select %d\n",
get_last_socket_error());
goto shut;
}
}
if (SSL_is_dtls(con) && DTLSv1_handle_timeout(con) > 0)
BIO_printf(bio_err, "TIMEOUT occurred\n");
if (!ssl_pending && FD_ISSET(SSL_get_fd(con), &writefds)) {
k = SSL_write(con, &(cbuf[cbuf_off]), (unsigned int)cbuf_len);
switch (SSL_get_error(con, k)) {
case SSL_ERROR_NONE:
cbuf_off += k;
cbuf_len -= k;
if (k <= 0)
goto end;
/* we have done a write(con,NULL,0); */
if (cbuf_len <= 0) {
read_tty = 1;
write_ssl = 0;
} else { /* if (cbuf_len > 0) */
read_tty = 0;
write_ssl = 1;
}
break;
case SSL_ERROR_WANT_WRITE:
BIO_printf(bio_c_out, "write W BLOCK\n");
write_ssl = 1;
read_tty = 0;
break;
case SSL_ERROR_WANT_ASYNC:
BIO_printf(bio_c_out, "write A BLOCK\n");
wait_for_async(con);
write_ssl = 1;
read_tty = 0;
break;
case SSL_ERROR_WANT_READ:
BIO_printf(bio_c_out, "write R BLOCK\n");
write_tty = 0;
read_ssl = 1;
write_ssl = 0;
break;
case SSL_ERROR_WANT_X509_LOOKUP:
BIO_printf(bio_c_out, "write X BLOCK\n");
break;
case SSL_ERROR_ZERO_RETURN:
if (cbuf_len != 0) {
BIO_printf(bio_c_out, "shutdown\n");
ret = 0;
goto shut;
} else {
read_tty = 1;
write_ssl = 0;
break;
}
case SSL_ERROR_SYSCALL:
if ((k != 0) || (cbuf_len != 0)) {
BIO_printf(bio_err, "write:errno=%d\n",
get_last_socket_error());
goto shut;
} else {
read_tty = 1;
write_ssl = 0;
}
break;
case SSL_ERROR_WANT_ASYNC_JOB:
/* This shouldn't ever happen in s_client - treat as an error */
case SSL_ERROR_SSL:
ERR_print_errors(bio_err);
goto shut;
}
}
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_VMS)
/* Assume Windows/DOS/BeOS can always write */
else if (!ssl_pending && write_tty)
#else
else if (!ssl_pending && FD_ISSET(fileno_stdout(), &writefds))
#endif
{
#ifdef CHARSET_EBCDIC
ascii2ebcdic(&(sbuf[sbuf_off]), &(sbuf[sbuf_off]), sbuf_len);
#endif
i = raw_write_stdout(&(sbuf[sbuf_off]), sbuf_len);
if (i <= 0) {
BIO_printf(bio_c_out, "DONE\n");
ret = 0;
goto shut;
}
sbuf_len -= i;
sbuf_off += i;
if (sbuf_len <= 0) {
read_ssl = 1;
write_tty = 0;
}
} else if (ssl_pending || FD_ISSET(SSL_get_fd(con), &readfds)) {
#ifdef RENEG
{
static int iiii;
if (++iiii == 52) {
SSL_renegotiate(con);
iiii = 0;
}
}
#endif
k = SSL_read(con, sbuf, 1024 /* BUFSIZZ */ );
switch (SSL_get_error(con, k)) {
case SSL_ERROR_NONE:
if (k <= 0)
goto end;
sbuf_off = 0;
sbuf_len = k;
read_ssl = 0;
write_tty = 1;
break;
case SSL_ERROR_WANT_ASYNC:
BIO_printf(bio_c_out, "read A BLOCK\n");
wait_for_async(con);
write_tty = 0;
read_ssl = 1;
if ((read_tty == 0) && (write_ssl == 0))
write_ssl = 1;
break;
case SSL_ERROR_WANT_WRITE:
BIO_printf(bio_c_out, "read W BLOCK\n");
write_ssl = 1;
read_tty = 0;
break;
case SSL_ERROR_WANT_READ:
BIO_printf(bio_c_out, "read R BLOCK\n");
write_tty = 0;
read_ssl = 1;
if ((read_tty == 0) && (write_ssl == 0))
write_ssl = 1;
break;
case SSL_ERROR_WANT_X509_LOOKUP:
BIO_printf(bio_c_out, "read X BLOCK\n");
break;
case SSL_ERROR_SYSCALL:
ret = get_last_socket_error();
if (c_brief)
BIO_puts(bio_err, "CONNECTION CLOSED BY SERVER\n");
else
BIO_printf(bio_err, "read:errno=%d\n", ret);
goto shut;
case SSL_ERROR_ZERO_RETURN:
BIO_printf(bio_c_out, "closed\n");
ret = 0;
goto shut;
case SSL_ERROR_WANT_ASYNC_JOB:
/* This shouldn't ever happen in s_client. Treat as an error */
case SSL_ERROR_SSL:
ERR_print_errors(bio_err);
goto shut;
}
}
/* OPENSSL_SYS_MSDOS includes OPENSSL_SYS_WINDOWS */
#if defined(OPENSSL_SYS_MSDOS)
else if (has_stdin_waiting())
#else
else if (FD_ISSET(fileno_stdin(), &readfds))
#endif
{
if (crlf) {
int j, lf_num;
i = raw_read_stdin(cbuf, BUFSIZZ / 2);
lf_num = 0;
/* both loops are skipped when i <= 0 */
for (j = 0; j < i; j++)
if (cbuf[j] == '\n')
lf_num++;
for (j = i - 1; j >= 0; j--) {
cbuf[j + lf_num] = cbuf[j];
if (cbuf[j] == '\n') {
lf_num--;
i++;
cbuf[j + lf_num] = '\r';
}
}
assert(lf_num == 0);
} else
i = raw_read_stdin(cbuf, BUFSIZZ);
#if !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_MSDOS)
if (i == 0)
at_eof = 1;
#endif
if ((!c_ign_eof) && ((i <= 0) || (cbuf[0] == 'Q' && cmdletters))) {
BIO_printf(bio_err, "DONE\n");
ret = 0;
goto shut;
}
if ((!c_ign_eof) && (cbuf[0] == 'R' && cmdletters)) {
BIO_printf(bio_err, "RENEGOTIATING\n");
SSL_renegotiate(con);
cbuf_len = 0;
} else if (!c_ign_eof && (cbuf[0] == 'K' || cbuf[0] == 'k' )
&& cmdletters) {
BIO_printf(bio_err, "KEYUPDATE\n");
SSL_key_update(con,
cbuf[0] == 'K' ? SSL_KEY_UPDATE_REQUESTED
: SSL_KEY_UPDATE_NOT_REQUESTED);
cbuf_len = 0;
}
#ifndef OPENSSL_NO_HEARTBEATS
else if ((!c_ign_eof) && (cbuf[0] == 'B' && cmdletters)) {
BIO_printf(bio_err, "HEARTBEATING\n");
SSL_heartbeat(con);
cbuf_len = 0;
}
#endif
else {
cbuf_len = i;
cbuf_off = 0;
#ifdef CHARSET_EBCDIC
ebcdic2ascii(cbuf, cbuf, i);
#endif
}
write_ssl = 1;
read_tty = 0;
}
}
ret = 0;
shut:
if (in_init)
print_stuff(bio_c_out, con, full_log);
do_ssl_shutdown(con);
/*
* If we ended with an alert being sent, but still with data in the
* network buffer to be read, then calling BIO_closesocket() will
* result in a TCP-RST being sent. On some platforms (notably
* Windows) then this will result in the peer immediately abandoning
* the connection including any buffered alert data before it has
* had a chance to be read. Shutting down the sending side first,
* and then closing the socket sends TCP-FIN first followed by
* TCP-RST. This seems to allow the peer to read the alert data.
*/
shutdown(SSL_get_fd(con), 1); /* SHUT_WR */
/*
* We just said we have nothing else to say, but it doesn't mean that
* the other side has nothing. It's even recommended to consume incoming
* data. [In testing context this ensures that alerts are passed on...]
*/
timeout.tv_sec = 0;
timeout.tv_usec = 500000; /* some extreme round-trip */
do {
FD_ZERO(&readfds);
openssl_fdset(s, &readfds);
} while (select(s + 1, &readfds, NULL, NULL, &timeout) > 0
&& BIO_read(sbio, sbuf, BUFSIZZ) > 0);
BIO_closesocket(SSL_get_fd(con));
end:
if (con != NULL) {
if (prexit != 0)
print_stuff(bio_c_out, con, 1);
SSL_free(con);
}
SSL_SESSION_free(psksess);
#if !defined(OPENSSL_NO_NEXTPROTONEG)
OPENSSL_free(next_proto.data);
#endif
SSL_CTX_free(ctx);
set_keylog_file(NULL, NULL);
X509_free(cert);
sk_X509_CRL_pop_free(crls, X509_CRL_free);
EVP_PKEY_free(key);
sk_X509_pop_free(chain, X509_free);
OPENSSL_free(pass);
#ifndef OPENSSL_NO_SRP
OPENSSL_free(srp_arg.srppassin);
#endif
OPENSSL_free(connectstr);
OPENSSL_free(bindstr);
OPENSSL_free(host);
OPENSSL_free(port);
X509_VERIFY_PARAM_free(vpm);
ssl_excert_free(exc);
sk_OPENSSL_STRING_free(ssl_args);
sk_OPENSSL_STRING_free(dane_tlsa_rrset);
SSL_CONF_CTX_free(cctx);
OPENSSL_clear_free(cbuf, BUFSIZZ);
OPENSSL_clear_free(sbuf, BUFSIZZ);
OPENSSL_clear_free(mbuf, BUFSIZZ);
release_engine(e);
BIO_free(bio_c_out);
bio_c_out = NULL;
BIO_free(bio_c_msg);
bio_c_msg = NULL;
return ret;
}
static void print_stuff(BIO *bio, SSL *s, int full)
{
X509 *peer = NULL;
STACK_OF(X509) *sk;
const SSL_CIPHER *c;
int i, istls13 = (SSL_version(s) == TLS1_3_VERSION);
long verify_result;
#ifndef OPENSSL_NO_COMP
const COMP_METHOD *comp, *expansion;
#endif
unsigned char *exportedkeymat;
#ifndef OPENSSL_NO_CT
const SSL_CTX *ctx = SSL_get_SSL_CTX(s);
#endif
if (full) {
int got_a_chain = 0;
sk = SSL_get_peer_cert_chain(s);
if (sk != NULL) {
got_a_chain = 1;
BIO_printf(bio, "---\nCertificate chain\n");
for (i = 0; i < sk_X509_num(sk); i++) {
BIO_printf(bio, "%2d s:", i);
X509_NAME_print_ex(bio, X509_get_subject_name(sk_X509_value(sk, i)), 0, get_nameopt());
BIO_puts(bio, "\n");
BIO_printf(bio, " i:");
X509_NAME_print_ex(bio, X509_get_issuer_name(sk_X509_value(sk, i)), 0, get_nameopt());
BIO_puts(bio, "\n");
if (c_showcerts)
PEM_write_bio_X509(bio, sk_X509_value(sk, i));
}
}
BIO_printf(bio, "---\n");
peer = SSL_get_peer_certificate(s);
if (peer != NULL) {
BIO_printf(bio, "Server certificate\n");
/* Redundant if we showed the whole chain */
if (!(c_showcerts && got_a_chain))
PEM_write_bio_X509(bio, peer);
dump_cert_text(bio, peer);
} else {
BIO_printf(bio, "no peer certificate available\n");
}
print_ca_names(bio, s);
ssl_print_sigalgs(bio, s);
ssl_print_tmp_key(bio, s);
#ifndef OPENSSL_NO_CT
/*
* When the SSL session is anonymous, or resumed via an abbreviated
* handshake, no SCTs are provided as part of the handshake. While in
* a resumed session SCTs may be present in the session's certificate,
* no callbacks are invoked to revalidate these, and in any case that
* set of SCTs may be incomplete. Thus it makes little sense to
* attempt to display SCTs from a resumed session's certificate, and of
* course none are associated with an anonymous peer.
*/
if (peer != NULL && !SSL_session_reused(s) && SSL_ct_is_enabled(s)) {
const STACK_OF(SCT) *scts = SSL_get0_peer_scts(s);
int sct_count = scts != NULL ? sk_SCT_num(scts) : 0;
BIO_printf(bio, "---\nSCTs present (%i)\n", sct_count);
if (sct_count > 0) {
const CTLOG_STORE *log_store = SSL_CTX_get0_ctlog_store(ctx);
BIO_printf(bio, "---\n");
for (i = 0; i < sct_count; ++i) {
SCT *sct = sk_SCT_value(scts, i);
BIO_printf(bio, "SCT validation status: %s\n",
SCT_validation_status_string(sct));
SCT_print(sct, bio, 0, log_store);
if (i < sct_count - 1)
BIO_printf(bio, "\n---\n");
}
BIO_printf(bio, "\n");
}
}
#endif
BIO_printf(bio,
"---\nSSL handshake has read %ju bytes "
"and written %ju bytes\n",
BIO_number_read(SSL_get_rbio(s)),
BIO_number_written(SSL_get_wbio(s)));
}
print_verify_detail(s, bio);
BIO_printf(bio, (SSL_session_reused(s) ? "---\nReused, " : "---\nNew, "));
c = SSL_get_current_cipher(s);
BIO_printf(bio, "%s, Cipher is %s\n",
SSL_CIPHER_get_version(c), SSL_CIPHER_get_name(c));
if (peer != NULL) {
EVP_PKEY *pktmp;
pktmp = X509_get0_pubkey(peer);
BIO_printf(bio, "Server public key is %d bit\n",
EVP_PKEY_bits(pktmp));
}
BIO_printf(bio, "Secure Renegotiation IS%s supported\n",
SSL_get_secure_renegotiation_support(s) ? "" : " NOT");
#ifndef OPENSSL_NO_COMP
comp = SSL_get_current_compression(s);
expansion = SSL_get_current_expansion(s);
BIO_printf(bio, "Compression: %s\n",
comp ? SSL_COMP_get_name(comp) : "NONE");
BIO_printf(bio, "Expansion: %s\n",
expansion ? SSL_COMP_get_name(expansion) : "NONE");
#endif
#ifdef SSL_DEBUG
{
/* Print out local port of connection: useful for debugging */
int sock;
union BIO_sock_info_u info;
sock = SSL_get_fd(s);
if ((info.addr = BIO_ADDR_new()) != NULL
&& BIO_sock_info(sock, BIO_SOCK_INFO_ADDRESS, &info)) {
BIO_printf(bio_c_out, "LOCAL PORT is %u\n",
ntohs(BIO_ADDR_rawport(info.addr)));
}
BIO_ADDR_free(info.addr);
}
#endif
#if !defined(OPENSSL_NO_NEXTPROTONEG)
if (next_proto.status != -1) {
const unsigned char *proto;
unsigned int proto_len;
SSL_get0_next_proto_negotiated(s, &proto, &proto_len);
BIO_printf(bio, "Next protocol: (%d) ", next_proto.status);
BIO_write(bio, proto, proto_len);
BIO_write(bio, "\n", 1);
}
#endif
{
const unsigned char *proto;
unsigned int proto_len;
SSL_get0_alpn_selected(s, &proto, &proto_len);
if (proto_len > 0) {
BIO_printf(bio, "ALPN protocol: ");
BIO_write(bio, proto, proto_len);
BIO_write(bio, "\n", 1);
} else
BIO_printf(bio, "No ALPN negotiated\n");
}
#ifndef OPENSSL_NO_SRTP
{
SRTP_PROTECTION_PROFILE *srtp_profile =
SSL_get_selected_srtp_profile(s);
if (srtp_profile)
BIO_printf(bio, "SRTP Extension negotiated, profile=%s\n",
srtp_profile->name);
}
#endif
if (istls13) {
switch (SSL_get_early_data_status(s)) {
case SSL_EARLY_DATA_NOT_SENT:
BIO_printf(bio, "Early data was not sent\n");
break;
case SSL_EARLY_DATA_REJECTED:
BIO_printf(bio, "Early data was rejected\n");
break;
case SSL_EARLY_DATA_ACCEPTED:
BIO_printf(bio, "Early data was accepted\n");
break;
}
/*
* We also print the verify results when we dump session information,
* but in TLSv1.3 we may not get that right away (or at all) depending
* on when we get a NewSessionTicket. Therefore we print it now as well.
*/
verify_result = SSL_get_verify_result(s);
BIO_printf(bio, "Verify return code: %ld (%s)\n", verify_result,
X509_verify_cert_error_string(verify_result));
} else {
/* In TLSv1.3 we do this on arrival of a NewSessionTicket */
SSL_SESSION_print(bio, SSL_get_session(s));
}
if (SSL_get_session(s) != NULL && keymatexportlabel != NULL) {
BIO_printf(bio, "Keying material exporter:\n");
BIO_printf(bio, " Label: '%s'\n", keymatexportlabel);
BIO_printf(bio, " Length: %i bytes\n", keymatexportlen);
exportedkeymat = app_malloc(keymatexportlen, "export key");
if (!SSL_export_keying_material(s, exportedkeymat,
keymatexportlen,
keymatexportlabel,
strlen(keymatexportlabel),
NULL, 0, 0)) {
BIO_printf(bio, " Error\n");
} else {
BIO_printf(bio, " Keying material: ");
for (i = 0; i < keymatexportlen; i++)
BIO_printf(bio, "%02X", exportedkeymat[i]);
BIO_printf(bio, "\n");
}
OPENSSL_free(exportedkeymat);
}
BIO_printf(bio, "---\n");
X509_free(peer);
/* flush, or debugging output gets mixed with http response */
(void)BIO_flush(bio);
}
# ifndef OPENSSL_NO_OCSP
static int ocsp_resp_cb(SSL *s, void *arg)
{
const unsigned char *p;
int len;
OCSP_RESPONSE *rsp;
len = SSL_get_tlsext_status_ocsp_resp(s, &p);
BIO_puts(arg, "OCSP response: ");
if (p == NULL) {
BIO_puts(arg, "no response sent\n");
return 1;
}
rsp = d2i_OCSP_RESPONSE(NULL, &p, len);
if (rsp == NULL) {
BIO_puts(arg, "response parse error\n");
BIO_dump_indent(arg, (char *)p, len, 4);
return 0;
}
BIO_puts(arg, "\n======================================\n");
OCSP_RESPONSE_print(arg, rsp, 0);
BIO_puts(arg, "======================================\n");
OCSP_RESPONSE_free(rsp);
return 1;
}
# endif
static int ldap_ExtendedResponse_parse(const char *buf, long rem)
{
const unsigned char *cur, *end;
long len;
int tag, xclass, inf, ret = -1;
cur = (const unsigned char *)buf;
end = cur + rem;
/*
* From RFC 4511:
*
* LDAPMessage ::= SEQUENCE {
* messageID MessageID,
* protocolOp CHOICE {
* ...
* extendedResp ExtendedResponse,
* ... },
* controls [0] Controls OPTIONAL }
*
* ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
* COMPONENTS OF LDAPResult,
* responseName [10] LDAPOID OPTIONAL,
* responseValue [11] OCTET STRING OPTIONAL }
*
* LDAPResult ::= SEQUENCE {
* resultCode ENUMERATED {
* success (0),
* ...
* other (80),
* ... },
* matchedDN LDAPDN,
* diagnosticMessage LDAPString,
* referral [3] Referral OPTIONAL }
*/
/* pull SEQUENCE */
inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE ||
(rem = end - cur, len > rem)) {
BIO_printf(bio_err, "Unexpected LDAP response\n");
goto end;
}
rem = len; /* ensure that we don't overstep the SEQUENCE */
/* pull MessageID */
inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_INTEGER ||
(rem = end - cur, len > rem)) {
BIO_printf(bio_err, "No MessageID\n");
goto end;
}
cur += len; /* shall we check for MessageId match or just skip? */
/* pull [APPLICATION 24] */
rem = end - cur;
inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
if (inf != V_ASN1_CONSTRUCTED || xclass != V_ASN1_APPLICATION ||
tag != 24) {
BIO_printf(bio_err, "Not ExtendedResponse\n");
goto end;
}
/* pull resultCode */
rem = end - cur;
inf = ASN1_get_object(&cur, &len, &tag, &xclass, rem);
if (inf != V_ASN1_UNIVERSAL || tag != V_ASN1_ENUMERATED || len == 0 ||
(rem = end - cur, len > rem)) {
BIO_printf(bio_err, "Not LDAPResult\n");
goto end;
}
/* len should always be one, but just in case... */
for (ret = 0, inf = 0; inf < len; inf++) {
ret <<= 8;
ret |= cur[inf];
}
/* There is more data, but we don't care... */
end:
return ret;
}
/*
* Host dNS Name verifier: used for checking that the hostname is in dNS format
* before setting it as SNI
*/
static int is_dNS_name(const char *host)
{
const size_t MAX_LABEL_LENGTH = 63;
size_t i;
int isdnsname = 0;
size_t length = strlen(host);
size_t label_length = 0;
int all_numeric = 1;
/*
* Deviation from strict DNS name syntax, also check names with '_'
* Check DNS name syntax, any '-' or '.' must be internal,
* and on either side of each '.' we can't have a '-' or '.'.
*
* If the name has just one label, we don't consider it a DNS name.
*/
for (i = 0; i < length && label_length < MAX_LABEL_LENGTH; ++i) {
char c = host[i];
if ((c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| c == '_') {
label_length += 1;
all_numeric = 0;
continue;
}
if (c >= '0' && c <= '9') {
label_length += 1;
continue;
}
/* Dot and hyphen cannot be first or last. */
if (i > 0 && i < length - 1) {
if (c == '-') {
label_length += 1;
continue;
}
/*
* Next to a dot the preceding and following characters must not be
* another dot or a hyphen. Otherwise, record that the name is
* plausible, since it has two or more labels.
*/
if (c == '.'
&& host[i + 1] != '.'
&& host[i - 1] != '-'
&& host[i + 1] != '-') {
label_length = 0;
isdnsname = 1;
continue;
}
}
isdnsname = 0;
break;
}
/* dNS name must not be all numeric and labels must be shorter than 64 characters. */
isdnsname &= !all_numeric && !(label_length == MAX_LABEL_LENGTH);
return isdnsname;
}
#endif /* OPENSSL_NO_SOCK */
diff --git a/apps/speed.c b/apps/speed.c
index 506737d05fc6..8d4b1695d851 100644
--- a/apps/speed.c
+++ b/apps/speed.c
@@ -1,3691 +1,3718 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#undef SECONDS
#define SECONDS 3
#define RSA_SECONDS 10
#define DSA_SECONDS 10
#define ECDSA_SECONDS 10
#define ECDH_SECONDS 10
#define EdDSA_SECONDS 10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "apps.h"
#include "progs.h"
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/async.h>
#if !defined(OPENSSL_SYS_MSDOS)
# include OPENSSL_UNISTD
#endif
#if defined(_WIN32)
# include <windows.h>
#endif
#include <openssl/bn.h>
#ifndef OPENSSL_NO_DES
# include <openssl/des.h>
#endif
#include <openssl/aes.h>
#ifndef OPENSSL_NO_CAMELLIA
# include <openssl/camellia.h>
#endif
#ifndef OPENSSL_NO_MD2
# include <openssl/md2.h>
#endif
#ifndef OPENSSL_NO_MDC2
# include <openssl/mdc2.h>
#endif
#ifndef OPENSSL_NO_MD4
# include <openssl/md4.h>
#endif
#ifndef OPENSSL_NO_MD5
# include <openssl/md5.h>
#endif
#include <openssl/hmac.h>
#include <openssl/sha.h>
#ifndef OPENSSL_NO_RMD160
# include <openssl/ripemd.h>
#endif
#ifndef OPENSSL_NO_WHIRLPOOL
# include <openssl/whrlpool.h>
#endif
#ifndef OPENSSL_NO_RC4
# include <openssl/rc4.h>
#endif
#ifndef OPENSSL_NO_RC5
# include <openssl/rc5.h>
#endif
#ifndef OPENSSL_NO_RC2
# include <openssl/rc2.h>
#endif
#ifndef OPENSSL_NO_IDEA
# include <openssl/idea.h>
#endif
#ifndef OPENSSL_NO_SEED
# include <openssl/seed.h>
#endif
#ifndef OPENSSL_NO_BF
# include <openssl/blowfish.h>
#endif
#ifndef OPENSSL_NO_CAST
# include <openssl/cast.h>
#endif
#ifndef OPENSSL_NO_RSA
# include <openssl/rsa.h>
# include "./testrsa.h"
#endif
#include <openssl/x509.h>
#ifndef OPENSSL_NO_DSA
# include <openssl/dsa.h>
# include "./testdsa.h"
#endif
#ifndef OPENSSL_NO_EC
# include <openssl/ec.h>
#endif
#include <openssl/modes.h>
#ifndef HAVE_FORK
# if defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_VXWORKS)
# define HAVE_FORK 0
# else
# define HAVE_FORK 1
# endif
#endif
#if HAVE_FORK
# undef NO_FORK
#else
# define NO_FORK
#endif
#define MAX_MISALIGNMENT 63
#define MAX_ECDH_SIZE 256
#define MISALIGN 64
typedef struct openssl_speed_sec_st {
int sym;
int rsa;
int dsa;
int ecdsa;
int ecdh;
int eddsa;
} openssl_speed_sec_t;
static volatile int run = 0;
static int mr = 0;
static int usertime = 1;
#ifndef OPENSSL_NO_MD2
static int EVP_Digest_MD2_loop(void *args);
#endif
#ifndef OPENSSL_NO_MDC2
static int EVP_Digest_MDC2_loop(void *args);
#endif
#ifndef OPENSSL_NO_MD4
static int EVP_Digest_MD4_loop(void *args);
#endif
#ifndef OPENSSL_NO_MD5
static int MD5_loop(void *args);
static int HMAC_loop(void *args);
#endif
static int SHA1_loop(void *args);
static int SHA256_loop(void *args);
static int SHA512_loop(void *args);
#ifndef OPENSSL_NO_WHIRLPOOL
static int WHIRLPOOL_loop(void *args);
#endif
#ifndef OPENSSL_NO_RMD160
static int EVP_Digest_RMD160_loop(void *args);
#endif
#ifndef OPENSSL_NO_RC4
static int RC4_loop(void *args);
#endif
#ifndef OPENSSL_NO_DES
static int DES_ncbc_encrypt_loop(void *args);
static int DES_ede3_cbc_encrypt_loop(void *args);
#endif
static int AES_cbc_128_encrypt_loop(void *args);
static int AES_cbc_192_encrypt_loop(void *args);
static int AES_ige_128_encrypt_loop(void *args);
static int AES_cbc_256_encrypt_loop(void *args);
static int AES_ige_192_encrypt_loop(void *args);
static int AES_ige_256_encrypt_loop(void *args);
static int CRYPTO_gcm128_aad_loop(void *args);
static int RAND_bytes_loop(void *args);
static int EVP_Update_loop(void *args);
static int EVP_Update_loop_ccm(void *args);
static int EVP_Update_loop_aead(void *args);
static int EVP_Digest_loop(void *args);
#ifndef OPENSSL_NO_RSA
static int RSA_sign_loop(void *args);
static int RSA_verify_loop(void *args);
#endif
#ifndef OPENSSL_NO_DSA
static int DSA_sign_loop(void *args);
static int DSA_verify_loop(void *args);
#endif
#ifndef OPENSSL_NO_EC
static int ECDSA_sign_loop(void *args);
static int ECDSA_verify_loop(void *args);
static int EdDSA_sign_loop(void *args);
static int EdDSA_verify_loop(void *args);
#endif
static double Time_F(int s);
static void print_message(const char *s, long num, int length, int tm);
static void pkey_print_message(const char *str, const char *str2,
long num, unsigned int bits, int sec);
static void print_result(int alg, int run_no, int count, double time_used);
#ifndef NO_FORK
static int do_multi(int multi, int size_num);
#endif
static const int lengths_list[] = {
16, 64, 256, 1024, 8 * 1024, 16 * 1024
};
static const int *lengths = lengths_list;
static const int aead_lengths_list[] = {
2, 31, 136, 1024, 8 * 1024, 16 * 1024
};
#define START 0
#define STOP 1
#ifdef SIGALRM
static void alarmed(int sig)
{
signal(SIGALRM, alarmed);
run = 0;
}
static double Time_F(int s)
{
double ret = app_tminterval(s, usertime);
if (s == STOP)
alarm(0);
return ret;
}
#elif defined(_WIN32)
# define SIGALRM -1
static unsigned int lapse;
static volatile unsigned int schlock;
static void alarm_win32(unsigned int secs)
{
lapse = secs * 1000;
}
# define alarm alarm_win32
static DWORD WINAPI sleepy(VOID * arg)
{
schlock = 1;
Sleep(lapse);
run = 0;
return 0;
}
static double Time_F(int s)
{
double ret;
static HANDLE thr;
if (s == START) {
schlock = 0;
thr = CreateThread(NULL, 4096, sleepy, NULL, 0, NULL);
if (thr == NULL) {
DWORD err = GetLastError();
BIO_printf(bio_err, "unable to CreateThread (%lu)", err);
ExitProcess(err);
}
while (!schlock)
Sleep(0); /* scheduler spinlock */
ret = app_tminterval(s, usertime);
} else {
ret = app_tminterval(s, usertime);
if (run)
TerminateThread(thr, 0);
CloseHandle(thr);
}
return ret;
}
#else
static double Time_F(int s)
{
return app_tminterval(s, usertime);
}
#endif
static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
const openssl_speed_sec_t *seconds);
#define found(value, pairs, result)\
opt_found(value, result, pairs, OSSL_NELEM(pairs))
static int opt_found(const char *name, unsigned int *result,
const OPT_PAIR pairs[], unsigned int nbelem)
{
unsigned int idx;
for (idx = 0; idx < nbelem; ++idx, pairs++)
if (strcmp(name, pairs->name) == 0) {
*result = pairs->retval;
return 1;
}
return 0;
}
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_ELAPSED, OPT_EVP, OPT_DECRYPT, OPT_ENGINE, OPT_MULTI,
OPT_MR, OPT_MB, OPT_MISALIGN, OPT_ASYNCJOBS, OPT_R_ENUM,
OPT_PRIMES, OPT_SECONDS, OPT_BYTES, OPT_AEAD
} OPTION_CHOICE;
const OPTIONS speed_options[] = {
{OPT_HELP_STR, 1, '-', "Usage: %s [options] ciphers...\n"},
{OPT_HELP_STR, 1, '-', "Valid options are:\n"},
{"help", OPT_HELP, '-', "Display this summary"},
{"evp", OPT_EVP, 's', "Use EVP-named cipher or digest"},
{"decrypt", OPT_DECRYPT, '-',
"Time decryption instead of encryption (only EVP)"},
{"aead", OPT_AEAD, '-',
"Benchmark EVP-named AEAD cipher in TLS-like sequence"},
{"mb", OPT_MB, '-',
"Enable (tls1>=1) multi-block mode on EVP-named cipher"},
{"mr", OPT_MR, '-', "Produce machine readable output"},
#ifndef NO_FORK
{"multi", OPT_MULTI, 'p', "Run benchmarks in parallel"},
#endif
#ifndef OPENSSL_NO_ASYNC
{"async_jobs", OPT_ASYNCJOBS, 'p',
"Enable async mode and start specified number of jobs"},
#endif
OPT_R_OPTIONS,
#ifndef OPENSSL_NO_ENGINE
{"engine", OPT_ENGINE, 's', "Use engine, possibly a hardware device"},
#endif
{"elapsed", OPT_ELAPSED, '-',
"Use wall-clock time instead of CPU user time as divisor"},
{"primes", OPT_PRIMES, 'p', "Specify number of primes (for RSA only)"},
{"seconds", OPT_SECONDS, 'p',
"Run benchmarks for specified amount of seconds"},
{"bytes", OPT_BYTES, 'p',
"Run [non-PKI] benchmarks on custom-sized buffer"},
{"misalign", OPT_MISALIGN, 'p',
"Use specified offset to mis-align buffers"},
{NULL}
};
#define D_MD2 0
#define D_MDC2 1
#define D_MD4 2
#define D_MD5 3
#define D_HMAC 4
#define D_SHA1 5
#define D_RMD160 6
#define D_RC4 7
#define D_CBC_DES 8
#define D_EDE3_DES 9
#define D_CBC_IDEA 10
#define D_CBC_SEED 11
#define D_CBC_RC2 12
#define D_CBC_RC5 13
#define D_CBC_BF 14
#define D_CBC_CAST 15
#define D_CBC_128_AES 16
#define D_CBC_192_AES 17
#define D_CBC_256_AES 18
#define D_CBC_128_CML 19
#define D_CBC_192_CML 20
#define D_CBC_256_CML 21
#define D_EVP 22
#define D_SHA256 23
#define D_SHA512 24
#define D_WHIRLPOOL 25
#define D_IGE_128_AES 26
#define D_IGE_192_AES 27
#define D_IGE_256_AES 28
#define D_GHASH 29
#define D_RAND 30
/* name of algorithms to test */
static const char *names[] = {
"md2", "mdc2", "md4", "md5", "hmac(md5)", "sha1", "rmd160", "rc4",
"des cbc", "des ede3", "idea cbc", "seed cbc",
"rc2 cbc", "rc5-32/12 cbc", "blowfish cbc", "cast cbc",
"aes-128 cbc", "aes-192 cbc", "aes-256 cbc",
"camellia-128 cbc", "camellia-192 cbc", "camellia-256 cbc",
"evp", "sha256", "sha512", "whirlpool",
"aes-128 ige", "aes-192 ige", "aes-256 ige", "ghash",
"rand"
};
#define ALGOR_NUM OSSL_NELEM(names)
/* list of configured algorithm (remaining) */
static const OPT_PAIR doit_choices[] = {
#ifndef OPENSSL_NO_MD2
{"md2", D_MD2},
#endif
#ifndef OPENSSL_NO_MDC2
{"mdc2", D_MDC2},
#endif
#ifndef OPENSSL_NO_MD4
{"md4", D_MD4},
#endif
#ifndef OPENSSL_NO_MD5
{"md5", D_MD5},
{"hmac", D_HMAC},
#endif
{"sha1", D_SHA1},
{"sha256", D_SHA256},
{"sha512", D_SHA512},
#ifndef OPENSSL_NO_WHIRLPOOL
{"whirlpool", D_WHIRLPOOL},
#endif
#ifndef OPENSSL_NO_RMD160
{"ripemd", D_RMD160},
{"rmd160", D_RMD160},
{"ripemd160", D_RMD160},
#endif
#ifndef OPENSSL_NO_RC4
{"rc4", D_RC4},
#endif
#ifndef OPENSSL_NO_DES
{"des-cbc", D_CBC_DES},
{"des-ede3", D_EDE3_DES},
#endif
{"aes-128-cbc", D_CBC_128_AES},
{"aes-192-cbc", D_CBC_192_AES},
{"aes-256-cbc", D_CBC_256_AES},
{"aes-128-ige", D_IGE_128_AES},
{"aes-192-ige", D_IGE_192_AES},
{"aes-256-ige", D_IGE_256_AES},
#ifndef OPENSSL_NO_RC2
{"rc2-cbc", D_CBC_RC2},
{"rc2", D_CBC_RC2},
#endif
#ifndef OPENSSL_NO_RC5
{"rc5-cbc", D_CBC_RC5},
{"rc5", D_CBC_RC5},
#endif
#ifndef OPENSSL_NO_IDEA
{"idea-cbc", D_CBC_IDEA},
{"idea", D_CBC_IDEA},
#endif
#ifndef OPENSSL_NO_SEED
{"seed-cbc", D_CBC_SEED},
{"seed", D_CBC_SEED},
#endif
#ifndef OPENSSL_NO_BF
{"bf-cbc", D_CBC_BF},
{"blowfish", D_CBC_BF},
{"bf", D_CBC_BF},
#endif
#ifndef OPENSSL_NO_CAST
{"cast-cbc", D_CBC_CAST},
{"cast", D_CBC_CAST},
{"cast5", D_CBC_CAST},
#endif
{"ghash", D_GHASH},
{"rand", D_RAND}
};
static double results[ALGOR_NUM][OSSL_NELEM(lengths_list)];
#ifndef OPENSSL_NO_DSA
# define R_DSA_512 0
# define R_DSA_1024 1
# define R_DSA_2048 2
static const OPT_PAIR dsa_choices[] = {
{"dsa512", R_DSA_512},
{"dsa1024", R_DSA_1024},
{"dsa2048", R_DSA_2048}
};
# define DSA_NUM OSSL_NELEM(dsa_choices)
static double dsa_results[DSA_NUM][2]; /* 2 ops: sign then verify */
#endif /* OPENSSL_NO_DSA */
#define R_RSA_512 0
#define R_RSA_1024 1
#define R_RSA_2048 2
#define R_RSA_3072 3
#define R_RSA_4096 4
#define R_RSA_7680 5
#define R_RSA_15360 6
#ifndef OPENSSL_NO_RSA
static const OPT_PAIR rsa_choices[] = {
{"rsa512", R_RSA_512},
{"rsa1024", R_RSA_1024},
{"rsa2048", R_RSA_2048},
{"rsa3072", R_RSA_3072},
{"rsa4096", R_RSA_4096},
{"rsa7680", R_RSA_7680},
{"rsa15360", R_RSA_15360}
};
# define RSA_NUM OSSL_NELEM(rsa_choices)
static double rsa_results[RSA_NUM][2]; /* 2 ops: sign then verify */
#endif /* OPENSSL_NO_RSA */
-#define R_EC_P160 0
-#define R_EC_P192 1
-#define R_EC_P224 2
-#define R_EC_P256 3
-#define R_EC_P384 4
-#define R_EC_P521 5
-#define R_EC_K163 6
-#define R_EC_K233 7
-#define R_EC_K283 8
-#define R_EC_K409 9
-#define R_EC_K571 10
-#define R_EC_B163 11
-#define R_EC_B233 12
-#define R_EC_B283 13
-#define R_EC_B409 14
-#define R_EC_B571 15
-#define R_EC_BRP256R1 16
-#define R_EC_BRP256T1 17
-#define R_EC_BRP384R1 18
-#define R_EC_BRP384T1 19
-#define R_EC_BRP512R1 20
-#define R_EC_BRP512T1 21
-#define R_EC_X25519 22
-#define R_EC_X448 23
+enum {
+ R_EC_P160,
+ R_EC_P192,
+ R_EC_P224,
+ R_EC_P256,
+ R_EC_P384,
+ R_EC_P521,
+#ifndef OPENSSL_NO_EC2M
+ R_EC_K163,
+ R_EC_K233,
+ R_EC_K283,
+ R_EC_K409,
+ R_EC_K571,
+ R_EC_B163,
+ R_EC_B233,
+ R_EC_B283,
+ R_EC_B409,
+ R_EC_B571,
+#endif
+ R_EC_BRP256R1,
+ R_EC_BRP256T1,
+ R_EC_BRP384R1,
+ R_EC_BRP384T1,
+ R_EC_BRP512R1,
+ R_EC_BRP512T1,
+ R_EC_X25519,
+ R_EC_X448
+};
+
#ifndef OPENSSL_NO_EC
static OPT_PAIR ecdsa_choices[] = {
{"ecdsap160", R_EC_P160},
{"ecdsap192", R_EC_P192},
{"ecdsap224", R_EC_P224},
{"ecdsap256", R_EC_P256},
{"ecdsap384", R_EC_P384},
{"ecdsap521", R_EC_P521},
+# ifndef OPENSSL_NO_EC2M
{"ecdsak163", R_EC_K163},
{"ecdsak233", R_EC_K233},
{"ecdsak283", R_EC_K283},
{"ecdsak409", R_EC_K409},
{"ecdsak571", R_EC_K571},
{"ecdsab163", R_EC_B163},
{"ecdsab233", R_EC_B233},
{"ecdsab283", R_EC_B283},
{"ecdsab409", R_EC_B409},
{"ecdsab571", R_EC_B571},
+# endif
{"ecdsabrp256r1", R_EC_BRP256R1},
{"ecdsabrp256t1", R_EC_BRP256T1},
{"ecdsabrp384r1", R_EC_BRP384R1},
{"ecdsabrp384t1", R_EC_BRP384T1},
{"ecdsabrp512r1", R_EC_BRP512R1},
{"ecdsabrp512t1", R_EC_BRP512T1}
};
# define ECDSA_NUM OSSL_NELEM(ecdsa_choices)
static double ecdsa_results[ECDSA_NUM][2]; /* 2 ops: sign then verify */
static const OPT_PAIR ecdh_choices[] = {
{"ecdhp160", R_EC_P160},
{"ecdhp192", R_EC_P192},
{"ecdhp224", R_EC_P224},
{"ecdhp256", R_EC_P256},
{"ecdhp384", R_EC_P384},
{"ecdhp521", R_EC_P521},
+# ifndef OPENSSL_NO_EC2M
{"ecdhk163", R_EC_K163},
{"ecdhk233", R_EC_K233},
{"ecdhk283", R_EC_K283},
{"ecdhk409", R_EC_K409},
{"ecdhk571", R_EC_K571},
{"ecdhb163", R_EC_B163},
{"ecdhb233", R_EC_B233},
{"ecdhb283", R_EC_B283},
{"ecdhb409", R_EC_B409},
{"ecdhb571", R_EC_B571},
+# endif
{"ecdhbrp256r1", R_EC_BRP256R1},
{"ecdhbrp256t1", R_EC_BRP256T1},
{"ecdhbrp384r1", R_EC_BRP384R1},
{"ecdhbrp384t1", R_EC_BRP384T1},
{"ecdhbrp512r1", R_EC_BRP512R1},
{"ecdhbrp512t1", R_EC_BRP512T1},
{"ecdhx25519", R_EC_X25519},
{"ecdhx448", R_EC_X448}
};
# define EC_NUM OSSL_NELEM(ecdh_choices)
static double ecdh_results[EC_NUM][1]; /* 1 op: derivation */
#define R_EC_Ed25519 0
#define R_EC_Ed448 1
static OPT_PAIR eddsa_choices[] = {
{"ed25519", R_EC_Ed25519},
{"ed448", R_EC_Ed448}
};
# define EdDSA_NUM OSSL_NELEM(eddsa_choices)
static double eddsa_results[EdDSA_NUM][2]; /* 2 ops: sign then verify */
#endif /* OPENSSL_NO_EC */
#ifndef SIGALRM
# define COND(d) (count < (d))
# define COUNT(d) (d)
#else
# define COND(unused_cond) (run && count<0x7fffffff)
# define COUNT(d) (count)
#endif /* SIGALRM */
typedef struct loopargs_st {
ASYNC_JOB *inprogress_job;
ASYNC_WAIT_CTX *wait_ctx;
unsigned char *buf;
unsigned char *buf2;
unsigned char *buf_malloc;
unsigned char *buf2_malloc;
unsigned char *key;
unsigned int siglen;
size_t sigsize;
#ifndef OPENSSL_NO_RSA
RSA *rsa_key[RSA_NUM];
#endif
#ifndef OPENSSL_NO_DSA
DSA *dsa_key[DSA_NUM];
#endif
#ifndef OPENSSL_NO_EC
EC_KEY *ecdsa[ECDSA_NUM];
EVP_PKEY_CTX *ecdh_ctx[EC_NUM];
EVP_MD_CTX *eddsa_ctx[EdDSA_NUM];
unsigned char *secret_a;
unsigned char *secret_b;
size_t outlen[EC_NUM];
#endif
EVP_CIPHER_CTX *ctx;
HMAC_CTX *hctx;
GCM128_CONTEXT *gcm_ctx;
} loopargs_t;
static int run_benchmark(int async_jobs, int (*loop_function) (void *),
loopargs_t * loopargs);
static unsigned int testnum;
/* Nb of iterations to do per algorithm and key-size */
static long c[ALGOR_NUM][OSSL_NELEM(lengths_list)];
#ifndef OPENSSL_NO_MD2
static int EVP_Digest_MD2_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char md2[MD2_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_MD2][testnum]); count++) {
if (!EVP_Digest(buf, (size_t)lengths[testnum], md2, NULL, EVP_md2(),
NULL))
return -1;
}
return count;
}
#endif
#ifndef OPENSSL_NO_MDC2
static int EVP_Digest_MDC2_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char mdc2[MDC2_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_MDC2][testnum]); count++) {
if (!EVP_Digest(buf, (size_t)lengths[testnum], mdc2, NULL, EVP_mdc2(),
NULL))
return -1;
}
return count;
}
#endif
#ifndef OPENSSL_NO_MD4
static int EVP_Digest_MD4_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char md4[MD4_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_MD4][testnum]); count++) {
if (!EVP_Digest(buf, (size_t)lengths[testnum], md4, NULL, EVP_md4(),
NULL))
return -1;
}
return count;
}
#endif
#ifndef OPENSSL_NO_MD5
static int MD5_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char md5[MD5_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_MD5][testnum]); count++)
MD5(buf, lengths[testnum], md5);
return count;
}
static int HMAC_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
HMAC_CTX *hctx = tempargs->hctx;
unsigned char hmac[MD5_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_HMAC][testnum]); count++) {
HMAC_Init_ex(hctx, NULL, 0, NULL, NULL);
HMAC_Update(hctx, buf, lengths[testnum]);
HMAC_Final(hctx, hmac, NULL);
}
return count;
}
#endif
static int SHA1_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char sha[SHA_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_SHA1][testnum]); count++)
SHA1(buf, lengths[testnum], sha);
return count;
}
static int SHA256_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char sha256[SHA256_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_SHA256][testnum]); count++)
SHA256(buf, lengths[testnum], sha256);
return count;
}
static int SHA512_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char sha512[SHA512_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_SHA512][testnum]); count++)
SHA512(buf, lengths[testnum], sha512);
return count;
}
#ifndef OPENSSL_NO_WHIRLPOOL
static int WHIRLPOOL_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char whirlpool[WHIRLPOOL_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_WHIRLPOOL][testnum]); count++)
WHIRLPOOL(buf, lengths[testnum], whirlpool);
return count;
}
#endif
#ifndef OPENSSL_NO_RMD160
static int EVP_Digest_RMD160_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char rmd160[RIPEMD160_DIGEST_LENGTH];
int count;
for (count = 0; COND(c[D_RMD160][testnum]); count++) {
if (!EVP_Digest(buf, (size_t)lengths[testnum], &(rmd160[0]),
NULL, EVP_ripemd160(), NULL))
return -1;
}
return count;
}
#endif
#ifndef OPENSSL_NO_RC4
static RC4_KEY rc4_ks;
static int RC4_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
int count;
for (count = 0; COND(c[D_RC4][testnum]); count++)
RC4(&rc4_ks, (size_t)lengths[testnum], buf, buf);
return count;
}
#endif
#ifndef OPENSSL_NO_DES
static unsigned char DES_iv[8];
static DES_key_schedule sch;
static DES_key_schedule sch2;
static DES_key_schedule sch3;
static int DES_ncbc_encrypt_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
int count;
for (count = 0; COND(c[D_CBC_DES][testnum]); count++)
DES_ncbc_encrypt(buf, buf, lengths[testnum], &sch,
&DES_iv, DES_ENCRYPT);
return count;
}
static int DES_ede3_cbc_encrypt_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
int count;
for (count = 0; COND(c[D_EDE3_DES][testnum]); count++)
DES_ede3_cbc_encrypt(buf, buf, lengths[testnum],
&sch, &sch2, &sch3, &DES_iv, DES_ENCRYPT);
return count;
}
#endif
#define MAX_BLOCK_SIZE 128
static unsigned char iv[2 * MAX_BLOCK_SIZE / 8];
static AES_KEY aes_ks1, aes_ks2, aes_ks3;
static int AES_cbc_128_encrypt_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
int count;
for (count = 0; COND(c[D_CBC_128_AES][testnum]); count++)
AES_cbc_encrypt(buf, buf,
(size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT);
return count;
}
static int AES_cbc_192_encrypt_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
int count;
for (count = 0; COND(c[D_CBC_192_AES][testnum]); count++)
AES_cbc_encrypt(buf, buf,
(size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT);
return count;
}
static int AES_cbc_256_encrypt_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
int count;
for (count = 0; COND(c[D_CBC_256_AES][testnum]); count++)
AES_cbc_encrypt(buf, buf,
(size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT);
return count;
}
static int AES_ige_128_encrypt_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
int count;
for (count = 0; COND(c[D_IGE_128_AES][testnum]); count++)
AES_ige_encrypt(buf, buf2,
(size_t)lengths[testnum], &aes_ks1, iv, AES_ENCRYPT);
return count;
}
static int AES_ige_192_encrypt_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
int count;
for (count = 0; COND(c[D_IGE_192_AES][testnum]); count++)
AES_ige_encrypt(buf, buf2,
(size_t)lengths[testnum], &aes_ks2, iv, AES_ENCRYPT);
return count;
}
static int AES_ige_256_encrypt_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
int count;
for (count = 0; COND(c[D_IGE_256_AES][testnum]); count++)
AES_ige_encrypt(buf, buf2,
(size_t)lengths[testnum], &aes_ks3, iv, AES_ENCRYPT);
return count;
}
static int CRYPTO_gcm128_aad_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
GCM128_CONTEXT *gcm_ctx = tempargs->gcm_ctx;
int count;
for (count = 0; COND(c[D_GHASH][testnum]); count++)
CRYPTO_gcm128_aad(gcm_ctx, buf, lengths[testnum]);
return count;
}
static int RAND_bytes_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
int count;
for (count = 0; COND(c[D_RAND][testnum]); count++)
RAND_bytes(buf, lengths[testnum]);
return count;
}
static long save_count = 0;
static int decrypt = 0;
static int EVP_Update_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_CIPHER_CTX *ctx = tempargs->ctx;
int outl, count, rc;
#ifndef SIGALRM
int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
#endif
if (decrypt) {
for (count = 0; COND(nb_iter); count++) {
rc = EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
if (rc != 1) {
/* reset iv in case of counter overflow */
EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1);
}
}
} else {
for (count = 0; COND(nb_iter); count++) {
rc = EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
if (rc != 1) {
/* reset iv in case of counter overflow */
EVP_CipherInit_ex(ctx, NULL, NULL, NULL, iv, -1);
}
}
}
if (decrypt)
EVP_DecryptFinal_ex(ctx, buf, &outl);
else
EVP_EncryptFinal_ex(ctx, buf, &outl);
return count;
}
/*
* CCM does not support streaming. For the purpose of performance measurement,
* each message is encrypted using the same (key,iv)-pair. Do not use this
* code in your application.
*/
static int EVP_Update_loop_ccm(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_CIPHER_CTX *ctx = tempargs->ctx;
int outl, count;
unsigned char tag[12];
#ifndef SIGALRM
int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
#endif
if (decrypt) {
for (count = 0; COND(nb_iter); count++) {
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, sizeof(tag), tag);
/* reset iv */
EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
/* counter is reset on every update */
EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
}
} else {
for (count = 0; COND(nb_iter); count++) {
/* restore iv length field */
EVP_EncryptUpdate(ctx, NULL, &outl, NULL, lengths[testnum]);
/* counter is reset on every update */
EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
}
}
if (decrypt)
EVP_DecryptFinal_ex(ctx, buf, &outl);
else
EVP_EncryptFinal_ex(ctx, buf, &outl);
return count;
}
/*
* To make AEAD benchmarking more relevant perform TLS-like operations,
* 13-byte AAD followed by payload. But don't use TLS-formatted AAD, as
* payload length is not actually limited by 16KB...
*/
static int EVP_Update_loop_aead(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_CIPHER_CTX *ctx = tempargs->ctx;
int outl, count;
unsigned char aad[13] = { 0xcc };
unsigned char faketag[16] = { 0xcc };
#ifndef SIGALRM
int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
#endif
if (decrypt) {
for (count = 0; COND(nb_iter); count++) {
EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
sizeof(faketag), faketag);
EVP_DecryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
EVP_DecryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
EVP_DecryptFinal_ex(ctx, buf + outl, &outl);
}
} else {
for (count = 0; COND(nb_iter); count++) {
EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv);
EVP_EncryptUpdate(ctx, NULL, &outl, aad, sizeof(aad));
EVP_EncryptUpdate(ctx, buf, &outl, buf, lengths[testnum]);
EVP_EncryptFinal_ex(ctx, buf + outl, &outl);
}
}
return count;
}
static const EVP_MD *evp_md = NULL;
static int EVP_Digest_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char md[EVP_MAX_MD_SIZE];
int count;
#ifndef SIGALRM
int nb_iter = save_count * 4 * lengths[0] / lengths[testnum];
#endif
for (count = 0; COND(nb_iter); count++) {
if (!EVP_Digest(buf, lengths[testnum], md, NULL, evp_md, NULL))
return -1;
}
return count;
}
#ifndef OPENSSL_NO_RSA
static long rsa_c[RSA_NUM][2]; /* # RSA iteration test */
static int RSA_sign_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
unsigned int *rsa_num = &tempargs->siglen;
RSA **rsa_key = tempargs->rsa_key;
int ret, count;
for (count = 0; COND(rsa_c[testnum][0]); count++) {
ret = RSA_sign(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
if (ret == 0) {
BIO_printf(bio_err, "RSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
static int RSA_verify_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
unsigned int rsa_num = tempargs->siglen;
RSA **rsa_key = tempargs->rsa_key;
int ret, count;
for (count = 0; COND(rsa_c[testnum][1]); count++) {
ret =
RSA_verify(NID_md5_sha1, buf, 36, buf2, rsa_num, rsa_key[testnum]);
if (ret <= 0) {
BIO_printf(bio_err, "RSA verify failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
#endif
#ifndef OPENSSL_NO_DSA
static long dsa_c[DSA_NUM][2];
static int DSA_sign_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
DSA **dsa_key = tempargs->dsa_key;
unsigned int *siglen = &tempargs->siglen;
int ret, count;
for (count = 0; COND(dsa_c[testnum][0]); count++) {
ret = DSA_sign(0, buf, 20, buf2, siglen, dsa_key[testnum]);
if (ret == 0) {
BIO_printf(bio_err, "DSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
static int DSA_verify_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
unsigned char *buf2 = tempargs->buf2;
DSA **dsa_key = tempargs->dsa_key;
unsigned int siglen = tempargs->siglen;
int ret, count;
for (count = 0; COND(dsa_c[testnum][1]); count++) {
ret = DSA_verify(0, buf, 20, buf2, siglen, dsa_key[testnum]);
if (ret <= 0) {
BIO_printf(bio_err, "DSA verify failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
#endif
#ifndef OPENSSL_NO_EC
static long ecdsa_c[ECDSA_NUM][2];
static int ECDSA_sign_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EC_KEY **ecdsa = tempargs->ecdsa;
unsigned char *ecdsasig = tempargs->buf2;
unsigned int *ecdsasiglen = &tempargs->siglen;
int ret, count;
for (count = 0; COND(ecdsa_c[testnum][0]); count++) {
ret = ECDSA_sign(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]);
if (ret == 0) {
BIO_printf(bio_err, "ECDSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
static int ECDSA_verify_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EC_KEY **ecdsa = tempargs->ecdsa;
unsigned char *ecdsasig = tempargs->buf2;
unsigned int ecdsasiglen = tempargs->siglen;
int ret, count;
for (count = 0; COND(ecdsa_c[testnum][1]); count++) {
ret = ECDSA_verify(0, buf, 20, ecdsasig, ecdsasiglen, ecdsa[testnum]);
if (ret != 1) {
BIO_printf(bio_err, "ECDSA verify failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
/* ******************************************************************** */
static long ecdh_c[EC_NUM][1];
static int ECDH_EVP_derive_key_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
EVP_PKEY_CTX *ctx = tempargs->ecdh_ctx[testnum];
unsigned char *derived_secret = tempargs->secret_a;
int count;
size_t *outlen = &(tempargs->outlen[testnum]);
for (count = 0; COND(ecdh_c[testnum][0]); count++)
EVP_PKEY_derive(ctx, derived_secret, outlen);
return count;
}
static long eddsa_c[EdDSA_NUM][2];
static int EdDSA_sign_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_MD_CTX **edctx = tempargs->eddsa_ctx;
unsigned char *eddsasig = tempargs->buf2;
size_t *eddsasigsize = &tempargs->sigsize;
int ret, count;
for (count = 0; COND(eddsa_c[testnum][0]); count++) {
ret = EVP_DigestSign(edctx[testnum], eddsasig, eddsasigsize, buf, 20);
if (ret == 0) {
BIO_printf(bio_err, "EdDSA sign failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
static int EdDSA_verify_loop(void *args)
{
loopargs_t *tempargs = *(loopargs_t **) args;
unsigned char *buf = tempargs->buf;
EVP_MD_CTX **edctx = tempargs->eddsa_ctx;
unsigned char *eddsasig = tempargs->buf2;
size_t eddsasigsize = tempargs->sigsize;
int ret, count;
for (count = 0; COND(eddsa_c[testnum][1]); count++) {
ret = EVP_DigestVerify(edctx[testnum], eddsasig, eddsasigsize, buf, 20);
if (ret != 1) {
BIO_printf(bio_err, "EdDSA verify failure\n");
ERR_print_errors(bio_err);
count = -1;
break;
}
}
return count;
}
#endif /* OPENSSL_NO_EC */
static int run_benchmark(int async_jobs,
int (*loop_function) (void *), loopargs_t * loopargs)
{
int job_op_count = 0;
int total_op_count = 0;
int num_inprogress = 0;
int error = 0, i = 0, ret = 0;
OSSL_ASYNC_FD job_fd = 0;
size_t num_job_fds = 0;
run = 1;
if (async_jobs == 0) {
return loop_function((void *)&loopargs);
}
for (i = 0; i < async_jobs && !error; i++) {
loopargs_t *looparg_item = loopargs + i;
/* Copy pointer content (looparg_t item address) into async context */
ret = ASYNC_start_job(&loopargs[i].inprogress_job, loopargs[i].wait_ctx,
&job_op_count, loop_function,
(void *)&looparg_item, sizeof(looparg_item));
switch (ret) {
case ASYNC_PAUSE:
++num_inprogress;
break;
case ASYNC_FINISH:
if (job_op_count == -1) {
error = 1;
} else {
total_op_count += job_op_count;
}
break;
case ASYNC_NO_JOBS:
case ASYNC_ERR:
BIO_printf(bio_err, "Failure in the job\n");
ERR_print_errors(bio_err);
error = 1;
break;
}
}
while (num_inprogress > 0) {
#if defined(OPENSSL_SYS_WINDOWS)
DWORD avail = 0;
#elif defined(OPENSSL_SYS_UNIX)
int select_result = 0;
OSSL_ASYNC_FD max_fd = 0;
fd_set waitfdset;
FD_ZERO(&waitfdset);
for (i = 0; i < async_jobs && num_inprogress > 0; i++) {
if (loopargs[i].inprogress_job == NULL)
continue;
if (!ASYNC_WAIT_CTX_get_all_fds
(loopargs[i].wait_ctx, NULL, &num_job_fds)
|| num_job_fds > 1) {
BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n");
ERR_print_errors(bio_err);
error = 1;
break;
}
ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd,
&num_job_fds);
FD_SET(job_fd, &waitfdset);
if (job_fd > max_fd)
max_fd = job_fd;
}
if (max_fd >= (OSSL_ASYNC_FD)FD_SETSIZE) {
BIO_printf(bio_err,
"Error: max_fd (%d) must be smaller than FD_SETSIZE (%d). "
"Decrease the value of async_jobs\n",
max_fd, FD_SETSIZE);
ERR_print_errors(bio_err);
error = 1;
break;
}
select_result = select(max_fd + 1, &waitfdset, NULL, NULL, NULL);
if (select_result == -1 && errno == EINTR)
continue;
if (select_result == -1) {
BIO_printf(bio_err, "Failure in the select\n");
ERR_print_errors(bio_err);
error = 1;
break;
}
if (select_result == 0)
continue;
#endif
for (i = 0; i < async_jobs; i++) {
if (loopargs[i].inprogress_job == NULL)
continue;
if (!ASYNC_WAIT_CTX_get_all_fds
(loopargs[i].wait_ctx, NULL, &num_job_fds)
|| num_job_fds > 1) {
BIO_printf(bio_err, "Too many fds in ASYNC_WAIT_CTX\n");
ERR_print_errors(bio_err);
error = 1;
break;
}
ASYNC_WAIT_CTX_get_all_fds(loopargs[i].wait_ctx, &job_fd,
&num_job_fds);
#if defined(OPENSSL_SYS_UNIX)
if (num_job_fds == 1 && !FD_ISSET(job_fd, &waitfdset))
continue;
#elif defined(OPENSSL_SYS_WINDOWS)
if (num_job_fds == 1
&& !PeekNamedPipe(job_fd, NULL, 0, NULL, &avail, NULL)
&& avail > 0)
continue;
#endif
ret = ASYNC_start_job(&loopargs[i].inprogress_job,
loopargs[i].wait_ctx, &job_op_count,
loop_function, (void *)(loopargs + i),
sizeof(loopargs_t));
switch (ret) {
case ASYNC_PAUSE:
break;
case ASYNC_FINISH:
if (job_op_count == -1) {
error = 1;
} else {
total_op_count += job_op_count;
}
--num_inprogress;
loopargs[i].inprogress_job = NULL;
break;
case ASYNC_NO_JOBS:
case ASYNC_ERR:
--num_inprogress;
loopargs[i].inprogress_job = NULL;
BIO_printf(bio_err, "Failure in the job\n");
ERR_print_errors(bio_err);
error = 1;
break;
}
}
}
return error ? -1 : total_op_count;
}
int speed_main(int argc, char **argv)
{
ENGINE *e = NULL;
loopargs_t *loopargs = NULL;
const char *prog;
const char *engine_id = NULL;
const EVP_CIPHER *evp_cipher = NULL;
double d = 0.0;
OPTION_CHOICE o;
int async_init = 0, multiblock = 0, pr_header = 0;
int doit[ALGOR_NUM] = { 0 };
int ret = 1, misalign = 0, lengths_single = 0, aead = 0;
long count = 0;
unsigned int size_num = OSSL_NELEM(lengths_list);
unsigned int i, k, loop, loopargs_len = 0, async_jobs = 0;
int keylen;
int buflen;
#ifndef NO_FORK
int multi = 0;
#endif
#if !defined(OPENSSL_NO_RSA) || !defined(OPENSSL_NO_DSA) \
|| !defined(OPENSSL_NO_EC)
long rsa_count = 1;
#endif
openssl_speed_sec_t seconds = { SECONDS, RSA_SECONDS, DSA_SECONDS,
ECDSA_SECONDS, ECDH_SECONDS,
EdDSA_SECONDS };
/* What follows are the buffers and key material. */
#ifndef OPENSSL_NO_RC5
RC5_32_KEY rc5_ks;
#endif
#ifndef OPENSSL_NO_RC2
RC2_KEY rc2_ks;
#endif
#ifndef OPENSSL_NO_IDEA
IDEA_KEY_SCHEDULE idea_ks;
#endif
#ifndef OPENSSL_NO_SEED
SEED_KEY_SCHEDULE seed_ks;
#endif
#ifndef OPENSSL_NO_BF
BF_KEY bf_ks;
#endif
#ifndef OPENSSL_NO_CAST
CAST_KEY cast_ks;
#endif
static const unsigned char key16[16] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
};
static const unsigned char key24[24] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
};
static const unsigned char key32[32] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56
};
#ifndef OPENSSL_NO_CAMELLIA
static const unsigned char ckey24[24] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
};
static const unsigned char ckey32[32] = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0,
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12,
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34,
0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56
};
CAMELLIA_KEY camellia_ks1, camellia_ks2, camellia_ks3;
#endif
#ifndef OPENSSL_NO_DES
static DES_cblock key = {
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0
};
static DES_cblock key2 = {
0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12
};
static DES_cblock key3 = {
0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34
};
#endif
#ifndef OPENSSL_NO_RSA
static const unsigned int rsa_bits[RSA_NUM] = {
512, 1024, 2048, 3072, 4096, 7680, 15360
};
static const unsigned char *rsa_data[RSA_NUM] = {
test512, test1024, test2048, test3072, test4096, test7680, test15360
};
static const int rsa_data_length[RSA_NUM] = {
sizeof(test512), sizeof(test1024),
sizeof(test2048), sizeof(test3072),
sizeof(test4096), sizeof(test7680),
sizeof(test15360)
};
int rsa_doit[RSA_NUM] = { 0 };
int primes = RSA_DEFAULT_PRIME_NUM;
#endif
#ifndef OPENSSL_NO_DSA
static const unsigned int dsa_bits[DSA_NUM] = { 512, 1024, 2048 };
int dsa_doit[DSA_NUM] = { 0 };
#endif
#ifndef OPENSSL_NO_EC
/*
* We only test over the following curves as they are representative, To
* add tests over more curves, simply add the curve NID and curve name to
* the following arrays and increase the |ecdh_choices| list accordingly.
*/
static const struct {
const char *name;
unsigned int nid;
unsigned int bits;
} test_curves[] = {
/* Prime Curves */
{"secp160r1", NID_secp160r1, 160},
{"nistp192", NID_X9_62_prime192v1, 192},
{"nistp224", NID_secp224r1, 224},
{"nistp256", NID_X9_62_prime256v1, 256},
{"nistp384", NID_secp384r1, 384},
{"nistp521", NID_secp521r1, 521},
+# ifndef OPENSSL_NO_EC2M
/* Binary Curves */
{"nistk163", NID_sect163k1, 163},
{"nistk233", NID_sect233k1, 233},
{"nistk283", NID_sect283k1, 283},
{"nistk409", NID_sect409k1, 409},
{"nistk571", NID_sect571k1, 571},
{"nistb163", NID_sect163r2, 163},
{"nistb233", NID_sect233r1, 233},
{"nistb283", NID_sect283r1, 283},
{"nistb409", NID_sect409r1, 409},
{"nistb571", NID_sect571r1, 571},
+# endif
{"brainpoolP256r1", NID_brainpoolP256r1, 256},
{"brainpoolP256t1", NID_brainpoolP256t1, 256},
{"brainpoolP384r1", NID_brainpoolP384r1, 384},
{"brainpoolP384t1", NID_brainpoolP384t1, 384},
{"brainpoolP512r1", NID_brainpoolP512r1, 512},
{"brainpoolP512t1", NID_brainpoolP512t1, 512},
/* Other and ECDH only ones */
{"X25519", NID_X25519, 253},
{"X448", NID_X448, 448}
};
static const struct {
const char *name;
unsigned int nid;
unsigned int bits;
size_t sigsize;
} test_ed_curves[] = {
/* EdDSA */
{"Ed25519", NID_ED25519, 253, 64},
{"Ed448", NID_ED448, 456, 114}
};
int ecdsa_doit[ECDSA_NUM] = { 0 };
int ecdh_doit[EC_NUM] = { 0 };
int eddsa_doit[EdDSA_NUM] = { 0 };
OPENSSL_assert(OSSL_NELEM(test_curves) >= EC_NUM);
OPENSSL_assert(OSSL_NELEM(test_ed_curves) >= EdDSA_NUM);
#endif /* ndef OPENSSL_NO_EC */
prog = opt_init(argc, argv, speed_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opterr:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(speed_options);
ret = 0;
goto end;
case OPT_ELAPSED:
usertime = 0;
break;
case OPT_EVP:
evp_md = NULL;
evp_cipher = EVP_get_cipherbyname(opt_arg());
if (evp_cipher == NULL)
evp_md = EVP_get_digestbyname(opt_arg());
if (evp_cipher == NULL && evp_md == NULL) {
BIO_printf(bio_err,
"%s: %s is an unknown cipher or digest\n",
prog, opt_arg());
goto end;
}
doit[D_EVP] = 1;
break;
case OPT_DECRYPT:
decrypt = 1;
break;
case OPT_ENGINE:
/*
* In a forked execution, an engine might need to be
* initialised by each child process, not by the parent.
* So store the name here and run setup_engine() later on.
*/
engine_id = opt_arg();
break;
case OPT_MULTI:
#ifndef NO_FORK
multi = atoi(opt_arg());
#endif
break;
case OPT_ASYNCJOBS:
#ifndef OPENSSL_NO_ASYNC
async_jobs = atoi(opt_arg());
if (!ASYNC_is_capable()) {
BIO_printf(bio_err,
"%s: async_jobs specified but async not supported\n",
prog);
goto opterr;
}
if (async_jobs > 99999) {
BIO_printf(bio_err, "%s: too many async_jobs\n", prog);
goto opterr;
}
#endif
break;
case OPT_MISALIGN:
if (!opt_int(opt_arg(), &misalign))
goto end;
if (misalign > MISALIGN) {
BIO_printf(bio_err,
"%s: Maximum offset is %d\n", prog, MISALIGN);
goto opterr;
}
break;
case OPT_MR:
mr = 1;
break;
case OPT_MB:
multiblock = 1;
#ifdef OPENSSL_NO_MULTIBLOCK
BIO_printf(bio_err,
"%s: -mb specified but multi-block support is disabled\n",
prog);
goto end;
#endif
break;
case OPT_R_CASES:
if (!opt_rand(o))
goto end;
break;
case OPT_PRIMES:
if (!opt_int(opt_arg(), &primes))
goto end;
break;
case OPT_SECONDS:
seconds.sym = seconds.rsa = seconds.dsa = seconds.ecdsa
= seconds.ecdh = seconds.eddsa = atoi(opt_arg());
break;
case OPT_BYTES:
lengths_single = atoi(opt_arg());
lengths = &lengths_single;
size_num = 1;
break;
case OPT_AEAD:
aead = 1;
break;
}
}
argc = opt_num_rest();
argv = opt_rest();
/* Remaining arguments are algorithms. */
for (; *argv; argv++) {
if (found(*argv, doit_choices, &i)) {
doit[i] = 1;
continue;
}
#ifndef OPENSSL_NO_DES
if (strcmp(*argv, "des") == 0) {
doit[D_CBC_DES] = doit[D_EDE3_DES] = 1;
continue;
}
#endif
if (strcmp(*argv, "sha") == 0) {
doit[D_SHA1] = doit[D_SHA256] = doit[D_SHA512] = 1;
continue;
}
#ifndef OPENSSL_NO_RSA
if (strcmp(*argv, "openssl") == 0)
continue;
if (strcmp(*argv, "rsa") == 0) {
for (loop = 0; loop < OSSL_NELEM(rsa_doit); loop++)
rsa_doit[loop] = 1;
continue;
}
if (found(*argv, rsa_choices, &i)) {
rsa_doit[i] = 1;
continue;
}
#endif
#ifndef OPENSSL_NO_DSA
if (strcmp(*argv, "dsa") == 0) {
dsa_doit[R_DSA_512] = dsa_doit[R_DSA_1024] =
dsa_doit[R_DSA_2048] = 1;
continue;
}
if (found(*argv, dsa_choices, &i)) {
dsa_doit[i] = 2;
continue;
}
#endif
if (strcmp(*argv, "aes") == 0) {
doit[D_CBC_128_AES] = doit[D_CBC_192_AES] = doit[D_CBC_256_AES] = 1;
continue;
}
#ifndef OPENSSL_NO_CAMELLIA
if (strcmp(*argv, "camellia") == 0) {
doit[D_CBC_128_CML] = doit[D_CBC_192_CML] = doit[D_CBC_256_CML] = 1;
continue;
}
#endif
#ifndef OPENSSL_NO_EC
if (strcmp(*argv, "ecdsa") == 0) {
for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++)
ecdsa_doit[loop] = 1;
continue;
}
if (found(*argv, ecdsa_choices, &i)) {
ecdsa_doit[i] = 2;
continue;
}
if (strcmp(*argv, "ecdh") == 0) {
for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
ecdh_doit[loop] = 1;
continue;
}
if (found(*argv, ecdh_choices, &i)) {
ecdh_doit[i] = 2;
continue;
}
if (strcmp(*argv, "eddsa") == 0) {
for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
eddsa_doit[loop] = 1;
continue;
}
if (found(*argv, eddsa_choices, &i)) {
eddsa_doit[i] = 2;
continue;
}
#endif
BIO_printf(bio_err, "%s: Unknown algorithm %s\n", prog, *argv);
goto end;
}
/* Sanity checks */
if (aead) {
if (evp_cipher == NULL) {
BIO_printf(bio_err, "-aead can be used only with an AEAD cipher\n");
goto end;
} else if (!(EVP_CIPHER_flags(evp_cipher) &
EVP_CIPH_FLAG_AEAD_CIPHER)) {
BIO_printf(bio_err, "%s is not an AEAD cipher\n",
OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
goto end;
}
}
if (multiblock) {
if (evp_cipher == NULL) {
BIO_printf(bio_err,"-mb can be used only with a multi-block"
" capable cipher\n");
goto end;
} else if (!(EVP_CIPHER_flags(evp_cipher) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
BIO_printf(bio_err, "%s is not a multi-block capable\n",
OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher)));
goto end;
} else if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with -mb");
goto end;
}
}
/* Initialize the job pool if async mode is enabled */
if (async_jobs > 0) {
async_init = ASYNC_init_thread(async_jobs, async_jobs);
if (!async_init) {
BIO_printf(bio_err, "Error creating the ASYNC job pool\n");
goto end;
}
}
loopargs_len = (async_jobs == 0 ? 1 : async_jobs);
loopargs =
app_malloc(loopargs_len * sizeof(loopargs_t), "array of loopargs");
memset(loopargs, 0, loopargs_len * sizeof(loopargs_t));
for (i = 0; i < loopargs_len; i++) {
if (async_jobs > 0) {
loopargs[i].wait_ctx = ASYNC_WAIT_CTX_new();
if (loopargs[i].wait_ctx == NULL) {
BIO_printf(bio_err, "Error creating the ASYNC_WAIT_CTX\n");
goto end;
}
}
buflen = lengths[size_num - 1];
if (buflen < 36) /* size of random vector in RSA bencmark */
buflen = 36;
buflen += MAX_MISALIGNMENT + 1;
loopargs[i].buf_malloc = app_malloc(buflen, "input buffer");
loopargs[i].buf2_malloc = app_malloc(buflen, "input buffer");
memset(loopargs[i].buf_malloc, 0, buflen);
memset(loopargs[i].buf2_malloc, 0, buflen);
/* Align the start of buffers on a 64 byte boundary */
loopargs[i].buf = loopargs[i].buf_malloc + misalign;
loopargs[i].buf2 = loopargs[i].buf2_malloc + misalign;
#ifndef OPENSSL_NO_EC
loopargs[i].secret_a = app_malloc(MAX_ECDH_SIZE, "ECDH secret a");
loopargs[i].secret_b = app_malloc(MAX_ECDH_SIZE, "ECDH secret b");
#endif
}
#ifndef NO_FORK
if (multi && do_multi(multi, size_num))
goto show_res;
#endif
/* Initialize the engine after the fork */
e = setup_engine(engine_id, 0);
/* No parameters; turn on everything. */
if ((argc == 0) && !doit[D_EVP]) {
for (i = 0; i < ALGOR_NUM; i++)
if (i != D_EVP)
doit[i] = 1;
#ifndef OPENSSL_NO_RSA
for (i = 0; i < RSA_NUM; i++)
rsa_doit[i] = 1;
#endif
#ifndef OPENSSL_NO_DSA
for (i = 0; i < DSA_NUM; i++)
dsa_doit[i] = 1;
#endif
#ifndef OPENSSL_NO_EC
for (loop = 0; loop < OSSL_NELEM(ecdsa_doit); loop++)
ecdsa_doit[loop] = 1;
for (loop = 0; loop < OSSL_NELEM(ecdh_doit); loop++)
ecdh_doit[loop] = 1;
for (loop = 0; loop < OSSL_NELEM(eddsa_doit); loop++)
eddsa_doit[loop] = 1;
#endif
}
for (i = 0; i < ALGOR_NUM; i++)
if (doit[i])
pr_header++;
if (usertime == 0 && !mr)
BIO_printf(bio_err,
"You have chosen to measure elapsed time "
"instead of user CPU time.\n");
#ifndef OPENSSL_NO_RSA
for (i = 0; i < loopargs_len; i++) {
if (primes > RSA_DEFAULT_PRIME_NUM) {
/* for multi-prime RSA, skip this */
break;
}
for (k = 0; k < RSA_NUM; k++) {
const unsigned char *p;
p = rsa_data[k];
loopargs[i].rsa_key[k] =
d2i_RSAPrivateKey(NULL, &p, rsa_data_length[k]);
if (loopargs[i].rsa_key[k] == NULL) {
BIO_printf(bio_err,
"internal error loading RSA key number %d\n", k);
goto end;
}
}
}
#endif
#ifndef OPENSSL_NO_DSA
for (i = 0; i < loopargs_len; i++) {
loopargs[i].dsa_key[0] = get_dsa(512);
loopargs[i].dsa_key[1] = get_dsa(1024);
loopargs[i].dsa_key[2] = get_dsa(2048);
}
#endif
#ifndef OPENSSL_NO_DES
DES_set_key_unchecked(&key, &sch);
DES_set_key_unchecked(&key2, &sch2);
DES_set_key_unchecked(&key3, &sch3);
#endif
AES_set_encrypt_key(key16, 128, &aes_ks1);
AES_set_encrypt_key(key24, 192, &aes_ks2);
AES_set_encrypt_key(key32, 256, &aes_ks3);
#ifndef OPENSSL_NO_CAMELLIA
Camellia_set_key(key16, 128, &camellia_ks1);
Camellia_set_key(ckey24, 192, &camellia_ks2);
Camellia_set_key(ckey32, 256, &camellia_ks3);
#endif
#ifndef OPENSSL_NO_IDEA
IDEA_set_encrypt_key(key16, &idea_ks);
#endif
#ifndef OPENSSL_NO_SEED
SEED_set_key(key16, &seed_ks);
#endif
#ifndef OPENSSL_NO_RC4
RC4_set_key(&rc4_ks, 16, key16);
#endif
#ifndef OPENSSL_NO_RC2
RC2_set_key(&rc2_ks, 16, key16, 128);
#endif
#ifndef OPENSSL_NO_RC5
RC5_32_set_key(&rc5_ks, 16, key16, 12);
#endif
#ifndef OPENSSL_NO_BF
BF_set_key(&bf_ks, 16, key16);
#endif
#ifndef OPENSSL_NO_CAST
CAST_set_key(&cast_ks, 16, key16);
#endif
#ifndef SIGALRM
# ifndef OPENSSL_NO_DES
BIO_printf(bio_err, "First we calculate the approximate speed ...\n");
count = 10;
do {
long it;
count *= 2;
Time_F(START);
for (it = count; it; it--)
DES_ecb_encrypt((DES_cblock *)loopargs[0].buf,
(DES_cblock *)loopargs[0].buf, &sch, DES_ENCRYPT);
d = Time_F(STOP);
} while (d < 3);
save_count = count;
c[D_MD2][0] = count / 10;
c[D_MDC2][0] = count / 10;
c[D_MD4][0] = count;
c[D_MD5][0] = count;
c[D_HMAC][0] = count;
c[D_SHA1][0] = count;
c[D_RMD160][0] = count;
c[D_RC4][0] = count * 5;
c[D_CBC_DES][0] = count;
c[D_EDE3_DES][0] = count / 3;
c[D_CBC_IDEA][0] = count;
c[D_CBC_SEED][0] = count;
c[D_CBC_RC2][0] = count;
c[D_CBC_RC5][0] = count;
c[D_CBC_BF][0] = count;
c[D_CBC_CAST][0] = count;
c[D_CBC_128_AES][0] = count;
c[D_CBC_192_AES][0] = count;
c[D_CBC_256_AES][0] = count;
c[D_CBC_128_CML][0] = count;
c[D_CBC_192_CML][0] = count;
c[D_CBC_256_CML][0] = count;
c[D_SHA256][0] = count;
c[D_SHA512][0] = count;
c[D_WHIRLPOOL][0] = count;
c[D_IGE_128_AES][0] = count;
c[D_IGE_192_AES][0] = count;
c[D_IGE_256_AES][0] = count;
c[D_GHASH][0] = count;
c[D_RAND][0] = count;
for (i = 1; i < size_num; i++) {
long l0, l1;
l0 = (long)lengths[0];
l1 = (long)lengths[i];
c[D_MD2][i] = c[D_MD2][0] * 4 * l0 / l1;
c[D_MDC2][i] = c[D_MDC2][0] * 4 * l0 / l1;
c[D_MD4][i] = c[D_MD4][0] * 4 * l0 / l1;
c[D_MD5][i] = c[D_MD5][0] * 4 * l0 / l1;
c[D_HMAC][i] = c[D_HMAC][0] * 4 * l0 / l1;
c[D_SHA1][i] = c[D_SHA1][0] * 4 * l0 / l1;
c[D_RMD160][i] = c[D_RMD160][0] * 4 * l0 / l1;
c[D_SHA256][i] = c[D_SHA256][0] * 4 * l0 / l1;
c[D_SHA512][i] = c[D_SHA512][0] * 4 * l0 / l1;
c[D_WHIRLPOOL][i] = c[D_WHIRLPOOL][0] * 4 * l0 / l1;
c[D_GHASH][i] = c[D_GHASH][0] * 4 * l0 / l1;
c[D_RAND][i] = c[D_RAND][0] * 4 * l0 / l1;
l0 = (long)lengths[i - 1];
c[D_RC4][i] = c[D_RC4][i - 1] * l0 / l1;
c[D_CBC_DES][i] = c[D_CBC_DES][i - 1] * l0 / l1;
c[D_EDE3_DES][i] = c[D_EDE3_DES][i - 1] * l0 / l1;
c[D_CBC_IDEA][i] = c[D_CBC_IDEA][i - 1] * l0 / l1;
c[D_CBC_SEED][i] = c[D_CBC_SEED][i - 1] * l0 / l1;
c[D_CBC_RC2][i] = c[D_CBC_RC2][i - 1] * l0 / l1;
c[D_CBC_RC5][i] = c[D_CBC_RC5][i - 1] * l0 / l1;
c[D_CBC_BF][i] = c[D_CBC_BF][i - 1] * l0 / l1;
c[D_CBC_CAST][i] = c[D_CBC_CAST][i - 1] * l0 / l1;
c[D_CBC_128_AES][i] = c[D_CBC_128_AES][i - 1] * l0 / l1;
c[D_CBC_192_AES][i] = c[D_CBC_192_AES][i - 1] * l0 / l1;
c[D_CBC_256_AES][i] = c[D_CBC_256_AES][i - 1] * l0 / l1;
c[D_CBC_128_CML][i] = c[D_CBC_128_CML][i - 1] * l0 / l1;
c[D_CBC_192_CML][i] = c[D_CBC_192_CML][i - 1] * l0 / l1;
c[D_CBC_256_CML][i] = c[D_CBC_256_CML][i - 1] * l0 / l1;
c[D_IGE_128_AES][i] = c[D_IGE_128_AES][i - 1] * l0 / l1;
c[D_IGE_192_AES][i] = c[D_IGE_192_AES][i - 1] * l0 / l1;
c[D_IGE_256_AES][i] = c[D_IGE_256_AES][i - 1] * l0 / l1;
}
# ifndef OPENSSL_NO_RSA
rsa_c[R_RSA_512][0] = count / 2000;
rsa_c[R_RSA_512][1] = count / 400;
for (i = 1; i < RSA_NUM; i++) {
rsa_c[i][0] = rsa_c[i - 1][0] / 8;
rsa_c[i][1] = rsa_c[i - 1][1] / 4;
if (rsa_doit[i] <= 1 && rsa_c[i][0] == 0)
rsa_doit[i] = 0;
else {
if (rsa_c[i][0] == 0) {
rsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
rsa_c[i][1] = 20;
}
}
}
# endif
# ifndef OPENSSL_NO_DSA
dsa_c[R_DSA_512][0] = count / 1000;
dsa_c[R_DSA_512][1] = count / 1000 / 2;
for (i = 1; i < DSA_NUM; i++) {
dsa_c[i][0] = dsa_c[i - 1][0] / 4;
dsa_c[i][1] = dsa_c[i - 1][1] / 4;
if (dsa_doit[i] <= 1 && dsa_c[i][0] == 0)
dsa_doit[i] = 0;
else {
if (dsa_c[i][0] == 0) {
dsa_c[i][0] = 1; /* Set minimum iteration Nb to 1. */
dsa_c[i][1] = 1;
}
}
}
# endif
# ifndef OPENSSL_NO_EC
ecdsa_c[R_EC_P160][0] = count / 1000;
ecdsa_c[R_EC_P160][1] = count / 1000 / 2;
for (i = R_EC_P192; i <= R_EC_P521; i++) {
ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
ecdsa_doit[i] = 0;
else {
if (ecdsa_c[i][0] == 0) {
ecdsa_c[i][0] = 1;
ecdsa_c[i][1] = 1;
}
}
}
+# ifndef OPENSSL_NO_EC2M
ecdsa_c[R_EC_K163][0] = count / 1000;
ecdsa_c[R_EC_K163][1] = count / 1000 / 2;
for (i = R_EC_K233; i <= R_EC_K571; i++) {
ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
ecdsa_doit[i] = 0;
else {
if (ecdsa_c[i][0] == 0) {
ecdsa_c[i][0] = 1;
ecdsa_c[i][1] = 1;
}
}
}
ecdsa_c[R_EC_B163][0] = count / 1000;
ecdsa_c[R_EC_B163][1] = count / 1000 / 2;
for (i = R_EC_B233; i <= R_EC_B571; i++) {
ecdsa_c[i][0] = ecdsa_c[i - 1][0] / 2;
ecdsa_c[i][1] = ecdsa_c[i - 1][1] / 2;
if (ecdsa_doit[i] <= 1 && ecdsa_c[i][0] == 0)
ecdsa_doit[i] = 0;
else {
if (ecdsa_c[i][0] == 0) {
ecdsa_c[i][0] = 1;
ecdsa_c[i][1] = 1;
}
}
}
+# endif
ecdh_c[R_EC_P160][0] = count / 1000;
for (i = R_EC_P192; i <= R_EC_P521; i++) {
ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
ecdh_doit[i] = 0;
else {
if (ecdh_c[i][0] == 0) {
ecdh_c[i][0] = 1;
}
}
}
+# ifndef OPENSSL_NO_EC2M
ecdh_c[R_EC_K163][0] = count / 1000;
for (i = R_EC_K233; i <= R_EC_K571; i++) {
ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
ecdh_doit[i] = 0;
else {
if (ecdh_c[i][0] == 0) {
ecdh_c[i][0] = 1;
}
}
}
ecdh_c[R_EC_B163][0] = count / 1000;
for (i = R_EC_B233; i <= R_EC_B571; i++) {
ecdh_c[i][0] = ecdh_c[i - 1][0] / 2;
if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
ecdh_doit[i] = 0;
else {
if (ecdh_c[i][0] == 0) {
ecdh_c[i][0] = 1;
}
}
}
+# endif
/* repeated code good to factorize */
ecdh_c[R_EC_BRP256R1][0] = count / 1000;
for (i = R_EC_BRP384R1; i <= R_EC_BRP512R1; i += 2) {
ecdh_c[i][0] = ecdh_c[i - 2][0] / 2;
if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
ecdh_doit[i] = 0;
else {
if (ecdh_c[i][0] == 0) {
ecdh_c[i][0] = 1;
}
}
}
ecdh_c[R_EC_BRP256T1][0] = count / 1000;
for (i = R_EC_BRP384T1; i <= R_EC_BRP512T1; i += 2) {
ecdh_c[i][0] = ecdh_c[i - 2][0] / 2;
if (ecdh_doit[i] <= 1 && ecdh_c[i][0] == 0)
ecdh_doit[i] = 0;
else {
if (ecdh_c[i][0] == 0) {
ecdh_c[i][0] = 1;
}
}
}
/* default iteration count for the last two EC Curves */
ecdh_c[R_EC_X25519][0] = count / 1800;
ecdh_c[R_EC_X448][0] = count / 7200;
eddsa_c[R_EC_Ed25519][0] = count / 1800;
eddsa_c[R_EC_Ed448][0] = count / 7200;
# endif
# else
/* not worth fixing */
# error "You cannot disable DES on systems without SIGALRM."
# endif /* OPENSSL_NO_DES */
#elif SIGALRM > 0
signal(SIGALRM, alarmed);
#endif /* SIGALRM */
#ifndef OPENSSL_NO_MD2
if (doit[D_MD2]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD2], c[D_MD2][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, EVP_Digest_MD2_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD2, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_MDC2
if (doit[D_MDC2]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MDC2], c[D_MDC2][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, EVP_Digest_MDC2_loop, loopargs);
d = Time_F(STOP);
print_result(D_MDC2, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_MD4
if (doit[D_MD4]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD4], c[D_MD4][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, EVP_Digest_MD4_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD4, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_MD5
if (doit[D_MD5]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_MD5], c[D_MD5][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, MD5_loop, loopargs);
d = Time_F(STOP);
print_result(D_MD5, testnum, count, d);
}
}
if (doit[D_HMAC]) {
static const char hmac_key[] = "This is a key...";
int len = strlen(hmac_key);
for (i = 0; i < loopargs_len; i++) {
loopargs[i].hctx = HMAC_CTX_new();
if (loopargs[i].hctx == NULL) {
BIO_printf(bio_err, "HMAC malloc failure, exiting...");
exit(1);
}
HMAC_Init_ex(loopargs[i].hctx, hmac_key, len, EVP_md5(), NULL);
}
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_HMAC], c[D_HMAC][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, HMAC_loop, loopargs);
d = Time_F(STOP);
print_result(D_HMAC, testnum, count, d);
}
for (i = 0; i < loopargs_len; i++) {
HMAC_CTX_free(loopargs[i].hctx);
}
}
#endif
if (doit[D_SHA1]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA1], c[D_SHA1][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, SHA1_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA1, testnum, count, d);
}
}
if (doit[D_SHA256]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA256], c[D_SHA256][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, SHA256_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA256, testnum, count, d);
}
}
if (doit[D_SHA512]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_SHA512], c[D_SHA512][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, SHA512_loop, loopargs);
d = Time_F(STOP);
print_result(D_SHA512, testnum, count, d);
}
}
#ifndef OPENSSL_NO_WHIRLPOOL
if (doit[D_WHIRLPOOL]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_WHIRLPOOL], c[D_WHIRLPOOL][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, WHIRLPOOL_loop, loopargs);
d = Time_F(STOP);
print_result(D_WHIRLPOOL, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_RMD160
if (doit[D_RMD160]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_RMD160], c[D_RMD160][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, EVP_Digest_RMD160_loop, loopargs);
d = Time_F(STOP);
print_result(D_RMD160, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_RC4
if (doit[D_RC4]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_RC4], c[D_RC4][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, RC4_loop, loopargs);
d = Time_F(STOP);
print_result(D_RC4, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_DES
if (doit[D_CBC_DES]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_CBC_DES], c[D_CBC_DES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, DES_ncbc_encrypt_loop, loopargs);
d = Time_F(STOP);
print_result(D_CBC_DES, testnum, count, d);
}
}
if (doit[D_EDE3_DES]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_EDE3_DES], c[D_EDE3_DES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, DES_ede3_cbc_encrypt_loop, loopargs);
d = Time_F(STOP);
print_result(D_EDE3_DES, testnum, count, d);
}
}
#endif
if (doit[D_CBC_128_AES]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_CBC_128_AES], c[D_CBC_128_AES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, AES_cbc_128_encrypt_loop, loopargs);
d = Time_F(STOP);
print_result(D_CBC_128_AES, testnum, count, d);
}
}
if (doit[D_CBC_192_AES]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_CBC_192_AES], c[D_CBC_192_AES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, AES_cbc_192_encrypt_loop, loopargs);
d = Time_F(STOP);
print_result(D_CBC_192_AES, testnum, count, d);
}
}
if (doit[D_CBC_256_AES]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_CBC_256_AES], c[D_CBC_256_AES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, AES_cbc_256_encrypt_loop, loopargs);
d = Time_F(STOP);
print_result(D_CBC_256_AES, testnum, count, d);
}
}
if (doit[D_IGE_128_AES]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_IGE_128_AES], c[D_IGE_128_AES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, AES_ige_128_encrypt_loop, loopargs);
d = Time_F(STOP);
print_result(D_IGE_128_AES, testnum, count, d);
}
}
if (doit[D_IGE_192_AES]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_IGE_192_AES], c[D_IGE_192_AES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, AES_ige_192_encrypt_loop, loopargs);
d = Time_F(STOP);
print_result(D_IGE_192_AES, testnum, count, d);
}
}
if (doit[D_IGE_256_AES]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_IGE_256_AES], c[D_IGE_256_AES][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count =
run_benchmark(async_jobs, AES_ige_256_encrypt_loop, loopargs);
d = Time_F(STOP);
print_result(D_IGE_256_AES, testnum, count, d);
}
}
if (doit[D_GHASH]) {
for (i = 0; i < loopargs_len; i++) {
loopargs[i].gcm_ctx =
CRYPTO_gcm128_new(&aes_ks1, (block128_f) AES_encrypt);
CRYPTO_gcm128_setiv(loopargs[i].gcm_ctx,
(unsigned char *)"0123456789ab", 12);
}
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_GHASH], c[D_GHASH][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, CRYPTO_gcm128_aad_loop, loopargs);
d = Time_F(STOP);
print_result(D_GHASH, testnum, count, d);
}
for (i = 0; i < loopargs_len; i++)
CRYPTO_gcm128_release(loopargs[i].gcm_ctx);
}
#ifndef OPENSSL_NO_CAMELLIA
if (doit[D_CBC_128_CML]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_128_CML]);
doit[D_CBC_128_CML] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_128_CML], c[D_CBC_128_CML][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_128_CML][testnum]); count++)
Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &camellia_ks1,
iv, CAMELLIA_ENCRYPT);
d = Time_F(STOP);
print_result(D_CBC_128_CML, testnum, count, d);
}
}
if (doit[D_CBC_192_CML]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_192_CML]);
doit[D_CBC_192_CML] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_192_CML], c[D_CBC_192_CML][testnum],
lengths[testnum], seconds.sym);
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported, exiting...");
exit(1);
}
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_192_CML][testnum]); count++)
Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &camellia_ks2,
iv, CAMELLIA_ENCRYPT);
d = Time_F(STOP);
print_result(D_CBC_192_CML, testnum, count, d);
}
}
if (doit[D_CBC_256_CML]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_256_CML]);
doit[D_CBC_256_CML] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_256_CML], c[D_CBC_256_CML][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_256_CML][testnum]); count++)
Camellia_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &camellia_ks3,
iv, CAMELLIA_ENCRYPT);
d = Time_F(STOP);
print_result(D_CBC_256_CML, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_IDEA
if (doit[D_CBC_IDEA]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_IDEA]);
doit[D_CBC_IDEA] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_IDEA], c[D_CBC_IDEA][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_IDEA][testnum]); count++)
IDEA_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &idea_ks,
iv, IDEA_ENCRYPT);
d = Time_F(STOP);
print_result(D_CBC_IDEA, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_SEED
if (doit[D_CBC_SEED]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_SEED]);
doit[D_CBC_SEED] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_SEED], c[D_CBC_SEED][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_SEED][testnum]); count++)
SEED_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &seed_ks, iv, 1);
d = Time_F(STOP);
print_result(D_CBC_SEED, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_RC2
if (doit[D_CBC_RC2]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_RC2]);
doit[D_CBC_RC2] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_RC2], c[D_CBC_RC2][testnum],
lengths[testnum], seconds.sym);
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported, exiting...");
exit(1);
}
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_RC2][testnum]); count++)
RC2_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &rc2_ks,
iv, RC2_ENCRYPT);
d = Time_F(STOP);
print_result(D_CBC_RC2, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_RC5
if (doit[D_CBC_RC5]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_RC5]);
doit[D_CBC_RC5] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_RC5], c[D_CBC_RC5][testnum],
lengths[testnum], seconds.sym);
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported, exiting...");
exit(1);
}
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_RC5][testnum]); count++)
RC5_32_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &rc5_ks,
iv, RC5_ENCRYPT);
d = Time_F(STOP);
print_result(D_CBC_RC5, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_BF
if (doit[D_CBC_BF]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_BF]);
doit[D_CBC_BF] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_BF], c[D_CBC_BF][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_BF][testnum]); count++)
BF_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &bf_ks,
iv, BF_ENCRYPT);
d = Time_F(STOP);
print_result(D_CBC_BF, testnum, count, d);
}
}
#endif
#ifndef OPENSSL_NO_CAST
if (doit[D_CBC_CAST]) {
if (async_jobs > 0) {
BIO_printf(bio_err, "Async mode is not supported with %s\n",
names[D_CBC_CAST]);
doit[D_CBC_CAST] = 0;
}
for (testnum = 0; testnum < size_num && async_init == 0; testnum++) {
print_message(names[D_CBC_CAST], c[D_CBC_CAST][testnum],
lengths[testnum], seconds.sym);
Time_F(START);
for (count = 0, run = 1; COND(c[D_CBC_CAST][testnum]); count++)
CAST_cbc_encrypt(loopargs[0].buf, loopargs[0].buf,
(size_t)lengths[testnum], &cast_ks,
iv, CAST_ENCRYPT);
d = Time_F(STOP);
print_result(D_CBC_CAST, testnum, count, d);
}
}
#endif
if (doit[D_RAND]) {
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_RAND], c[D_RAND][testnum], lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, RAND_bytes_loop, loopargs);
d = Time_F(STOP);
print_result(D_RAND, testnum, count, d);
}
}
if (doit[D_EVP]) {
if (evp_cipher != NULL) {
int (*loopfunc)(void *args) = EVP_Update_loop;
if (multiblock && (EVP_CIPHER_flags(evp_cipher) &
EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)) {
multiblock_speed(evp_cipher, lengths_single, &seconds);
ret = 0;
goto end;
}
names[D_EVP] = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
if (EVP_CIPHER_mode(evp_cipher) == EVP_CIPH_CCM_MODE) {
loopfunc = EVP_Update_loop_ccm;
} else if (aead && (EVP_CIPHER_flags(evp_cipher) &
EVP_CIPH_FLAG_AEAD_CIPHER)) {
loopfunc = EVP_Update_loop_aead;
if (lengths == lengths_list) {
lengths = aead_lengths_list;
size_num = OSSL_NELEM(aead_lengths_list);
}
}
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_EVP], save_count, lengths[testnum],
seconds.sym);
for (k = 0; k < loopargs_len; k++) {
loopargs[k].ctx = EVP_CIPHER_CTX_new();
- EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL, NULL,
- iv, decrypt ? 0 : 1);
+ if (loopargs[k].ctx == NULL) {
+ BIO_printf(bio_err, "\nEVP_CIPHER_CTX_new failure\n");
+ exit(1);
+ }
+ if (!EVP_CipherInit_ex(loopargs[k].ctx, evp_cipher, NULL,
+ NULL, iv, decrypt ? 0 : 1)) {
+ BIO_printf(bio_err, "\nEVP_CipherInit_ex failure\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
EVP_CIPHER_CTX_set_padding(loopargs[k].ctx, 0);
keylen = EVP_CIPHER_CTX_key_length(loopargs[k].ctx);
loopargs[k].key = app_malloc(keylen, "evp_cipher key");
EVP_CIPHER_CTX_rand_key(loopargs[k].ctx, loopargs[k].key);
- EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
- loopargs[k].key, NULL, -1);
+ if (!EVP_CipherInit_ex(loopargs[k].ctx, NULL, NULL,
+ loopargs[k].key, NULL, -1)) {
+ BIO_printf(bio_err, "\nEVP_CipherInit_ex failure\n");
+ ERR_print_errors(bio_err);
+ exit(1);
+ }
OPENSSL_clear_free(loopargs[k].key, keylen);
}
Time_F(START);
count = run_benchmark(async_jobs, loopfunc, loopargs);
d = Time_F(STOP);
for (k = 0; k < loopargs_len; k++) {
EVP_CIPHER_CTX_free(loopargs[k].ctx);
}
print_result(D_EVP, testnum, count, d);
}
} else if (evp_md != NULL) {
names[D_EVP] = OBJ_nid2ln(EVP_MD_type(evp_md));
for (testnum = 0; testnum < size_num; testnum++) {
print_message(names[D_EVP], save_count, lengths[testnum],
seconds.sym);
Time_F(START);
count = run_benchmark(async_jobs, EVP_Digest_loop, loopargs);
d = Time_F(STOP);
print_result(D_EVP, testnum, count, d);
}
}
}
for (i = 0; i < loopargs_len; i++)
if (RAND_bytes(loopargs[i].buf, 36) <= 0)
goto end;
#ifndef OPENSSL_NO_RSA
for (testnum = 0; testnum < RSA_NUM; testnum++) {
int st = 0;
if (!rsa_doit[testnum])
continue;
for (i = 0; i < loopargs_len; i++) {
if (primes > 2) {
/* we haven't set keys yet, generate multi-prime RSA keys */
BIGNUM *bn = BN_new();
if (bn == NULL)
goto end;
if (!BN_set_word(bn, RSA_F4)) {
BN_free(bn);
goto end;
}
BIO_printf(bio_err, "Generate multi-prime RSA key for %s\n",
rsa_choices[testnum].name);
loopargs[i].rsa_key[testnum] = RSA_new();
if (loopargs[i].rsa_key[testnum] == NULL) {
BN_free(bn);
goto end;
}
if (!RSA_generate_multi_prime_key(loopargs[i].rsa_key[testnum],
rsa_bits[testnum],
primes, bn, NULL)) {
BN_free(bn);
goto end;
}
BN_free(bn);
}
st = RSA_sign(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
&loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
if (st == 0)
break;
}
if (st == 0) {
BIO_printf(bio_err,
"RSA sign failure. No RSA sign will be done.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
} else {
pkey_print_message("private", "rsa",
rsa_c[testnum][0], rsa_bits[testnum],
seconds.rsa);
/* RSA_blinding_on(rsa_key[testnum],NULL); */
Time_F(START);
count = run_benchmark(async_jobs, RSA_sign_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R1:%ld:%d:%.2f\n"
: "%ld %u bits private RSA's in %.2fs\n",
count, rsa_bits[testnum], d);
rsa_results[testnum][0] = (double)count / d;
rsa_count = count;
}
for (i = 0; i < loopargs_len; i++) {
st = RSA_verify(NID_md5_sha1, loopargs[i].buf, 36, loopargs[i].buf2,
loopargs[i].siglen, loopargs[i].rsa_key[testnum]);
if (st <= 0)
break;
}
if (st <= 0) {
BIO_printf(bio_err,
"RSA verify failure. No RSA verify will be done.\n");
ERR_print_errors(bio_err);
rsa_doit[testnum] = 0;
} else {
pkey_print_message("public", "rsa",
rsa_c[testnum][1], rsa_bits[testnum],
seconds.rsa);
Time_F(START);
count = run_benchmark(async_jobs, RSA_verify_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R2:%ld:%d:%.2f\n"
: "%ld %u bits public RSA's in %.2fs\n",
count, rsa_bits[testnum], d);
rsa_results[testnum][1] = (double)count / d;
}
if (rsa_count <= 1) {
/* if longer than 10s, don't do any more */
for (testnum++; testnum < RSA_NUM; testnum++)
rsa_doit[testnum] = 0;
}
}
#endif /* OPENSSL_NO_RSA */
for (i = 0; i < loopargs_len; i++)
if (RAND_bytes(loopargs[i].buf, 36) <= 0)
goto end;
#ifndef OPENSSL_NO_DSA
for (testnum = 0; testnum < DSA_NUM; testnum++) {
int st = 0;
if (!dsa_doit[testnum])
continue;
/* DSA_generate_key(dsa_key[testnum]); */
/* DSA_sign_setup(dsa_key[testnum],NULL); */
for (i = 0; i < loopargs_len; i++) {
st = DSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
&loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
if (st == 0)
break;
}
if (st == 0) {
BIO_printf(bio_err,
"DSA sign failure. No DSA sign will be done.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
} else {
pkey_print_message("sign", "dsa",
dsa_c[testnum][0], dsa_bits[testnum],
seconds.dsa);
Time_F(START);
count = run_benchmark(async_jobs, DSA_sign_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R3:%ld:%u:%.2f\n"
: "%ld %u bits DSA signs in %.2fs\n",
count, dsa_bits[testnum], d);
dsa_results[testnum][0] = (double)count / d;
rsa_count = count;
}
for (i = 0; i < loopargs_len; i++) {
st = DSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2,
loopargs[i].siglen, loopargs[i].dsa_key[testnum]);
if (st <= 0)
break;
}
if (st <= 0) {
BIO_printf(bio_err,
"DSA verify failure. No DSA verify will be done.\n");
ERR_print_errors(bio_err);
dsa_doit[testnum] = 0;
} else {
pkey_print_message("verify", "dsa",
dsa_c[testnum][1], dsa_bits[testnum],
seconds.dsa);
Time_F(START);
count = run_benchmark(async_jobs, DSA_verify_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R4:%ld:%u:%.2f\n"
: "%ld %u bits DSA verify in %.2fs\n",
count, dsa_bits[testnum], d);
dsa_results[testnum][1] = (double)count / d;
}
if (rsa_count <= 1) {
/* if longer than 10s, don't do any more */
for (testnum++; testnum < DSA_NUM; testnum++)
dsa_doit[testnum] = 0;
}
}
#endif /* OPENSSL_NO_DSA */
#ifndef OPENSSL_NO_EC
for (testnum = 0; testnum < ECDSA_NUM; testnum++) {
int st = 1;
if (!ecdsa_doit[testnum])
continue; /* Ignore Curve */
for (i = 0; i < loopargs_len; i++) {
loopargs[i].ecdsa[testnum] =
EC_KEY_new_by_curve_name(test_curves[testnum].nid);
if (loopargs[i].ecdsa[testnum] == NULL) {
st = 0;
break;
}
}
if (st == 0) {
BIO_printf(bio_err, "ECDSA failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
} else {
for (i = 0; i < loopargs_len; i++) {
EC_KEY_precompute_mult(loopargs[i].ecdsa[testnum], NULL);
/* Perform ECDSA signature test */
EC_KEY_generate_key(loopargs[i].ecdsa[testnum]);
st = ECDSA_sign(0, loopargs[i].buf, 20, loopargs[i].buf2,
&loopargs[i].siglen,
loopargs[i].ecdsa[testnum]);
if (st == 0)
break;
}
if (st == 0) {
BIO_printf(bio_err,
"ECDSA sign failure. No ECDSA sign will be done.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
} else {
pkey_print_message("sign", "ecdsa",
ecdsa_c[testnum][0],
test_curves[testnum].bits, seconds.ecdsa);
Time_F(START);
count = run_benchmark(async_jobs, ECDSA_sign_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R5:%ld:%u:%.2f\n" :
"%ld %u bits ECDSA signs in %.2fs \n",
count, test_curves[testnum].bits, d);
ecdsa_results[testnum][0] = (double)count / d;
rsa_count = count;
}
/* Perform ECDSA verification test */
for (i = 0; i < loopargs_len; i++) {
st = ECDSA_verify(0, loopargs[i].buf, 20, loopargs[i].buf2,
loopargs[i].siglen,
loopargs[i].ecdsa[testnum]);
if (st != 1)
break;
}
if (st != 1) {
BIO_printf(bio_err,
"ECDSA verify failure. No ECDSA verify will be done.\n");
ERR_print_errors(bio_err);
ecdsa_doit[testnum] = 0;
} else {
pkey_print_message("verify", "ecdsa",
ecdsa_c[testnum][1],
test_curves[testnum].bits, seconds.ecdsa);
Time_F(START);
count = run_benchmark(async_jobs, ECDSA_verify_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R6:%ld:%u:%.2f\n"
: "%ld %u bits ECDSA verify in %.2fs\n",
count, test_curves[testnum].bits, d);
ecdsa_results[testnum][1] = (double)count / d;
}
if (rsa_count <= 1) {
/* if longer than 10s, don't do any more */
for (testnum++; testnum < ECDSA_NUM; testnum++)
ecdsa_doit[testnum] = 0;
}
}
}
for (testnum = 0; testnum < EC_NUM; testnum++) {
int ecdh_checks = 1;
if (!ecdh_doit[testnum])
continue;
for (i = 0; i < loopargs_len; i++) {
EVP_PKEY_CTX *kctx = NULL;
EVP_PKEY_CTX *test_ctx = NULL;
EVP_PKEY_CTX *ctx = NULL;
EVP_PKEY *key_A = NULL;
EVP_PKEY *key_B = NULL;
size_t outlen;
size_t test_outlen;
/* Ensure that the error queue is empty */
if (ERR_peek_error()) {
BIO_printf(bio_err,
"WARNING: the error queue contains previous unhandled errors.\n");
ERR_print_errors(bio_err);
}
/* Let's try to create a ctx directly from the NID: this works for
* curves like Curve25519 that are not implemented through the low
* level EC interface.
* If this fails we try creating a EVP_PKEY_EC generic param ctx,
* then we set the curve by NID before deriving the actual keygen
* ctx for that specific curve. */
kctx = EVP_PKEY_CTX_new_id(test_curves[testnum].nid, NULL); /* keygen ctx from NID */
if (!kctx) {
EVP_PKEY_CTX *pctx = NULL;
EVP_PKEY *params = NULL;
/* If we reach this code EVP_PKEY_CTX_new_id() failed and a
* "int_ctx_new:unsupported algorithm" error was added to the
* error queue.
* We remove it from the error queue as we are handling it. */
unsigned long error = ERR_peek_error(); /* peek the latest error in the queue */
if (error == ERR_peek_last_error() && /* oldest and latest errors match */
/* check that the error origin matches */
ERR_GET_LIB(error) == ERR_LIB_EVP &&
ERR_GET_FUNC(error) == EVP_F_INT_CTX_NEW &&
ERR_GET_REASON(error) == EVP_R_UNSUPPORTED_ALGORITHM)
ERR_get_error(); /* pop error from queue */
if (ERR_peek_error()) {
BIO_printf(bio_err,
"Unhandled error in the error queue during ECDH init.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
break;
}
if ( /* Create the context for parameter generation */
!(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)) ||
/* Initialise the parameter generation */
!EVP_PKEY_paramgen_init(pctx) ||
/* Set the curve by NID */
!EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx,
test_curves
[testnum].nid) ||
/* Create the parameter object params */
!EVP_PKEY_paramgen(pctx, &params)) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH EC params init failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
break;
}
/* Create the context for the key generation */
kctx = EVP_PKEY_CTX_new(params, NULL);
EVP_PKEY_free(params);
params = NULL;
EVP_PKEY_CTX_free(pctx);
pctx = NULL;
}
if (kctx == NULL || /* keygen ctx is not null */
!EVP_PKEY_keygen_init(kctx) /* init keygen ctx */ ) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH keygen failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
break;
}
if (!EVP_PKEY_keygen(kctx, &key_A) || /* generate secret key A */
!EVP_PKEY_keygen(kctx, &key_B) || /* generate secret key B */
!(ctx = EVP_PKEY_CTX_new(key_A, NULL)) || /* derivation ctx from skeyA */
!EVP_PKEY_derive_init(ctx) || /* init derivation ctx */
!EVP_PKEY_derive_set_peer(ctx, key_B) || /* set peer pubkey in ctx */
!EVP_PKEY_derive(ctx, NULL, &outlen) || /* determine max length */
outlen == 0 || /* ensure outlen is a valid size */
outlen > MAX_ECDH_SIZE /* avoid buffer overflow */ ) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH key generation failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
break;
}
/* Here we perform a test run, comparing the output of a*B and b*A;
* we try this here and assume that further EVP_PKEY_derive calls
* never fail, so we can skip checks in the actually benchmarked
* code, for maximum performance. */
if (!(test_ctx = EVP_PKEY_CTX_new(key_B, NULL)) || /* test ctx from skeyB */
!EVP_PKEY_derive_init(test_ctx) || /* init derivation test_ctx */
!EVP_PKEY_derive_set_peer(test_ctx, key_A) || /* set peer pubkey in test_ctx */
!EVP_PKEY_derive(test_ctx, NULL, &test_outlen) || /* determine max length */
!EVP_PKEY_derive(ctx, loopargs[i].secret_a, &outlen) || /* compute a*B */
!EVP_PKEY_derive(test_ctx, loopargs[i].secret_b, &test_outlen) || /* compute b*A */
test_outlen != outlen /* compare output length */ ) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH computation failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
break;
}
/* Compare the computation results: CRYPTO_memcmp() returns 0 if equal */
if (CRYPTO_memcmp(loopargs[i].secret_a,
loopargs[i].secret_b, outlen)) {
ecdh_checks = 0;
BIO_printf(bio_err, "ECDH computations don't match.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
break;
}
loopargs[i].ecdh_ctx[testnum] = ctx;
loopargs[i].outlen[testnum] = outlen;
EVP_PKEY_free(key_A);
EVP_PKEY_free(key_B);
EVP_PKEY_CTX_free(kctx);
kctx = NULL;
EVP_PKEY_CTX_free(test_ctx);
test_ctx = NULL;
}
if (ecdh_checks != 0) {
pkey_print_message("", "ecdh",
ecdh_c[testnum][0],
test_curves[testnum].bits, seconds.ecdh);
Time_F(START);
count =
run_benchmark(async_jobs, ECDH_EVP_derive_key_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R7:%ld:%d:%.2f\n" :
"%ld %u-bits ECDH ops in %.2fs\n", count,
test_curves[testnum].bits, d);
ecdh_results[testnum][0] = (double)count / d;
rsa_count = count;
}
if (rsa_count <= 1) {
/* if longer than 10s, don't do any more */
for (testnum++; testnum < OSSL_NELEM(ecdh_doit); testnum++)
ecdh_doit[testnum] = 0;
}
}
for (testnum = 0; testnum < EdDSA_NUM; testnum++) {
int st = 1;
EVP_PKEY *ed_pkey = NULL;
EVP_PKEY_CTX *ed_pctx = NULL;
if (!eddsa_doit[testnum])
continue; /* Ignore Curve */
for (i = 0; i < loopargs_len; i++) {
loopargs[i].eddsa_ctx[testnum] = EVP_MD_CTX_new();
if (loopargs[i].eddsa_ctx[testnum] == NULL) {
st = 0;
break;
}
if ((ed_pctx = EVP_PKEY_CTX_new_id(test_ed_curves[testnum].nid, NULL))
== NULL
|| !EVP_PKEY_keygen_init(ed_pctx)
|| !EVP_PKEY_keygen(ed_pctx, &ed_pkey)) {
st = 0;
EVP_PKEY_CTX_free(ed_pctx);
break;
}
EVP_PKEY_CTX_free(ed_pctx);
if (!EVP_DigestSignInit(loopargs[i].eddsa_ctx[testnum], NULL, NULL,
NULL, ed_pkey)) {
st = 0;
EVP_PKEY_free(ed_pkey);
break;
}
EVP_PKEY_free(ed_pkey);
}
if (st == 0) {
BIO_printf(bio_err, "EdDSA failure.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
} else {
for (i = 0; i < loopargs_len; i++) {
/* Perform EdDSA signature test */
loopargs[i].sigsize = test_ed_curves[testnum].sigsize;
st = EVP_DigestSign(loopargs[i].eddsa_ctx[testnum],
loopargs[i].buf2, &loopargs[i].sigsize,
loopargs[i].buf, 20);
if (st == 0)
break;
}
if (st == 0) {
BIO_printf(bio_err,
"EdDSA sign failure. No EdDSA sign will be done.\n");
ERR_print_errors(bio_err);
rsa_count = 1;
} else {
pkey_print_message("sign", test_ed_curves[testnum].name,
eddsa_c[testnum][0],
test_ed_curves[testnum].bits, seconds.eddsa);
Time_F(START);
count = run_benchmark(async_jobs, EdDSA_sign_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R8:%ld:%u:%s:%.2f\n" :
"%ld %u bits %s signs in %.2fs \n",
count, test_ed_curves[testnum].bits,
test_ed_curves[testnum].name, d);
eddsa_results[testnum][0] = (double)count / d;
rsa_count = count;
}
/* Perform EdDSA verification test */
for (i = 0; i < loopargs_len; i++) {
st = EVP_DigestVerify(loopargs[i].eddsa_ctx[testnum],
loopargs[i].buf2, loopargs[i].sigsize,
loopargs[i].buf, 20);
if (st != 1)
break;
}
if (st != 1) {
BIO_printf(bio_err,
"EdDSA verify failure. No EdDSA verify will be done.\n");
ERR_print_errors(bio_err);
eddsa_doit[testnum] = 0;
} else {
pkey_print_message("verify", test_ed_curves[testnum].name,
eddsa_c[testnum][1],
test_ed_curves[testnum].bits, seconds.eddsa);
Time_F(START);
count = run_benchmark(async_jobs, EdDSA_verify_loop, loopargs);
d = Time_F(STOP);
BIO_printf(bio_err,
mr ? "+R9:%ld:%u:%s:%.2f\n"
: "%ld %u bits %s verify in %.2fs\n",
count, test_ed_curves[testnum].bits,
test_ed_curves[testnum].name, d);
eddsa_results[testnum][1] = (double)count / d;
}
if (rsa_count <= 1) {
/* if longer than 10s, don't do any more */
for (testnum++; testnum < EdDSA_NUM; testnum++)
eddsa_doit[testnum] = 0;
}
}
}
#endif /* OPENSSL_NO_EC */
#ifndef NO_FORK
show_res:
#endif
if (!mr) {
printf("%s\n", OpenSSL_version(OPENSSL_VERSION));
printf("%s\n", OpenSSL_version(OPENSSL_BUILT_ON));
printf("options:");
printf("%s ", BN_options());
#ifndef OPENSSL_NO_MD2
printf("%s ", MD2_options());
#endif
#ifndef OPENSSL_NO_RC4
printf("%s ", RC4_options());
#endif
#ifndef OPENSSL_NO_DES
printf("%s ", DES_options());
#endif
printf("%s ", AES_options());
#ifndef OPENSSL_NO_IDEA
printf("%s ", IDEA_options());
#endif
#ifndef OPENSSL_NO_BF
printf("%s ", BF_options());
#endif
printf("\n%s\n", OpenSSL_version(OPENSSL_CFLAGS));
}
if (pr_header) {
if (mr)
printf("+H");
else {
printf
("The 'numbers' are in 1000s of bytes per second processed.\n");
printf("type ");
}
for (testnum = 0; testnum < size_num; testnum++)
printf(mr ? ":%d" : "%7d bytes", lengths[testnum]);
printf("\n");
}
for (k = 0; k < ALGOR_NUM; k++) {
if (!doit[k])
continue;
if (mr)
printf("+F:%u:%s", k, names[k]);
else
printf("%-13s", names[k]);
for (testnum = 0; testnum < size_num; testnum++) {
if (results[k][testnum] > 10000 && !mr)
printf(" %11.2fk", results[k][testnum] / 1e3);
else
printf(mr ? ":%.2f" : " %11.2f ", results[k][testnum]);
}
printf("\n");
}
#ifndef OPENSSL_NO_RSA
testnum = 1;
for (k = 0; k < RSA_NUM; k++) {
if (!rsa_doit[k])
continue;
if (testnum && !mr) {
printf("%18ssign verify sign/s verify/s\n", " ");
testnum = 0;
}
if (mr)
printf("+F2:%u:%u:%f:%f\n",
k, rsa_bits[k], rsa_results[k][0], rsa_results[k][1]);
else
printf("rsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
rsa_bits[k], 1.0 / rsa_results[k][0], 1.0 / rsa_results[k][1],
rsa_results[k][0], rsa_results[k][1]);
}
#endif
#ifndef OPENSSL_NO_DSA
testnum = 1;
for (k = 0; k < DSA_NUM; k++) {
if (!dsa_doit[k])
continue;
if (testnum && !mr) {
printf("%18ssign verify sign/s verify/s\n", " ");
testnum = 0;
}
if (mr)
printf("+F3:%u:%u:%f:%f\n",
k, dsa_bits[k], dsa_results[k][0], dsa_results[k][1]);
else
printf("dsa %4u bits %8.6fs %8.6fs %8.1f %8.1f\n",
dsa_bits[k], 1.0 / dsa_results[k][0], 1.0 / dsa_results[k][1],
dsa_results[k][0], dsa_results[k][1]);
}
#endif
#ifndef OPENSSL_NO_EC
testnum = 1;
for (k = 0; k < OSSL_NELEM(ecdsa_doit); k++) {
if (!ecdsa_doit[k])
continue;
if (testnum && !mr) {
printf("%30ssign verify sign/s verify/s\n", " ");
testnum = 0;
}
if (mr)
printf("+F4:%u:%u:%f:%f\n",
k, test_curves[k].bits,
ecdsa_results[k][0], ecdsa_results[k][1]);
else
printf("%4u bits ecdsa (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
test_curves[k].bits, test_curves[k].name,
1.0 / ecdsa_results[k][0], 1.0 / ecdsa_results[k][1],
ecdsa_results[k][0], ecdsa_results[k][1]);
}
testnum = 1;
for (k = 0; k < EC_NUM; k++) {
if (!ecdh_doit[k])
continue;
if (testnum && !mr) {
printf("%30sop op/s\n", " ");
testnum = 0;
}
if (mr)
printf("+F5:%u:%u:%f:%f\n",
k, test_curves[k].bits,
ecdh_results[k][0], 1.0 / ecdh_results[k][0]);
else
printf("%4u bits ecdh (%s) %8.4fs %8.1f\n",
test_curves[k].bits, test_curves[k].name,
1.0 / ecdh_results[k][0], ecdh_results[k][0]);
}
testnum = 1;
for (k = 0; k < OSSL_NELEM(eddsa_doit); k++) {
if (!eddsa_doit[k])
continue;
if (testnum && !mr) {
printf("%30ssign verify sign/s verify/s\n", " ");
testnum = 0;
}
if (mr)
printf("+F6:%u:%u:%s:%f:%f\n",
k, test_ed_curves[k].bits, test_ed_curves[k].name,
eddsa_results[k][0], eddsa_results[k][1]);
else
printf("%4u bits EdDSA (%s) %8.4fs %8.4fs %8.1f %8.1f\n",
test_ed_curves[k].bits, test_ed_curves[k].name,
1.0 / eddsa_results[k][0], 1.0 / eddsa_results[k][1],
eddsa_results[k][0], eddsa_results[k][1]);
}
#endif
ret = 0;
end:
ERR_print_errors(bio_err);
for (i = 0; i < loopargs_len; i++) {
OPENSSL_free(loopargs[i].buf_malloc);
OPENSSL_free(loopargs[i].buf2_malloc);
#ifndef OPENSSL_NO_RSA
for (k = 0; k < RSA_NUM; k++)
RSA_free(loopargs[i].rsa_key[k]);
#endif
#ifndef OPENSSL_NO_DSA
for (k = 0; k < DSA_NUM; k++)
DSA_free(loopargs[i].dsa_key[k]);
#endif
#ifndef OPENSSL_NO_EC
for (k = 0; k < ECDSA_NUM; k++)
EC_KEY_free(loopargs[i].ecdsa[k]);
for (k = 0; k < EC_NUM; k++)
EVP_PKEY_CTX_free(loopargs[i].ecdh_ctx[k]);
for (k = 0; k < EdDSA_NUM; k++)
EVP_MD_CTX_free(loopargs[i].eddsa_ctx[k]);
OPENSSL_free(loopargs[i].secret_a);
OPENSSL_free(loopargs[i].secret_b);
#endif
}
if (async_jobs > 0) {
for (i = 0; i < loopargs_len; i++)
ASYNC_WAIT_CTX_free(loopargs[i].wait_ctx);
}
if (async_init) {
ASYNC_cleanup_thread();
}
OPENSSL_free(loopargs);
release_engine(e);
return ret;
}
static void print_message(const char *s, long num, int length, int tm)
{
#ifdef SIGALRM
BIO_printf(bio_err,
mr ? "+DT:%s:%d:%d\n"
: "Doing %s for %ds on %d size blocks: ", s, tm, length);
(void)BIO_flush(bio_err);
alarm(tm);
#else
BIO_printf(bio_err,
mr ? "+DN:%s:%ld:%d\n"
: "Doing %s %ld times on %d size blocks: ", s, num, length);
(void)BIO_flush(bio_err);
#endif
}
static void pkey_print_message(const char *str, const char *str2, long num,
unsigned int bits, int tm)
{
#ifdef SIGALRM
BIO_printf(bio_err,
mr ? "+DTP:%d:%s:%s:%d\n"
: "Doing %u bits %s %s's for %ds: ", bits, str, str2, tm);
(void)BIO_flush(bio_err);
alarm(tm);
#else
BIO_printf(bio_err,
mr ? "+DNP:%ld:%d:%s:%s\n"
: "Doing %ld %u bits %s %s's: ", num, bits, str, str2);
(void)BIO_flush(bio_err);
#endif
}
static void print_result(int alg, int run_no, int count, double time_used)
{
if (count == -1) {
BIO_puts(bio_err, "EVP error!\n");
exit(1);
}
BIO_printf(bio_err,
mr ? "+R:%d:%s:%f\n"
: "%d %s's in %.2fs\n", count, names[alg], time_used);
results[alg][run_no] = ((double)count) / time_used * lengths[run_no];
}
#ifndef NO_FORK
static char *sstrsep(char **string, const char *delim)
{
char isdelim[256];
char *token = *string;
if (**string == 0)
return NULL;
memset(isdelim, 0, sizeof(isdelim));
isdelim[0] = 1;
while (*delim) {
isdelim[(unsigned char)(*delim)] = 1;
delim++;
}
while (!isdelim[(unsigned char)(**string)]) {
(*string)++;
}
if (**string) {
**string = 0;
(*string)++;
}
return token;
}
static int do_multi(int multi, int size_num)
{
int n;
int fd[2];
int *fds;
static char sep[] = ":";
fds = app_malloc(sizeof(*fds) * multi, "fd buffer for do_multi");
for (n = 0; n < multi; ++n) {
if (pipe(fd) == -1) {
BIO_printf(bio_err, "pipe failure\n");
exit(1);
}
fflush(stdout);
(void)BIO_flush(bio_err);
if (fork()) {
close(fd[1]);
fds[n] = fd[0];
} else {
close(fd[0]);
close(1);
if (dup(fd[1]) == -1) {
BIO_printf(bio_err, "dup failed\n");
exit(1);
}
close(fd[1]);
mr = 1;
usertime = 0;
free(fds);
return 0;
}
printf("Forked child %d\n", n);
}
/* for now, assume the pipe is long enough to take all the output */
for (n = 0; n < multi; ++n) {
FILE *f;
char buf[1024];
char *p;
f = fdopen(fds[n], "r");
while (fgets(buf, sizeof(buf), f)) {
p = strchr(buf, '\n');
if (p)
*p = '\0';
if (buf[0] != '+') {
BIO_printf(bio_err,
"Don't understand line '%s' from child %d\n", buf,
n);
continue;
}
printf("Got: %s from %d\n", buf, n);
if (strncmp(buf, "+F:", 3) == 0) {
int alg;
int j;
p = buf + 3;
alg = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
for (j = 0; j < size_num; ++j)
results[alg][j] += atof(sstrsep(&p, sep));
} else if (strncmp(buf, "+F2:", 4) == 0) {
int k;
double d;
p = buf + 4;
k = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
rsa_results[k][0] += d;
d = atof(sstrsep(&p, sep));
rsa_results[k][1] += d;
}
# ifndef OPENSSL_NO_DSA
else if (strncmp(buf, "+F3:", 4) == 0) {
int k;
double d;
p = buf + 4;
k = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
dsa_results[k][0] += d;
d = atof(sstrsep(&p, sep));
dsa_results[k][1] += d;
}
# endif
# ifndef OPENSSL_NO_EC
else if (strncmp(buf, "+F4:", 4) == 0) {
int k;
double d;
p = buf + 4;
k = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
ecdsa_results[k][0] += d;
d = atof(sstrsep(&p, sep));
ecdsa_results[k][1] += d;
} else if (strncmp(buf, "+F5:", 4) == 0) {
int k;
double d;
p = buf + 4;
k = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
ecdh_results[k][0] += d;
} else if (strncmp(buf, "+F6:", 4) == 0) {
int k;
double d;
p = buf + 4;
k = atoi(sstrsep(&p, sep));
sstrsep(&p, sep);
d = atof(sstrsep(&p, sep));
eddsa_results[k][0] += d;
d = atof(sstrsep(&p, sep));
eddsa_results[k][1] += d;
}
# endif
else if (strncmp(buf, "+H:", 3) == 0) {
;
} else
BIO_printf(bio_err, "Unknown type '%s' from child %d\n", buf,
n);
}
fclose(f);
}
free(fds);
return 1;
}
#endif
static void multiblock_speed(const EVP_CIPHER *evp_cipher, int lengths_single,
const openssl_speed_sec_t *seconds)
{
static const int mblengths_list[] =
{ 8 * 1024, 2 * 8 * 1024, 4 * 8 * 1024, 8 * 8 * 1024, 8 * 16 * 1024 };
const int *mblengths = mblengths_list;
int j, count, keylen, num = OSSL_NELEM(mblengths_list);
const char *alg_name;
unsigned char *inp, *out, *key, no_key[32], no_iv[16];
EVP_CIPHER_CTX *ctx;
double d = 0.0;
if (lengths_single) {
mblengths = &lengths_single;
num = 1;
}
inp = app_malloc(mblengths[num - 1], "multiblock input buffer");
out = app_malloc(mblengths[num - 1] + 1024, "multiblock output buffer");
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, evp_cipher, NULL, NULL, no_iv);
keylen = EVP_CIPHER_CTX_key_length(ctx);
key = app_malloc(keylen, "evp_cipher key");
EVP_CIPHER_CTX_rand_key(ctx, key);
EVP_EncryptInit_ex(ctx, NULL, NULL, key, NULL);
OPENSSL_clear_free(key, keylen);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_MAC_KEY, sizeof(no_key), no_key);
alg_name = OBJ_nid2ln(EVP_CIPHER_nid(evp_cipher));
for (j = 0; j < num; j++) {
print_message(alg_name, 0, mblengths[j], seconds->sym);
Time_F(START);
for (count = 0, run = 1; run && count < 0x7fffffff; count++) {
unsigned char aad[EVP_AEAD_TLS1_AAD_LEN];
EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM mb_param;
size_t len = mblengths[j];
int packlen;
memset(aad, 0, 8); /* avoid uninitialized values */
aad[8] = 23; /* SSL3_RT_APPLICATION_DATA */
aad[9] = 3; /* version */
aad[10] = 2;
aad[11] = 0; /* length */
aad[12] = 0;
mb_param.out = NULL;
mb_param.inp = aad;
mb_param.len = len;
mb_param.interleave = 8;
packlen = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_AAD,
sizeof(mb_param), &mb_param);
if (packlen > 0) {
mb_param.out = out;
mb_param.inp = inp;
mb_param.len = len;
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT,
sizeof(mb_param), &mb_param);
} else {
int pad;
RAND_bytes(out, 16);
len += 16;
aad[11] = (unsigned char)(len >> 8);
aad[12] = (unsigned char)(len);
pad = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_TLS1_AAD,
EVP_AEAD_TLS1_AAD_LEN, aad);
EVP_Cipher(ctx, out, inp, len + pad);
}
}
d = Time_F(STOP);
BIO_printf(bio_err, mr ? "+R:%d:%s:%f\n"
: "%d %s's in %.2fs\n", count, "evp", d);
results[D_EVP][j] = ((double)count) / d * mblengths[j];
}
if (mr) {
fprintf(stdout, "+H");
for (j = 0; j < num; j++)
fprintf(stdout, ":%d", mblengths[j]);
fprintf(stdout, "\n");
fprintf(stdout, "+F:%d:%s", D_EVP, alg_name);
for (j = 0; j < num; j++)
fprintf(stdout, ":%.2f", results[D_EVP][j]);
fprintf(stdout, "\n");
} else {
fprintf(stdout,
"The 'numbers' are in 1000s of bytes per second processed.\n");
fprintf(stdout, "type ");
for (j = 0; j < num; j++)
fprintf(stdout, "%7d bytes", mblengths[j]);
fprintf(stdout, "\n");
fprintf(stdout, "%-24s", alg_name);
for (j = 0; j < num; j++) {
if (results[D_EVP][j] > 10000)
fprintf(stdout, " %11.2fk", results[D_EVP][j] / 1e3);
else
fprintf(stdout, " %11.2f ", results[D_EVP][j]);
}
fprintf(stdout, "\n");
}
OPENSSL_free(inp);
OPENSSL_free(out);
EVP_CIPHER_CTX_free(ctx);
}
diff --git a/crypto/aes/asm/aesp8-ppc.pl b/crypto/aes/asm/aesp8-ppc.pl
index 488b133250c6..c0da1b84aaa9 100755
--- a/crypto/aes/asm/aesp8-ppc.pl
+++ b/crypto/aes/asm/aesp8-ppc.pl
@@ -1,3807 +1,3807 @@
#! /usr/bin/env perl
-# Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
# ====================================================================
#
# This module implements support for AES instructions as per PowerISA
# specification version 2.07, first implemented by POWER8 processor.
# The module is endian-agnostic in sense that it supports both big-
# and little-endian cases. Data alignment in parallelizable modes is
# handled with VSX loads and stores, which implies MSR.VSX flag being
# set. It should also be noted that ISA specification doesn't prohibit
# alignment exceptions for these instructions on page boundaries.
# Initially alignment was handled in pure AltiVec/VMX way [when data
# is aligned programmatically, which in turn guarantees exception-
# free execution], but it turned to hamper performance when vcipher
# instructions are interleaved. It's reckoned that eventual
# misalignment penalties at page boundaries are in average lower
# than additional overhead in pure AltiVec approach.
#
# May 2016
#
# Add XTS subroutine, 9x on little- and 12x improvement on big-endian
# systems were measured.
#
######################################################################
# Current large-block performance in cycles per byte processed with
# 128-bit key (less is better).
#
# CBC en-/decrypt CTR XTS
# POWER8[le] 3.96/0.72 0.74 1.1
# POWER8[be] 3.75/0.65 0.66 1.0
# POWER9[le] 4.02/0.86 0.84 1.05
# POWER9[be] 3.99/0.78 0.79 0.97
$flavour = shift;
if ($flavour =~ /64/) {
$SIZE_T =8;
$LRSAVE =2*$SIZE_T;
$STU ="stdu";
$POP ="ld";
$PUSH ="std";
$UCMP ="cmpld";
$SHL ="sldi";
} elsif ($flavour =~ /32/) {
$SIZE_T =4;
$LRSAVE =$SIZE_T;
$STU ="stwu";
$POP ="lwz";
$PUSH ="stw";
$UCMP ="cmplw";
$SHL ="slwi";
} else { die "nonsense $flavour"; }
$LITTLE_ENDIAN = ($flavour=~/le$/) ? $SIZE_T : 0;
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
$FRAME=8*$SIZE_T;
$prefix="aes_p8";
$sp="r1";
$vrsave="r12";
#########################################################################
{{{ # Key setup procedures #
my ($inp,$bits,$out,$ptr,$cnt,$rounds)=map("r$_",(3..8));
my ($zero,$in0,$in1,$key,$rcon,$mask,$tmp)=map("v$_",(0..6));
my ($stage,$outperm,$outmask,$outhead,$outtail)=map("v$_",(7..11));
$code.=<<___;
.machine "any"
.text
.align 7
rcon:
.long 0x01000000, 0x01000000, 0x01000000, 0x01000000 ?rev
.long 0x1b000000, 0x1b000000, 0x1b000000, 0x1b000000 ?rev
.long 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c, 0x0d0e0f0c ?rev
.long 0,0,0,0 ?asis
Lconsts:
mflr r0
bcl 20,31,\$+4
mflr $ptr #vvvvv "distance between . and rcon
addi $ptr,$ptr,-0x48
mtlr r0
blr
.long 0
.byte 0,12,0x14,0,0,0,0,0
.asciz "AES for PowerISA 2.07, CRYPTOGAMS by <appro\@openssl.org>"
.globl .${prefix}_set_encrypt_key
.align 5
.${prefix}_set_encrypt_key:
Lset_encrypt_key:
mflr r11
$PUSH r11,$LRSAVE($sp)
li $ptr,-1
${UCMP}i $inp,0
beq- Lenc_key_abort # if ($inp==0) return -1;
${UCMP}i $out,0
beq- Lenc_key_abort # if ($out==0) return -1;
li $ptr,-2
cmpwi $bits,128
blt- Lenc_key_abort
cmpwi $bits,256
bgt- Lenc_key_abort
andi. r0,$bits,0x3f
bne- Lenc_key_abort
lis r0,0xfff0
mfspr $vrsave,256
mtspr 256,r0
bl Lconsts
mtlr r11
neg r9,$inp
lvx $in0,0,$inp
addi $inp,$inp,15 # 15 is not typo
lvsr $key,0,r9 # borrow $key
li r8,0x20
cmpwi $bits,192
lvx $in1,0,$inp
le?vspltisb $mask,0x0f # borrow $mask
lvx $rcon,0,$ptr
le?vxor $key,$key,$mask # adjust for byte swap
lvx $mask,r8,$ptr
addi $ptr,$ptr,0x10
vperm $in0,$in0,$in1,$key # align [and byte swap in LE]
li $cnt,8
vxor $zero,$zero,$zero
mtctr $cnt
?lvsr $outperm,0,$out
vspltisb $outmask,-1
lvx $outhead,0,$out
?vperm $outmask,$zero,$outmask,$outperm
blt Loop128
addi $inp,$inp,8
beq L192
addi $inp,$inp,8
b L256
.align 4
Loop128:
vperm $key,$in0,$in0,$mask # rotate-n-splat
vsldoi $tmp,$zero,$in0,12 # >>32
vperm $outtail,$in0,$in0,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
vcipherlast $key,$key,$rcon
stvx $stage,0,$out
addi $out,$out,16
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vadduwm $rcon,$rcon,$rcon
vxor $in0,$in0,$key
bdnz Loop128
lvx $rcon,0,$ptr # last two round keys
vperm $key,$in0,$in0,$mask # rotate-n-splat
vsldoi $tmp,$zero,$in0,12 # >>32
vperm $outtail,$in0,$in0,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
vcipherlast $key,$key,$rcon
stvx $stage,0,$out
addi $out,$out,16
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vadduwm $rcon,$rcon,$rcon
vxor $in0,$in0,$key
vperm $key,$in0,$in0,$mask # rotate-n-splat
vsldoi $tmp,$zero,$in0,12 # >>32
vperm $outtail,$in0,$in0,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
vcipherlast $key,$key,$rcon
stvx $stage,0,$out
addi $out,$out,16
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vxor $in0,$in0,$key
vperm $outtail,$in0,$in0,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
stvx $stage,0,$out
addi $inp,$out,15 # 15 is not typo
addi $out,$out,0x50
li $rounds,10
b Ldone
.align 4
L192:
lvx $tmp,0,$inp
li $cnt,4
vperm $outtail,$in0,$in0,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
stvx $stage,0,$out
addi $out,$out,16
vperm $in1,$in1,$tmp,$key # align [and byte swap in LE]
vspltisb $key,8 # borrow $key
mtctr $cnt
vsububm $mask,$mask,$key # adjust the mask
Loop192:
vperm $key,$in1,$in1,$mask # roate-n-splat
vsldoi $tmp,$zero,$in0,12 # >>32
vcipherlast $key,$key,$rcon
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vsldoi $stage,$zero,$in1,8
vspltw $tmp,$in0,3
vxor $tmp,$tmp,$in1
vsldoi $in1,$zero,$in1,12 # >>32
vadduwm $rcon,$rcon,$rcon
vxor $in1,$in1,$tmp
vxor $in0,$in0,$key
vxor $in1,$in1,$key
vsldoi $stage,$stage,$in0,8
vperm $key,$in1,$in1,$mask # rotate-n-splat
vsldoi $tmp,$zero,$in0,12 # >>32
vperm $outtail,$stage,$stage,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
vcipherlast $key,$key,$rcon
stvx $stage,0,$out
addi $out,$out,16
vsldoi $stage,$in0,$in1,8
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vperm $outtail,$stage,$stage,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
stvx $stage,0,$out
addi $out,$out,16
vspltw $tmp,$in0,3
vxor $tmp,$tmp,$in1
vsldoi $in1,$zero,$in1,12 # >>32
vadduwm $rcon,$rcon,$rcon
vxor $in1,$in1,$tmp
vxor $in0,$in0,$key
vxor $in1,$in1,$key
vperm $outtail,$in0,$in0,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
stvx $stage,0,$out
addi $inp,$out,15 # 15 is not typo
addi $out,$out,16
bdnz Loop192
li $rounds,12
addi $out,$out,0x20
b Ldone
.align 4
L256:
lvx $tmp,0,$inp
li $cnt,7
li $rounds,14
vperm $outtail,$in0,$in0,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
stvx $stage,0,$out
addi $out,$out,16
vperm $in1,$in1,$tmp,$key # align [and byte swap in LE]
mtctr $cnt
Loop256:
vperm $key,$in1,$in1,$mask # rotate-n-splat
vsldoi $tmp,$zero,$in0,12 # >>32
vperm $outtail,$in1,$in1,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
vcipherlast $key,$key,$rcon
stvx $stage,0,$out
addi $out,$out,16
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in0,$in0,$tmp
vadduwm $rcon,$rcon,$rcon
vxor $in0,$in0,$key
vperm $outtail,$in0,$in0,$outperm # rotate
vsel $stage,$outhead,$outtail,$outmask
vmr $outhead,$outtail
stvx $stage,0,$out
addi $inp,$out,15 # 15 is not typo
addi $out,$out,16
bdz Ldone
vspltw $key,$in0,3 # just splat
vsldoi $tmp,$zero,$in1,12 # >>32
vsbox $key,$key
vxor $in1,$in1,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in1,$in1,$tmp
vsldoi $tmp,$zero,$tmp,12 # >>32
vxor $in1,$in1,$tmp
vxor $in1,$in1,$key
b Loop256
.align 4
Ldone:
lvx $in1,0,$inp # redundant in aligned case
vsel $in1,$outhead,$in1,$outmask
stvx $in1,0,$inp
li $ptr,0
mtspr 256,$vrsave
stw $rounds,0($out)
Lenc_key_abort:
mr r3,$ptr
blr
.long 0
.byte 0,12,0x14,1,0,0,3,0
.long 0
.size .${prefix}_set_encrypt_key,.-.${prefix}_set_encrypt_key
.globl .${prefix}_set_decrypt_key
.align 5
.${prefix}_set_decrypt_key:
$STU $sp,-$FRAME($sp)
mflr r10
$PUSH r10,$FRAME+$LRSAVE($sp)
bl Lset_encrypt_key
mtlr r10
cmpwi r3,0
bne- Ldec_key_abort
slwi $cnt,$rounds,4
subi $inp,$out,240 # first round key
srwi $rounds,$rounds,1
add $out,$inp,$cnt # last round key
mtctr $rounds
Ldeckey:
lwz r0, 0($inp)
lwz r6, 4($inp)
lwz r7, 8($inp)
lwz r8, 12($inp)
addi $inp,$inp,16
lwz r9, 0($out)
lwz r10,4($out)
lwz r11,8($out)
lwz r12,12($out)
stw r0, 0($out)
stw r6, 4($out)
stw r7, 8($out)
stw r8, 12($out)
subi $out,$out,16
stw r9, -16($inp)
stw r10,-12($inp)
stw r11,-8($inp)
stw r12,-4($inp)
bdnz Ldeckey
xor r3,r3,r3 # return value
Ldec_key_abort:
addi $sp,$sp,$FRAME
blr
.long 0
.byte 0,12,4,1,0x80,0,3,0
.long 0
.size .${prefix}_set_decrypt_key,.-.${prefix}_set_decrypt_key
___
}}}
#########################################################################
{{{ # Single block en- and decrypt procedures #
sub gen_block () {
my $dir = shift;
my $n = $dir eq "de" ? "n" : "";
my ($inp,$out,$key,$rounds,$idx)=map("r$_",(3..7));
$code.=<<___;
.globl .${prefix}_${dir}crypt
.align 5
.${prefix}_${dir}crypt:
lwz $rounds,240($key)
lis r0,0xfc00
mfspr $vrsave,256
li $idx,15 # 15 is not typo
mtspr 256,r0
lvx v0,0,$inp
neg r11,$out
lvx v1,$idx,$inp
lvsl v2,0,$inp # inpperm
le?vspltisb v4,0x0f
?lvsl v3,0,r11 # outperm
le?vxor v2,v2,v4
li $idx,16
vperm v0,v0,v1,v2 # align [and byte swap in LE]
lvx v1,0,$key
?lvsl v5,0,$key # keyperm
srwi $rounds,$rounds,1
lvx v2,$idx,$key
addi $idx,$idx,16
subi $rounds,$rounds,1
?vperm v1,v1,v2,v5 # align round key
vxor v0,v0,v1
lvx v1,$idx,$key
addi $idx,$idx,16
mtctr $rounds
Loop_${dir}c:
?vperm v2,v2,v1,v5
v${n}cipher v0,v0,v2
lvx v2,$idx,$key
addi $idx,$idx,16
?vperm v1,v1,v2,v5
v${n}cipher v0,v0,v1
lvx v1,$idx,$key
addi $idx,$idx,16
bdnz Loop_${dir}c
?vperm v2,v2,v1,v5
v${n}cipher v0,v0,v2
lvx v2,$idx,$key
?vperm v1,v1,v2,v5
v${n}cipherlast v0,v0,v1
vspltisb v2,-1
vxor v1,v1,v1
li $idx,15 # 15 is not typo
?vperm v2,v1,v2,v3 # outmask
le?vxor v3,v3,v4
lvx v1,0,$out # outhead
vperm v0,v0,v0,v3 # rotate [and byte swap in LE]
vsel v1,v1,v0,v2
lvx v4,$idx,$out
stvx v1,0,$out
vsel v0,v0,v4,v2
stvx v0,$idx,$out
mtspr 256,$vrsave
blr
.long 0
.byte 0,12,0x14,0,0,0,3,0
.long 0
.size .${prefix}_${dir}crypt,.-.${prefix}_${dir}crypt
___
}
&gen_block("en");
&gen_block("de");
}}}
#########################################################################
{{{ # CBC en- and decrypt procedures #
my ($inp,$out,$len,$key,$ivp,$enc,$rounds,$idx)=map("r$_",(3..10));
my ($rndkey0,$rndkey1,$inout,$tmp)= map("v$_",(0..3));
my ($ivec,$inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm)=
map("v$_",(4..10));
$code.=<<___;
.globl .${prefix}_cbc_encrypt
.align 5
.${prefix}_cbc_encrypt:
${UCMP}i $len,16
bltlr-
cmpwi $enc,0 # test direction
lis r0,0xffe0
mfspr $vrsave,256
mtspr 256,r0
li $idx,15
vxor $rndkey0,$rndkey0,$rndkey0
le?vspltisb $tmp,0x0f
lvx $ivec,0,$ivp # load [unaligned] iv
lvsl $inpperm,0,$ivp
lvx $inptail,$idx,$ivp
le?vxor $inpperm,$inpperm,$tmp
vperm $ivec,$ivec,$inptail,$inpperm
neg r11,$inp
?lvsl $keyperm,0,$key # prepare for unaligned key
lwz $rounds,240($key)
lvsr $inpperm,0,r11 # prepare for unaligned load
lvx $inptail,0,$inp
addi $inp,$inp,15 # 15 is not typo
le?vxor $inpperm,$inpperm,$tmp
?lvsr $outperm,0,$out # prepare for unaligned store
vspltisb $outmask,-1
lvx $outhead,0,$out
?vperm $outmask,$rndkey0,$outmask,$outperm
le?vxor $outperm,$outperm,$tmp
srwi $rounds,$rounds,1
li $idx,16
subi $rounds,$rounds,1
beq Lcbc_dec
Lcbc_enc:
vmr $inout,$inptail
lvx $inptail,0,$inp
addi $inp,$inp,16
mtctr $rounds
subi $len,$len,16 # len-=16
lvx $rndkey0,0,$key
vperm $inout,$inout,$inptail,$inpperm
lvx $rndkey1,$idx,$key
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key
addi $idx,$idx,16
vxor $inout,$inout,$ivec
Loop_cbc_enc:
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vcipher $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key
addi $idx,$idx,16
bdnz Loop_cbc_enc
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key
li $idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vcipherlast $ivec,$inout,$rndkey0
${UCMP}i $len,16
vperm $tmp,$ivec,$ivec,$outperm
vsel $inout,$outhead,$tmp,$outmask
vmr $outhead,$tmp
stvx $inout,0,$out
addi $out,$out,16
bge Lcbc_enc
b Lcbc_done
.align 4
Lcbc_dec:
${UCMP}i $len,128
bge _aesp8_cbc_decrypt8x
vmr $tmp,$inptail
lvx $inptail,0,$inp
addi $inp,$inp,16
mtctr $rounds
subi $len,$len,16 # len-=16
lvx $rndkey0,0,$key
vperm $tmp,$tmp,$inptail,$inpperm
lvx $rndkey1,$idx,$key
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $inout,$tmp,$rndkey0
lvx $rndkey0,$idx,$key
addi $idx,$idx,16
Loop_cbc_dec:
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vncipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vncipher $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key
addi $idx,$idx,16
bdnz Loop_cbc_dec
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vncipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key
li $idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vncipherlast $inout,$inout,$rndkey0
${UCMP}i $len,16
vxor $inout,$inout,$ivec
vmr $ivec,$tmp
vperm $tmp,$inout,$inout,$outperm
vsel $inout,$outhead,$tmp,$outmask
vmr $outhead,$tmp
stvx $inout,0,$out
addi $out,$out,16
bge Lcbc_dec
Lcbc_done:
addi $out,$out,-1
lvx $inout,0,$out # redundant in aligned case
vsel $inout,$outhead,$inout,$outmask
stvx $inout,0,$out
neg $enc,$ivp # write [unaligned] iv
li $idx,15 # 15 is not typo
vxor $rndkey0,$rndkey0,$rndkey0
vspltisb $outmask,-1
le?vspltisb $tmp,0x0f
?lvsl $outperm,0,$enc
?vperm $outmask,$rndkey0,$outmask,$outperm
le?vxor $outperm,$outperm,$tmp
lvx $outhead,0,$ivp
vperm $ivec,$ivec,$ivec,$outperm
vsel $inout,$outhead,$ivec,$outmask
lvx $inptail,$idx,$ivp
stvx $inout,0,$ivp
vsel $inout,$ivec,$inptail,$outmask
stvx $inout,$idx,$ivp
mtspr 256,$vrsave
blr
.long 0
.byte 0,12,0x14,0,0,0,6,0
.long 0
___
#########################################################################
{{ # Optimized CBC decrypt procedure #
my $key_="r11";
my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,8,26..31));
$x00=0 if ($flavour =~ /osx/);
my ($in0, $in1, $in2, $in3, $in4, $in5, $in6, $in7 )=map("v$_",(0..3,10..13));
my ($out0,$out1,$out2,$out3,$out4,$out5,$out6,$out7)=map("v$_",(14..21));
my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys
# v26-v31 last 6 round keys
my ($tmp,$keyperm)=($in3,$in4); # aliases with "caller", redundant assignment
$code.=<<___;
.align 5
_aesp8_cbc_decrypt8x:
$STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp)
li r10,`$FRAME+8*16+15`
li r11,`$FRAME+8*16+31`
stvx v20,r10,$sp # ABI says so
addi r10,r10,32
stvx v21,r11,$sp
addi r11,r11,32
stvx v22,r10,$sp
addi r10,r10,32
stvx v23,r11,$sp
addi r11,r11,32
stvx v24,r10,$sp
addi r10,r10,32
stvx v25,r11,$sp
addi r11,r11,32
stvx v26,r10,$sp
addi r10,r10,32
stvx v27,r11,$sp
addi r11,r11,32
stvx v28,r10,$sp
addi r10,r10,32
stvx v29,r11,$sp
addi r11,r11,32
stvx v30,r10,$sp
stvx v31,r11,$sp
li r0,-1
stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave
li $x10,0x10
$PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp)
li $x20,0x20
$PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp)
li $x30,0x30
$PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp)
li $x40,0x40
$PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp)
li $x50,0x50
$PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp)
li $x60,0x60
$PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp)
li $x70,0x70
mtspr 256,r0
subi $rounds,$rounds,3 # -4 in total
subi $len,$len,128 # bias
lvx $rndkey0,$x00,$key # load key schedule
lvx v30,$x10,$key
addi $key,$key,0x20
lvx v31,$x00,$key
?vperm $rndkey0,$rndkey0,v30,$keyperm
addi $key_,$sp,$FRAME+15
mtctr $rounds
Load_cbc_dec_key:
?vperm v24,v30,v31,$keyperm
lvx v30,$x10,$key
addi $key,$key,0x20
stvx v24,$x00,$key_ # off-load round[1]
?vperm v25,v31,v30,$keyperm
lvx v31,$x00,$key
stvx v25,$x10,$key_ # off-load round[2]
addi $key_,$key_,0x20
bdnz Load_cbc_dec_key
lvx v26,$x10,$key
?vperm v24,v30,v31,$keyperm
lvx v27,$x20,$key
stvx v24,$x00,$key_ # off-load round[3]
?vperm v25,v31,v26,$keyperm
lvx v28,$x30,$key
stvx v25,$x10,$key_ # off-load round[4]
addi $key_,$sp,$FRAME+15 # rewind $key_
?vperm v26,v26,v27,$keyperm
lvx v29,$x40,$key
?vperm v27,v27,v28,$keyperm
lvx v30,$x50,$key
?vperm v28,v28,v29,$keyperm
lvx v31,$x60,$key
?vperm v29,v29,v30,$keyperm
lvx $out0,$x70,$key # borrow $out0
?vperm v30,v30,v31,$keyperm
lvx v24,$x00,$key_ # pre-load round[1]
?vperm v31,v31,$out0,$keyperm
lvx v25,$x10,$key_ # pre-load round[2]
#lvx $inptail,0,$inp # "caller" already did this
#addi $inp,$inp,15 # 15 is not typo
subi $inp,$inp,15 # undo "caller"
le?li $idx,8
lvx_u $in0,$x00,$inp # load first 8 "words"
le?lvsl $inpperm,0,$idx
le?vspltisb $tmp,0x0f
lvx_u $in1,$x10,$inp
le?vxor $inpperm,$inpperm,$tmp # transform for lvx_u/stvx_u
lvx_u $in2,$x20,$inp
le?vperm $in0,$in0,$in0,$inpperm
lvx_u $in3,$x30,$inp
le?vperm $in1,$in1,$in1,$inpperm
lvx_u $in4,$x40,$inp
le?vperm $in2,$in2,$in2,$inpperm
vxor $out0,$in0,$rndkey0
lvx_u $in5,$x50,$inp
le?vperm $in3,$in3,$in3,$inpperm
vxor $out1,$in1,$rndkey0
lvx_u $in6,$x60,$inp
le?vperm $in4,$in4,$in4,$inpperm
vxor $out2,$in2,$rndkey0
lvx_u $in7,$x70,$inp
addi $inp,$inp,0x80
le?vperm $in5,$in5,$in5,$inpperm
vxor $out3,$in3,$rndkey0
le?vperm $in6,$in6,$in6,$inpperm
vxor $out4,$in4,$rndkey0
le?vperm $in7,$in7,$in7,$inpperm
vxor $out5,$in5,$rndkey0
vxor $out6,$in6,$rndkey0
vxor $out7,$in7,$rndkey0
mtctr $rounds
b Loop_cbc_dec8x
.align 5
Loop_cbc_dec8x:
vncipher $out0,$out0,v24
vncipher $out1,$out1,v24
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
vncipher $out4,$out4,v24
vncipher $out5,$out5,v24
vncipher $out6,$out6,v24
vncipher $out7,$out7,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vncipher $out0,$out0,v25
vncipher $out1,$out1,v25
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vncipher $out4,$out4,v25
vncipher $out5,$out5,v25
vncipher $out6,$out6,v25
vncipher $out7,$out7,v25
lvx v25,$x10,$key_ # round[4]
bdnz Loop_cbc_dec8x
subic $len,$len,128 # $len-=128
vncipher $out0,$out0,v24
vncipher $out1,$out1,v24
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
vncipher $out4,$out4,v24
vncipher $out5,$out5,v24
vncipher $out6,$out6,v24
vncipher $out7,$out7,v24
subfe. r0,r0,r0 # borrow?-1:0
vncipher $out0,$out0,v25
vncipher $out1,$out1,v25
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vncipher $out4,$out4,v25
vncipher $out5,$out5,v25
vncipher $out6,$out6,v25
vncipher $out7,$out7,v25
and r0,r0,$len
vncipher $out0,$out0,v26
vncipher $out1,$out1,v26
vncipher $out2,$out2,v26
vncipher $out3,$out3,v26
vncipher $out4,$out4,v26
vncipher $out5,$out5,v26
vncipher $out6,$out6,v26
vncipher $out7,$out7,v26
add $inp,$inp,r0 # $inp is adjusted in such
# way that at exit from the
# loop inX-in7 are loaded
# with last "words"
vncipher $out0,$out0,v27
vncipher $out1,$out1,v27
vncipher $out2,$out2,v27
vncipher $out3,$out3,v27
vncipher $out4,$out4,v27
vncipher $out5,$out5,v27
vncipher $out6,$out6,v27
vncipher $out7,$out7,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
vncipher $out0,$out0,v28
vncipher $out1,$out1,v28
vncipher $out2,$out2,v28
vncipher $out3,$out3,v28
vncipher $out4,$out4,v28
vncipher $out5,$out5,v28
vncipher $out6,$out6,v28
vncipher $out7,$out7,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
vncipher $out0,$out0,v29
vncipher $out1,$out1,v29
vncipher $out2,$out2,v29
vncipher $out3,$out3,v29
vncipher $out4,$out4,v29
vncipher $out5,$out5,v29
vncipher $out6,$out6,v29
vncipher $out7,$out7,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vncipher $out0,$out0,v30
vxor $ivec,$ivec,v31 # xor with last round key
vncipher $out1,$out1,v30
vxor $in0,$in0,v31
vncipher $out2,$out2,v30
vxor $in1,$in1,v31
vncipher $out3,$out3,v30
vxor $in2,$in2,v31
vncipher $out4,$out4,v30
vxor $in3,$in3,v31
vncipher $out5,$out5,v30
vxor $in4,$in4,v31
vncipher $out6,$out6,v30
vxor $in5,$in5,v31
vncipher $out7,$out7,v30
vxor $in6,$in6,v31
vncipherlast $out0,$out0,$ivec
vncipherlast $out1,$out1,$in0
lvx_u $in0,$x00,$inp # load next input block
vncipherlast $out2,$out2,$in1
lvx_u $in1,$x10,$inp
vncipherlast $out3,$out3,$in2
le?vperm $in0,$in0,$in0,$inpperm
lvx_u $in2,$x20,$inp
vncipherlast $out4,$out4,$in3
le?vperm $in1,$in1,$in1,$inpperm
lvx_u $in3,$x30,$inp
vncipherlast $out5,$out5,$in4
le?vperm $in2,$in2,$in2,$inpperm
lvx_u $in4,$x40,$inp
vncipherlast $out6,$out6,$in5
le?vperm $in3,$in3,$in3,$inpperm
lvx_u $in5,$x50,$inp
vncipherlast $out7,$out7,$in6
le?vperm $in4,$in4,$in4,$inpperm
lvx_u $in6,$x60,$inp
vmr $ivec,$in7
le?vperm $in5,$in5,$in5,$inpperm
lvx_u $in7,$x70,$inp
addi $inp,$inp,0x80
le?vperm $out0,$out0,$out0,$inpperm
le?vperm $out1,$out1,$out1,$inpperm
stvx_u $out0,$x00,$out
le?vperm $in6,$in6,$in6,$inpperm
vxor $out0,$in0,$rndkey0
le?vperm $out2,$out2,$out2,$inpperm
stvx_u $out1,$x10,$out
le?vperm $in7,$in7,$in7,$inpperm
vxor $out1,$in1,$rndkey0
le?vperm $out3,$out3,$out3,$inpperm
stvx_u $out2,$x20,$out
vxor $out2,$in2,$rndkey0
le?vperm $out4,$out4,$out4,$inpperm
stvx_u $out3,$x30,$out
vxor $out3,$in3,$rndkey0
le?vperm $out5,$out5,$out5,$inpperm
stvx_u $out4,$x40,$out
vxor $out4,$in4,$rndkey0
le?vperm $out6,$out6,$out6,$inpperm
stvx_u $out5,$x50,$out
vxor $out5,$in5,$rndkey0
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out6,$x60,$out
vxor $out6,$in6,$rndkey0
stvx_u $out7,$x70,$out
addi $out,$out,0x80
vxor $out7,$in7,$rndkey0
mtctr $rounds
beq Loop_cbc_dec8x # did $len-=128 borrow?
addic. $len,$len,128
beq Lcbc_dec8x_done
nop
nop
Loop_cbc_dec8x_tail: # up to 7 "words" tail...
vncipher $out1,$out1,v24
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
vncipher $out4,$out4,v24
vncipher $out5,$out5,v24
vncipher $out6,$out6,v24
vncipher $out7,$out7,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vncipher $out1,$out1,v25
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vncipher $out4,$out4,v25
vncipher $out5,$out5,v25
vncipher $out6,$out6,v25
vncipher $out7,$out7,v25
lvx v25,$x10,$key_ # round[4]
bdnz Loop_cbc_dec8x_tail
vncipher $out1,$out1,v24
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
vncipher $out4,$out4,v24
vncipher $out5,$out5,v24
vncipher $out6,$out6,v24
vncipher $out7,$out7,v24
vncipher $out1,$out1,v25
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vncipher $out4,$out4,v25
vncipher $out5,$out5,v25
vncipher $out6,$out6,v25
vncipher $out7,$out7,v25
vncipher $out1,$out1,v26
vncipher $out2,$out2,v26
vncipher $out3,$out3,v26
vncipher $out4,$out4,v26
vncipher $out5,$out5,v26
vncipher $out6,$out6,v26
vncipher $out7,$out7,v26
vncipher $out1,$out1,v27
vncipher $out2,$out2,v27
vncipher $out3,$out3,v27
vncipher $out4,$out4,v27
vncipher $out5,$out5,v27
vncipher $out6,$out6,v27
vncipher $out7,$out7,v27
vncipher $out1,$out1,v28
vncipher $out2,$out2,v28
vncipher $out3,$out3,v28
vncipher $out4,$out4,v28
vncipher $out5,$out5,v28
vncipher $out6,$out6,v28
vncipher $out7,$out7,v28
vncipher $out1,$out1,v29
vncipher $out2,$out2,v29
vncipher $out3,$out3,v29
vncipher $out4,$out4,v29
vncipher $out5,$out5,v29
vncipher $out6,$out6,v29
vncipher $out7,$out7,v29
vncipher $out1,$out1,v30
vxor $ivec,$ivec,v31 # last round key
vncipher $out2,$out2,v30
vxor $in1,$in1,v31
vncipher $out3,$out3,v30
vxor $in2,$in2,v31
vncipher $out4,$out4,v30
vxor $in3,$in3,v31
vncipher $out5,$out5,v30
vxor $in4,$in4,v31
vncipher $out6,$out6,v30
vxor $in5,$in5,v31
vncipher $out7,$out7,v30
vxor $in6,$in6,v31
cmplwi $len,32 # switch($len)
blt Lcbc_dec8x_one
nop
beq Lcbc_dec8x_two
cmplwi $len,64
blt Lcbc_dec8x_three
nop
beq Lcbc_dec8x_four
cmplwi $len,96
blt Lcbc_dec8x_five
nop
beq Lcbc_dec8x_six
Lcbc_dec8x_seven:
vncipherlast $out1,$out1,$ivec
vncipherlast $out2,$out2,$in1
vncipherlast $out3,$out3,$in2
vncipherlast $out4,$out4,$in3
vncipherlast $out5,$out5,$in4
vncipherlast $out6,$out6,$in5
vncipherlast $out7,$out7,$in6
vmr $ivec,$in7
le?vperm $out1,$out1,$out1,$inpperm
le?vperm $out2,$out2,$out2,$inpperm
stvx_u $out1,$x00,$out
le?vperm $out3,$out3,$out3,$inpperm
stvx_u $out2,$x10,$out
le?vperm $out4,$out4,$out4,$inpperm
stvx_u $out3,$x20,$out
le?vperm $out5,$out5,$out5,$inpperm
stvx_u $out4,$x30,$out
le?vperm $out6,$out6,$out6,$inpperm
stvx_u $out5,$x40,$out
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out6,$x50,$out
stvx_u $out7,$x60,$out
addi $out,$out,0x70
b Lcbc_dec8x_done
.align 5
Lcbc_dec8x_six:
vncipherlast $out2,$out2,$ivec
vncipherlast $out3,$out3,$in2
vncipherlast $out4,$out4,$in3
vncipherlast $out5,$out5,$in4
vncipherlast $out6,$out6,$in5
vncipherlast $out7,$out7,$in6
vmr $ivec,$in7
le?vperm $out2,$out2,$out2,$inpperm
le?vperm $out3,$out3,$out3,$inpperm
stvx_u $out2,$x00,$out
le?vperm $out4,$out4,$out4,$inpperm
stvx_u $out3,$x10,$out
le?vperm $out5,$out5,$out5,$inpperm
stvx_u $out4,$x20,$out
le?vperm $out6,$out6,$out6,$inpperm
stvx_u $out5,$x30,$out
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out6,$x40,$out
stvx_u $out7,$x50,$out
addi $out,$out,0x60
b Lcbc_dec8x_done
.align 5
Lcbc_dec8x_five:
vncipherlast $out3,$out3,$ivec
vncipherlast $out4,$out4,$in3
vncipherlast $out5,$out5,$in4
vncipherlast $out6,$out6,$in5
vncipherlast $out7,$out7,$in6
vmr $ivec,$in7
le?vperm $out3,$out3,$out3,$inpperm
le?vperm $out4,$out4,$out4,$inpperm
stvx_u $out3,$x00,$out
le?vperm $out5,$out5,$out5,$inpperm
stvx_u $out4,$x10,$out
le?vperm $out6,$out6,$out6,$inpperm
stvx_u $out5,$x20,$out
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out6,$x30,$out
stvx_u $out7,$x40,$out
addi $out,$out,0x50
b Lcbc_dec8x_done
.align 5
Lcbc_dec8x_four:
vncipherlast $out4,$out4,$ivec
vncipherlast $out5,$out5,$in4
vncipherlast $out6,$out6,$in5
vncipherlast $out7,$out7,$in6
vmr $ivec,$in7
le?vperm $out4,$out4,$out4,$inpperm
le?vperm $out5,$out5,$out5,$inpperm
stvx_u $out4,$x00,$out
le?vperm $out6,$out6,$out6,$inpperm
stvx_u $out5,$x10,$out
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out6,$x20,$out
stvx_u $out7,$x30,$out
addi $out,$out,0x40
b Lcbc_dec8x_done
.align 5
Lcbc_dec8x_three:
vncipherlast $out5,$out5,$ivec
vncipherlast $out6,$out6,$in5
vncipherlast $out7,$out7,$in6
vmr $ivec,$in7
le?vperm $out5,$out5,$out5,$inpperm
le?vperm $out6,$out6,$out6,$inpperm
stvx_u $out5,$x00,$out
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out6,$x10,$out
stvx_u $out7,$x20,$out
addi $out,$out,0x30
b Lcbc_dec8x_done
.align 5
Lcbc_dec8x_two:
vncipherlast $out6,$out6,$ivec
vncipherlast $out7,$out7,$in6
vmr $ivec,$in7
le?vperm $out6,$out6,$out6,$inpperm
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out6,$x00,$out
stvx_u $out7,$x10,$out
addi $out,$out,0x20
b Lcbc_dec8x_done
.align 5
Lcbc_dec8x_one:
vncipherlast $out7,$out7,$ivec
vmr $ivec,$in7
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out7,0,$out
addi $out,$out,0x10
Lcbc_dec8x_done:
le?vperm $ivec,$ivec,$ivec,$inpperm
stvx_u $ivec,0,$ivp # write [unaligned] iv
li r10,`$FRAME+15`
li r11,`$FRAME+31`
stvx $inpperm,r10,$sp # wipe copies of round keys
addi r10,r10,32
stvx $inpperm,r11,$sp
addi r11,r11,32
stvx $inpperm,r10,$sp
addi r10,r10,32
stvx $inpperm,r11,$sp
addi r11,r11,32
stvx $inpperm,r10,$sp
addi r10,r10,32
stvx $inpperm,r11,$sp
addi r11,r11,32
stvx $inpperm,r10,$sp
addi r10,r10,32
stvx $inpperm,r11,$sp
addi r11,r11,32
mtspr 256,$vrsave
lvx v20,r10,$sp # ABI says so
addi r10,r10,32
lvx v21,r11,$sp
addi r11,r11,32
lvx v22,r10,$sp
addi r10,r10,32
lvx v23,r11,$sp
addi r11,r11,32
lvx v24,r10,$sp
addi r10,r10,32
lvx v25,r11,$sp
addi r11,r11,32
lvx v26,r10,$sp
addi r10,r10,32
lvx v27,r11,$sp
addi r11,r11,32
lvx v28,r10,$sp
addi r10,r10,32
lvx v29,r11,$sp
addi r11,r11,32
lvx v30,r10,$sp
lvx v31,r11,$sp
$POP r26,`$FRAME+21*16+0*$SIZE_T`($sp)
$POP r27,`$FRAME+21*16+1*$SIZE_T`($sp)
$POP r28,`$FRAME+21*16+2*$SIZE_T`($sp)
$POP r29,`$FRAME+21*16+3*$SIZE_T`($sp)
$POP r30,`$FRAME+21*16+4*$SIZE_T`($sp)
$POP r31,`$FRAME+21*16+5*$SIZE_T`($sp)
addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T`
blr
.long 0
.byte 0,12,0x04,0,0x80,6,6,0
.long 0
.size .${prefix}_cbc_encrypt,.-.${prefix}_cbc_encrypt
___
}} }}}
#########################################################################
{{{ # CTR procedure[s] #
my ($inp,$out,$len,$key,$ivp,$x10,$rounds,$idx)=map("r$_",(3..10));
my ($rndkey0,$rndkey1,$inout,$tmp)= map("v$_",(0..3));
my ($ivec,$inptail,$inpperm,$outhead,$outperm,$outmask,$keyperm,$one)=
map("v$_",(4..11));
my $dat=$tmp;
$code.=<<___;
.globl .${prefix}_ctr32_encrypt_blocks
.align 5
.${prefix}_ctr32_encrypt_blocks:
${UCMP}i $len,1
bltlr-
lis r0,0xfff0
mfspr $vrsave,256
mtspr 256,r0
li $idx,15
vxor $rndkey0,$rndkey0,$rndkey0
le?vspltisb $tmp,0x0f
lvx $ivec,0,$ivp # load [unaligned] iv
lvsl $inpperm,0,$ivp
lvx $inptail,$idx,$ivp
vspltisb $one,1
le?vxor $inpperm,$inpperm,$tmp
vperm $ivec,$ivec,$inptail,$inpperm
vsldoi $one,$rndkey0,$one,1
neg r11,$inp
?lvsl $keyperm,0,$key # prepare for unaligned key
lwz $rounds,240($key)
lvsr $inpperm,0,r11 # prepare for unaligned load
lvx $inptail,0,$inp
addi $inp,$inp,15 # 15 is not typo
le?vxor $inpperm,$inpperm,$tmp
srwi $rounds,$rounds,1
li $idx,16
subi $rounds,$rounds,1
${UCMP}i $len,8
bge _aesp8_ctr32_encrypt8x
?lvsr $outperm,0,$out # prepare for unaligned store
vspltisb $outmask,-1
lvx $outhead,0,$out
?vperm $outmask,$rndkey0,$outmask,$outperm
le?vxor $outperm,$outperm,$tmp
lvx $rndkey0,0,$key
mtctr $rounds
lvx $rndkey1,$idx,$key
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $inout,$ivec,$rndkey0
lvx $rndkey0,$idx,$key
addi $idx,$idx,16
b Loop_ctr32_enc
.align 5
Loop_ctr32_enc:
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vcipher $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key
addi $idx,$idx,16
bdnz Loop_ctr32_enc
vadduwm $ivec,$ivec,$one
vmr $dat,$inptail
lvx $inptail,0,$inp
addi $inp,$inp,16
subic. $len,$len,1 # blocks--
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key
vperm $dat,$dat,$inptail,$inpperm
li $idx,16
?vperm $rndkey1,$rndkey0,$rndkey1,$keyperm
lvx $rndkey0,0,$key
vxor $dat,$dat,$rndkey1 # last round key
vcipherlast $inout,$inout,$dat
lvx $rndkey1,$idx,$key
addi $idx,$idx,16
vperm $inout,$inout,$inout,$outperm
vsel $dat,$outhead,$inout,$outmask
mtctr $rounds
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vmr $outhead,$inout
vxor $inout,$ivec,$rndkey0
lvx $rndkey0,$idx,$key
addi $idx,$idx,16
stvx $dat,0,$out
addi $out,$out,16
bne Loop_ctr32_enc
addi $out,$out,-1
lvx $inout,0,$out # redundant in aligned case
vsel $inout,$outhead,$inout,$outmask
stvx $inout,0,$out
mtspr 256,$vrsave
blr
.long 0
.byte 0,12,0x14,0,0,0,6,0
.long 0
___
#########################################################################
{{ # Optimized CTR procedure #
my $key_="r11";
my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,8,26..31));
$x00=0 if ($flavour =~ /osx/);
my ($in0, $in1, $in2, $in3, $in4, $in5, $in6, $in7 )=map("v$_",(0..3,10,12..14));
my ($out0,$out1,$out2,$out3,$out4,$out5,$out6,$out7)=map("v$_",(15..22));
my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys
# v26-v31 last 6 round keys
my ($tmp,$keyperm)=($in3,$in4); # aliases with "caller", redundant assignment
my ($two,$three,$four)=($outhead,$outperm,$outmask);
$code.=<<___;
.align 5
_aesp8_ctr32_encrypt8x:
$STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp)
li r10,`$FRAME+8*16+15`
li r11,`$FRAME+8*16+31`
stvx v20,r10,$sp # ABI says so
addi r10,r10,32
stvx v21,r11,$sp
addi r11,r11,32
stvx v22,r10,$sp
addi r10,r10,32
stvx v23,r11,$sp
addi r11,r11,32
stvx v24,r10,$sp
addi r10,r10,32
stvx v25,r11,$sp
addi r11,r11,32
stvx v26,r10,$sp
addi r10,r10,32
stvx v27,r11,$sp
addi r11,r11,32
stvx v28,r10,$sp
addi r10,r10,32
stvx v29,r11,$sp
addi r11,r11,32
stvx v30,r10,$sp
stvx v31,r11,$sp
li r0,-1
stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave
li $x10,0x10
$PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp)
li $x20,0x20
$PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp)
li $x30,0x30
$PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp)
li $x40,0x40
$PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp)
li $x50,0x50
$PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp)
li $x60,0x60
$PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp)
li $x70,0x70
mtspr 256,r0
subi $rounds,$rounds,3 # -4 in total
lvx $rndkey0,$x00,$key # load key schedule
lvx v30,$x10,$key
addi $key,$key,0x20
lvx v31,$x00,$key
?vperm $rndkey0,$rndkey0,v30,$keyperm
addi $key_,$sp,$FRAME+15
mtctr $rounds
Load_ctr32_enc_key:
?vperm v24,v30,v31,$keyperm
lvx v30,$x10,$key
addi $key,$key,0x20
stvx v24,$x00,$key_ # off-load round[1]
?vperm v25,v31,v30,$keyperm
lvx v31,$x00,$key
stvx v25,$x10,$key_ # off-load round[2]
addi $key_,$key_,0x20
bdnz Load_ctr32_enc_key
lvx v26,$x10,$key
?vperm v24,v30,v31,$keyperm
lvx v27,$x20,$key
stvx v24,$x00,$key_ # off-load round[3]
?vperm v25,v31,v26,$keyperm
lvx v28,$x30,$key
stvx v25,$x10,$key_ # off-load round[4]
addi $key_,$sp,$FRAME+15 # rewind $key_
?vperm v26,v26,v27,$keyperm
lvx v29,$x40,$key
?vperm v27,v27,v28,$keyperm
lvx v30,$x50,$key
?vperm v28,v28,v29,$keyperm
lvx v31,$x60,$key
?vperm v29,v29,v30,$keyperm
lvx $out0,$x70,$key # borrow $out0
?vperm v30,v30,v31,$keyperm
lvx v24,$x00,$key_ # pre-load round[1]
?vperm v31,v31,$out0,$keyperm
lvx v25,$x10,$key_ # pre-load round[2]
vadduwm $two,$one,$one
subi $inp,$inp,15 # undo "caller"
$SHL $len,$len,4
vadduwm $out1,$ivec,$one # counter values ...
vadduwm $out2,$ivec,$two
vxor $out0,$ivec,$rndkey0 # ... xored with rndkey[0]
le?li $idx,8
vadduwm $out3,$out1,$two
vxor $out1,$out1,$rndkey0
le?lvsl $inpperm,0,$idx
vadduwm $out4,$out2,$two
vxor $out2,$out2,$rndkey0
le?vspltisb $tmp,0x0f
vadduwm $out5,$out3,$two
vxor $out3,$out3,$rndkey0
le?vxor $inpperm,$inpperm,$tmp # transform for lvx_u/stvx_u
vadduwm $out6,$out4,$two
vxor $out4,$out4,$rndkey0
vadduwm $out7,$out5,$two
vxor $out5,$out5,$rndkey0
vadduwm $ivec,$out6,$two # next counter value
vxor $out6,$out6,$rndkey0
vxor $out7,$out7,$rndkey0
mtctr $rounds
b Loop_ctr32_enc8x
.align 5
Loop_ctr32_enc8x:
vcipher $out0,$out0,v24
vcipher $out1,$out1,v24
vcipher $out2,$out2,v24
vcipher $out3,$out3,v24
vcipher $out4,$out4,v24
vcipher $out5,$out5,v24
vcipher $out6,$out6,v24
vcipher $out7,$out7,v24
Loop_ctr32_enc8x_middle:
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vcipher $out0,$out0,v25
vcipher $out1,$out1,v25
vcipher $out2,$out2,v25
vcipher $out3,$out3,v25
vcipher $out4,$out4,v25
vcipher $out5,$out5,v25
vcipher $out6,$out6,v25
vcipher $out7,$out7,v25
lvx v25,$x10,$key_ # round[4]
bdnz Loop_ctr32_enc8x
subic r11,$len,256 # $len-256, borrow $key_
vcipher $out0,$out0,v24
vcipher $out1,$out1,v24
vcipher $out2,$out2,v24
vcipher $out3,$out3,v24
vcipher $out4,$out4,v24
vcipher $out5,$out5,v24
vcipher $out6,$out6,v24
vcipher $out7,$out7,v24
subfe r0,r0,r0 # borrow?-1:0
vcipher $out0,$out0,v25
vcipher $out1,$out1,v25
vcipher $out2,$out2,v25
vcipher $out3,$out3,v25
vcipher $out4,$out4,v25
vcipher $out5,$out5,v25
vcipher $out6,$out6,v25
vcipher $out7,$out7,v25
and r0,r0,r11
addi $key_,$sp,$FRAME+15 # rewind $key_
vcipher $out0,$out0,v26
vcipher $out1,$out1,v26
vcipher $out2,$out2,v26
vcipher $out3,$out3,v26
vcipher $out4,$out4,v26
vcipher $out5,$out5,v26
vcipher $out6,$out6,v26
vcipher $out7,$out7,v26
lvx v24,$x00,$key_ # re-pre-load round[1]
subic $len,$len,129 # $len-=129
vcipher $out0,$out0,v27
addi $len,$len,1 # $len-=128 really
vcipher $out1,$out1,v27
vcipher $out2,$out2,v27
vcipher $out3,$out3,v27
vcipher $out4,$out4,v27
vcipher $out5,$out5,v27
vcipher $out6,$out6,v27
vcipher $out7,$out7,v27
lvx v25,$x10,$key_ # re-pre-load round[2]
vcipher $out0,$out0,v28
lvx_u $in0,$x00,$inp # load input
vcipher $out1,$out1,v28
lvx_u $in1,$x10,$inp
vcipher $out2,$out2,v28
lvx_u $in2,$x20,$inp
vcipher $out3,$out3,v28
lvx_u $in3,$x30,$inp
vcipher $out4,$out4,v28
lvx_u $in4,$x40,$inp
vcipher $out5,$out5,v28
lvx_u $in5,$x50,$inp
vcipher $out6,$out6,v28
lvx_u $in6,$x60,$inp
vcipher $out7,$out7,v28
lvx_u $in7,$x70,$inp
addi $inp,$inp,0x80
vcipher $out0,$out0,v29
le?vperm $in0,$in0,$in0,$inpperm
vcipher $out1,$out1,v29
le?vperm $in1,$in1,$in1,$inpperm
vcipher $out2,$out2,v29
le?vperm $in2,$in2,$in2,$inpperm
vcipher $out3,$out3,v29
le?vperm $in3,$in3,$in3,$inpperm
vcipher $out4,$out4,v29
le?vperm $in4,$in4,$in4,$inpperm
vcipher $out5,$out5,v29
le?vperm $in5,$in5,$in5,$inpperm
vcipher $out6,$out6,v29
le?vperm $in6,$in6,$in6,$inpperm
vcipher $out7,$out7,v29
le?vperm $in7,$in7,$in7,$inpperm
add $inp,$inp,r0 # $inp is adjusted in such
# way that at exit from the
# loop inX-in7 are loaded
# with last "words"
subfe. r0,r0,r0 # borrow?-1:0
vcipher $out0,$out0,v30
vxor $in0,$in0,v31 # xor with last round key
vcipher $out1,$out1,v30
vxor $in1,$in1,v31
vcipher $out2,$out2,v30
vxor $in2,$in2,v31
vcipher $out3,$out3,v30
vxor $in3,$in3,v31
vcipher $out4,$out4,v30
vxor $in4,$in4,v31
vcipher $out5,$out5,v30
vxor $in5,$in5,v31
vcipher $out6,$out6,v30
vxor $in6,$in6,v31
vcipher $out7,$out7,v30
vxor $in7,$in7,v31
bne Lctr32_enc8x_break # did $len-129 borrow?
vcipherlast $in0,$out0,$in0
vcipherlast $in1,$out1,$in1
vadduwm $out1,$ivec,$one # counter values ...
vcipherlast $in2,$out2,$in2
vadduwm $out2,$ivec,$two
vxor $out0,$ivec,$rndkey0 # ... xored with rndkey[0]
vcipherlast $in3,$out3,$in3
vadduwm $out3,$out1,$two
vxor $out1,$out1,$rndkey0
vcipherlast $in4,$out4,$in4
vadduwm $out4,$out2,$two
vxor $out2,$out2,$rndkey0
vcipherlast $in5,$out5,$in5
vadduwm $out5,$out3,$two
vxor $out3,$out3,$rndkey0
vcipherlast $in6,$out6,$in6
vadduwm $out6,$out4,$two
vxor $out4,$out4,$rndkey0
vcipherlast $in7,$out7,$in7
vadduwm $out7,$out5,$two
vxor $out5,$out5,$rndkey0
le?vperm $in0,$in0,$in0,$inpperm
vadduwm $ivec,$out6,$two # next counter value
vxor $out6,$out6,$rndkey0
le?vperm $in1,$in1,$in1,$inpperm
vxor $out7,$out7,$rndkey0
mtctr $rounds
vcipher $out0,$out0,v24
stvx_u $in0,$x00,$out
le?vperm $in2,$in2,$in2,$inpperm
vcipher $out1,$out1,v24
stvx_u $in1,$x10,$out
le?vperm $in3,$in3,$in3,$inpperm
vcipher $out2,$out2,v24
stvx_u $in2,$x20,$out
le?vperm $in4,$in4,$in4,$inpperm
vcipher $out3,$out3,v24
stvx_u $in3,$x30,$out
le?vperm $in5,$in5,$in5,$inpperm
vcipher $out4,$out4,v24
stvx_u $in4,$x40,$out
le?vperm $in6,$in6,$in6,$inpperm
vcipher $out5,$out5,v24
stvx_u $in5,$x50,$out
le?vperm $in7,$in7,$in7,$inpperm
vcipher $out6,$out6,v24
stvx_u $in6,$x60,$out
vcipher $out7,$out7,v24
stvx_u $in7,$x70,$out
addi $out,$out,0x80
b Loop_ctr32_enc8x_middle
.align 5
Lctr32_enc8x_break:
cmpwi $len,-0x60
blt Lctr32_enc8x_one
nop
beq Lctr32_enc8x_two
cmpwi $len,-0x40
blt Lctr32_enc8x_three
nop
beq Lctr32_enc8x_four
cmpwi $len,-0x20
blt Lctr32_enc8x_five
nop
beq Lctr32_enc8x_six
cmpwi $len,0x00
blt Lctr32_enc8x_seven
Lctr32_enc8x_eight:
vcipherlast $out0,$out0,$in0
vcipherlast $out1,$out1,$in1
vcipherlast $out2,$out2,$in2
vcipherlast $out3,$out3,$in3
vcipherlast $out4,$out4,$in4
vcipherlast $out5,$out5,$in5
vcipherlast $out6,$out6,$in6
vcipherlast $out7,$out7,$in7
le?vperm $out0,$out0,$out0,$inpperm
le?vperm $out1,$out1,$out1,$inpperm
stvx_u $out0,$x00,$out
le?vperm $out2,$out2,$out2,$inpperm
stvx_u $out1,$x10,$out
le?vperm $out3,$out3,$out3,$inpperm
stvx_u $out2,$x20,$out
le?vperm $out4,$out4,$out4,$inpperm
stvx_u $out3,$x30,$out
le?vperm $out5,$out5,$out5,$inpperm
stvx_u $out4,$x40,$out
le?vperm $out6,$out6,$out6,$inpperm
stvx_u $out5,$x50,$out
le?vperm $out7,$out7,$out7,$inpperm
stvx_u $out6,$x60,$out
stvx_u $out7,$x70,$out
addi $out,$out,0x80
b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_seven:
vcipherlast $out0,$out0,$in1
vcipherlast $out1,$out1,$in2
vcipherlast $out2,$out2,$in3
vcipherlast $out3,$out3,$in4
vcipherlast $out4,$out4,$in5
vcipherlast $out5,$out5,$in6
vcipherlast $out6,$out6,$in7
le?vperm $out0,$out0,$out0,$inpperm
le?vperm $out1,$out1,$out1,$inpperm
stvx_u $out0,$x00,$out
le?vperm $out2,$out2,$out2,$inpperm
stvx_u $out1,$x10,$out
le?vperm $out3,$out3,$out3,$inpperm
stvx_u $out2,$x20,$out
le?vperm $out4,$out4,$out4,$inpperm
stvx_u $out3,$x30,$out
le?vperm $out5,$out5,$out5,$inpperm
stvx_u $out4,$x40,$out
le?vperm $out6,$out6,$out6,$inpperm
stvx_u $out5,$x50,$out
stvx_u $out6,$x60,$out
addi $out,$out,0x70
b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_six:
vcipherlast $out0,$out0,$in2
vcipherlast $out1,$out1,$in3
vcipherlast $out2,$out2,$in4
vcipherlast $out3,$out3,$in5
vcipherlast $out4,$out4,$in6
vcipherlast $out5,$out5,$in7
le?vperm $out0,$out0,$out0,$inpperm
le?vperm $out1,$out1,$out1,$inpperm
stvx_u $out0,$x00,$out
le?vperm $out2,$out2,$out2,$inpperm
stvx_u $out1,$x10,$out
le?vperm $out3,$out3,$out3,$inpperm
stvx_u $out2,$x20,$out
le?vperm $out4,$out4,$out4,$inpperm
stvx_u $out3,$x30,$out
le?vperm $out5,$out5,$out5,$inpperm
stvx_u $out4,$x40,$out
stvx_u $out5,$x50,$out
addi $out,$out,0x60
b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_five:
vcipherlast $out0,$out0,$in3
vcipherlast $out1,$out1,$in4
vcipherlast $out2,$out2,$in5
vcipherlast $out3,$out3,$in6
vcipherlast $out4,$out4,$in7
le?vperm $out0,$out0,$out0,$inpperm
le?vperm $out1,$out1,$out1,$inpperm
stvx_u $out0,$x00,$out
le?vperm $out2,$out2,$out2,$inpperm
stvx_u $out1,$x10,$out
le?vperm $out3,$out3,$out3,$inpperm
stvx_u $out2,$x20,$out
le?vperm $out4,$out4,$out4,$inpperm
stvx_u $out3,$x30,$out
stvx_u $out4,$x40,$out
addi $out,$out,0x50
b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_four:
vcipherlast $out0,$out0,$in4
vcipherlast $out1,$out1,$in5
vcipherlast $out2,$out2,$in6
vcipherlast $out3,$out3,$in7
le?vperm $out0,$out0,$out0,$inpperm
le?vperm $out1,$out1,$out1,$inpperm
stvx_u $out0,$x00,$out
le?vperm $out2,$out2,$out2,$inpperm
stvx_u $out1,$x10,$out
le?vperm $out3,$out3,$out3,$inpperm
stvx_u $out2,$x20,$out
stvx_u $out3,$x30,$out
addi $out,$out,0x40
b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_three:
vcipherlast $out0,$out0,$in5
vcipherlast $out1,$out1,$in6
vcipherlast $out2,$out2,$in7
le?vperm $out0,$out0,$out0,$inpperm
le?vperm $out1,$out1,$out1,$inpperm
stvx_u $out0,$x00,$out
le?vperm $out2,$out2,$out2,$inpperm
stvx_u $out1,$x10,$out
stvx_u $out2,$x20,$out
addi $out,$out,0x30
- b Lcbc_dec8x_done
+ b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_two:
vcipherlast $out0,$out0,$in6
vcipherlast $out1,$out1,$in7
le?vperm $out0,$out0,$out0,$inpperm
le?vperm $out1,$out1,$out1,$inpperm
stvx_u $out0,$x00,$out
stvx_u $out1,$x10,$out
addi $out,$out,0x20
- b Lcbc_dec8x_done
+ b Lctr32_enc8x_done
.align 5
Lctr32_enc8x_one:
vcipherlast $out0,$out0,$in7
le?vperm $out0,$out0,$out0,$inpperm
stvx_u $out0,0,$out
addi $out,$out,0x10
Lctr32_enc8x_done:
li r10,`$FRAME+15`
li r11,`$FRAME+31`
stvx $inpperm,r10,$sp # wipe copies of round keys
addi r10,r10,32
stvx $inpperm,r11,$sp
addi r11,r11,32
stvx $inpperm,r10,$sp
addi r10,r10,32
stvx $inpperm,r11,$sp
addi r11,r11,32
stvx $inpperm,r10,$sp
addi r10,r10,32
stvx $inpperm,r11,$sp
addi r11,r11,32
stvx $inpperm,r10,$sp
addi r10,r10,32
stvx $inpperm,r11,$sp
addi r11,r11,32
mtspr 256,$vrsave
lvx v20,r10,$sp # ABI says so
addi r10,r10,32
lvx v21,r11,$sp
addi r11,r11,32
lvx v22,r10,$sp
addi r10,r10,32
lvx v23,r11,$sp
addi r11,r11,32
lvx v24,r10,$sp
addi r10,r10,32
lvx v25,r11,$sp
addi r11,r11,32
lvx v26,r10,$sp
addi r10,r10,32
lvx v27,r11,$sp
addi r11,r11,32
lvx v28,r10,$sp
addi r10,r10,32
lvx v29,r11,$sp
addi r11,r11,32
lvx v30,r10,$sp
lvx v31,r11,$sp
$POP r26,`$FRAME+21*16+0*$SIZE_T`($sp)
$POP r27,`$FRAME+21*16+1*$SIZE_T`($sp)
$POP r28,`$FRAME+21*16+2*$SIZE_T`($sp)
$POP r29,`$FRAME+21*16+3*$SIZE_T`($sp)
$POP r30,`$FRAME+21*16+4*$SIZE_T`($sp)
$POP r31,`$FRAME+21*16+5*$SIZE_T`($sp)
addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T`
blr
.long 0
.byte 0,12,0x04,0,0x80,6,6,0
.long 0
.size .${prefix}_ctr32_encrypt_blocks,.-.${prefix}_ctr32_encrypt_blocks
___
}} }}}
#########################################################################
{{{ # XTS procedures #
# int aes_p8_xts_[en|de]crypt(const char *inp, char *out, size_t len, #
# const AES_KEY *key1, const AES_KEY *key2, #
# [const] unsigned char iv[16]); #
# If $key2 is NULL, then a "tweak chaining" mode is engaged, in which #
# input tweak value is assumed to be encrypted already, and last tweak #
# value, one suitable for consecutive call on same chunk of data, is #
# written back to original buffer. In addition, in "tweak chaining" #
# mode only complete input blocks are processed. #
my ($inp,$out,$len,$key1,$key2,$ivp,$rounds,$idx) = map("r$_",(3..10));
my ($rndkey0,$rndkey1,$inout) = map("v$_",(0..2));
my ($output,$inptail,$inpperm,$leperm,$keyperm) = map("v$_",(3..7));
my ($tweak,$seven,$eighty7,$tmp,$tweak1) = map("v$_",(8..12));
my $taillen = $key2;
($inp,$idx) = ($idx,$inp); # reassign
$code.=<<___;
.globl .${prefix}_xts_encrypt
.align 5
.${prefix}_xts_encrypt:
mr $inp,r3 # reassign
li r3,-1
${UCMP}i $len,16
bltlr-
lis r0,0xfff0
mfspr r12,256 # save vrsave
li r11,0
mtspr 256,r0
vspltisb $seven,0x07 # 0x070707..07
le?lvsl $leperm,r11,r11
le?vspltisb $tmp,0x0f
le?vxor $leperm,$leperm,$seven
li $idx,15
lvx $tweak,0,$ivp # load [unaligned] iv
lvsl $inpperm,0,$ivp
lvx $inptail,$idx,$ivp
le?vxor $inpperm,$inpperm,$tmp
vperm $tweak,$tweak,$inptail,$inpperm
neg r11,$inp
lvsr $inpperm,0,r11 # prepare for unaligned load
lvx $inout,0,$inp
addi $inp,$inp,15 # 15 is not typo
le?vxor $inpperm,$inpperm,$tmp
${UCMP}i $key2,0 # key2==NULL?
beq Lxts_enc_no_key2
?lvsl $keyperm,0,$key2 # prepare for unaligned key
lwz $rounds,240($key2)
srwi $rounds,$rounds,1
subi $rounds,$rounds,1
li $idx,16
lvx $rndkey0,0,$key2
lvx $rndkey1,$idx,$key2
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $tweak,$tweak,$rndkey0
lvx $rndkey0,$idx,$key2
addi $idx,$idx,16
mtctr $rounds
Ltweak_xts_enc:
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $tweak,$tweak,$rndkey1
lvx $rndkey1,$idx,$key2
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vcipher $tweak,$tweak,$rndkey0
lvx $rndkey0,$idx,$key2
addi $idx,$idx,16
bdnz Ltweak_xts_enc
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $tweak,$tweak,$rndkey1
lvx $rndkey1,$idx,$key2
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vcipherlast $tweak,$tweak,$rndkey0
li $ivp,0 # don't chain the tweak
b Lxts_enc
Lxts_enc_no_key2:
li $idx,-16
and $len,$len,$idx # in "tweak chaining"
# mode only complete
# blocks are processed
Lxts_enc:
lvx $inptail,0,$inp
addi $inp,$inp,16
?lvsl $keyperm,0,$key1 # prepare for unaligned key
lwz $rounds,240($key1)
srwi $rounds,$rounds,1
subi $rounds,$rounds,1
li $idx,16
vslb $eighty7,$seven,$seven # 0x808080..80
vor $eighty7,$eighty7,$seven # 0x878787..87
vspltisb $tmp,1 # 0x010101..01
vsldoi $eighty7,$eighty7,$tmp,15 # 0x870101..01
${UCMP}i $len,96
bge _aesp8_xts_encrypt6x
andi. $taillen,$len,15
subic r0,$len,32
subi $taillen,$taillen,16
subfe r0,r0,r0
and r0,r0,$taillen
add $inp,$inp,r0
lvx $rndkey0,0,$key1
lvx $rndkey1,$idx,$key1
addi $idx,$idx,16
vperm $inout,$inout,$inptail,$inpperm
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $inout,$inout,$tweak
vxor $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key1
addi $idx,$idx,16
mtctr $rounds
b Loop_xts_enc
.align 5
Loop_xts_enc:
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key1
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vcipher $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key1
addi $idx,$idx,16
bdnz Loop_xts_enc
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key1
li $idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $rndkey0,$rndkey0,$tweak
vcipherlast $output,$inout,$rndkey0
le?vperm $tmp,$output,$output,$leperm
be?nop
le?stvx_u $tmp,0,$out
be?stvx_u $output,0,$out
addi $out,$out,16
subic. $len,$len,16
beq Lxts_enc_done
vmr $inout,$inptail
lvx $inptail,0,$inp
addi $inp,$inp,16
lvx $rndkey0,0,$key1
lvx $rndkey1,$idx,$key1
addi $idx,$idx,16
subic r0,$len,32
subfe r0,r0,r0
and r0,r0,$taillen
add $inp,$inp,r0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $tweak,$tweak,$tmp
vperm $inout,$inout,$inptail,$inpperm
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $inout,$inout,$tweak
vxor $output,$output,$rndkey0 # just in case $len<16
vxor $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key1
addi $idx,$idx,16
mtctr $rounds
${UCMP}i $len,16
bge Loop_xts_enc
vxor $output,$output,$tweak
lvsr $inpperm,0,$len # $inpperm is no longer needed
vxor $inptail,$inptail,$inptail # $inptail is no longer needed
vspltisb $tmp,-1
vperm $inptail,$inptail,$tmp,$inpperm
vsel $inout,$inout,$output,$inptail
subi r11,$out,17
subi $out,$out,16
mtctr $len
li $len,16
Loop_xts_enc_steal:
lbzu r0,1(r11)
stb r0,16(r11)
bdnz Loop_xts_enc_steal
mtctr $rounds
b Loop_xts_enc # one more time...
Lxts_enc_done:
${UCMP}i $ivp,0
beq Lxts_enc_ret
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $tweak,$tweak,$tmp
le?vperm $tweak,$tweak,$tweak,$leperm
stvx_u $tweak,0,$ivp
Lxts_enc_ret:
mtspr 256,r12 # restore vrsave
li r3,0
blr
.long 0
.byte 0,12,0x04,0,0x80,6,6,0
.long 0
.size .${prefix}_xts_encrypt,.-.${prefix}_xts_encrypt
.globl .${prefix}_xts_decrypt
.align 5
.${prefix}_xts_decrypt:
mr $inp,r3 # reassign
li r3,-1
${UCMP}i $len,16
bltlr-
lis r0,0xfff8
mfspr r12,256 # save vrsave
li r11,0
mtspr 256,r0
andi. r0,$len,15
neg r0,r0
andi. r0,r0,16
sub $len,$len,r0
vspltisb $seven,0x07 # 0x070707..07
le?lvsl $leperm,r11,r11
le?vspltisb $tmp,0x0f
le?vxor $leperm,$leperm,$seven
li $idx,15
lvx $tweak,0,$ivp # load [unaligned] iv
lvsl $inpperm,0,$ivp
lvx $inptail,$idx,$ivp
le?vxor $inpperm,$inpperm,$tmp
vperm $tweak,$tweak,$inptail,$inpperm
neg r11,$inp
lvsr $inpperm,0,r11 # prepare for unaligned load
lvx $inout,0,$inp
addi $inp,$inp,15 # 15 is not typo
le?vxor $inpperm,$inpperm,$tmp
${UCMP}i $key2,0 # key2==NULL?
beq Lxts_dec_no_key2
?lvsl $keyperm,0,$key2 # prepare for unaligned key
lwz $rounds,240($key2)
srwi $rounds,$rounds,1
subi $rounds,$rounds,1
li $idx,16
lvx $rndkey0,0,$key2
lvx $rndkey1,$idx,$key2
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $tweak,$tweak,$rndkey0
lvx $rndkey0,$idx,$key2
addi $idx,$idx,16
mtctr $rounds
Ltweak_xts_dec:
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $tweak,$tweak,$rndkey1
lvx $rndkey1,$idx,$key2
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vcipher $tweak,$tweak,$rndkey0
lvx $rndkey0,$idx,$key2
addi $idx,$idx,16
bdnz Ltweak_xts_dec
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vcipher $tweak,$tweak,$rndkey1
lvx $rndkey1,$idx,$key2
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vcipherlast $tweak,$tweak,$rndkey0
li $ivp,0 # don't chain the tweak
b Lxts_dec
Lxts_dec_no_key2:
neg $idx,$len
andi. $idx,$idx,15
add $len,$len,$idx # in "tweak chaining"
# mode only complete
# blocks are processed
Lxts_dec:
lvx $inptail,0,$inp
addi $inp,$inp,16
?lvsl $keyperm,0,$key1 # prepare for unaligned key
lwz $rounds,240($key1)
srwi $rounds,$rounds,1
subi $rounds,$rounds,1
li $idx,16
vslb $eighty7,$seven,$seven # 0x808080..80
vor $eighty7,$eighty7,$seven # 0x878787..87
vspltisb $tmp,1 # 0x010101..01
vsldoi $eighty7,$eighty7,$tmp,15 # 0x870101..01
${UCMP}i $len,96
bge _aesp8_xts_decrypt6x
lvx $rndkey0,0,$key1
lvx $rndkey1,$idx,$key1
addi $idx,$idx,16
vperm $inout,$inout,$inptail,$inpperm
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $inout,$inout,$tweak
vxor $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key1
addi $idx,$idx,16
mtctr $rounds
${UCMP}i $len,16
blt Ltail_xts_dec
be?b Loop_xts_dec
.align 5
Loop_xts_dec:
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vncipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key1
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vncipher $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key1
addi $idx,$idx,16
bdnz Loop_xts_dec
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vncipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key1
li $idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $rndkey0,$rndkey0,$tweak
vncipherlast $output,$inout,$rndkey0
le?vperm $tmp,$output,$output,$leperm
be?nop
le?stvx_u $tmp,0,$out
be?stvx_u $output,0,$out
addi $out,$out,16
subic. $len,$len,16
beq Lxts_dec_done
vmr $inout,$inptail
lvx $inptail,0,$inp
addi $inp,$inp,16
lvx $rndkey0,0,$key1
lvx $rndkey1,$idx,$key1
addi $idx,$idx,16
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $tweak,$tweak,$tmp
vperm $inout,$inout,$inptail,$inpperm
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $inout,$inout,$tweak
vxor $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key1
addi $idx,$idx,16
mtctr $rounds
${UCMP}i $len,16
bge Loop_xts_dec
Ltail_xts_dec:
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak1,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $tweak1,$tweak1,$tmp
subi $inp,$inp,16
add $inp,$inp,$len
vxor $inout,$inout,$tweak # :-(
vxor $inout,$inout,$tweak1 # :-)
Loop_xts_dec_short:
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vncipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key1
addi $idx,$idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vncipher $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key1
addi $idx,$idx,16
bdnz Loop_xts_dec_short
?vperm $rndkey1,$rndkey1,$rndkey0,$keyperm
vncipher $inout,$inout,$rndkey1
lvx $rndkey1,$idx,$key1
li $idx,16
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
vxor $rndkey0,$rndkey0,$tweak1
vncipherlast $output,$inout,$rndkey0
le?vperm $tmp,$output,$output,$leperm
be?nop
le?stvx_u $tmp,0,$out
be?stvx_u $output,0,$out
vmr $inout,$inptail
lvx $inptail,0,$inp
#addi $inp,$inp,16
lvx $rndkey0,0,$key1
lvx $rndkey1,$idx,$key1
addi $idx,$idx,16
vperm $inout,$inout,$inptail,$inpperm
?vperm $rndkey0,$rndkey0,$rndkey1,$keyperm
lvsr $inpperm,0,$len # $inpperm is no longer needed
vxor $inptail,$inptail,$inptail # $inptail is no longer needed
vspltisb $tmp,-1
vperm $inptail,$inptail,$tmp,$inpperm
vsel $inout,$inout,$output,$inptail
vxor $rndkey0,$rndkey0,$tweak
vxor $inout,$inout,$rndkey0
lvx $rndkey0,$idx,$key1
addi $idx,$idx,16
subi r11,$out,1
mtctr $len
li $len,16
Loop_xts_dec_steal:
lbzu r0,1(r11)
stb r0,16(r11)
bdnz Loop_xts_dec_steal
mtctr $rounds
b Loop_xts_dec # one more time...
Lxts_dec_done:
${UCMP}i $ivp,0
beq Lxts_dec_ret
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $tweak,$tweak,$tmp
le?vperm $tweak,$tweak,$tweak,$leperm
stvx_u $tweak,0,$ivp
Lxts_dec_ret:
mtspr 256,r12 # restore vrsave
li r3,0
blr
.long 0
.byte 0,12,0x04,0,0x80,6,6,0
.long 0
.size .${prefix}_xts_decrypt,.-.${prefix}_xts_decrypt
___
#########################################################################
{{ # Optimized XTS procedures #
my $key_=$key2;
my ($x00,$x10,$x20,$x30,$x40,$x50,$x60,$x70)=map("r$_",(0,3,26..31));
$x00=0 if ($flavour =~ /osx/);
my ($in0, $in1, $in2, $in3, $in4, $in5 )=map("v$_",(0..5));
my ($out0, $out1, $out2, $out3, $out4, $out5)=map("v$_",(7,12..16));
my ($twk0, $twk1, $twk2, $twk3, $twk4, $twk5)=map("v$_",(17..22));
my $rndkey0="v23"; # v24-v25 rotating buffer for first found keys
# v26-v31 last 6 round keys
my ($keyperm)=($out0); # aliases with "caller", redundant assignment
my $taillen=$x70;
$code.=<<___;
.align 5
_aesp8_xts_encrypt6x:
$STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp)
mflr r11
li r7,`$FRAME+8*16+15`
li r3,`$FRAME+8*16+31`
$PUSH r11,`$FRAME+21*16+6*$SIZE_T+$LRSAVE`($sp)
stvx v20,r7,$sp # ABI says so
addi r7,r7,32
stvx v21,r3,$sp
addi r3,r3,32
stvx v22,r7,$sp
addi r7,r7,32
stvx v23,r3,$sp
addi r3,r3,32
stvx v24,r7,$sp
addi r7,r7,32
stvx v25,r3,$sp
addi r3,r3,32
stvx v26,r7,$sp
addi r7,r7,32
stvx v27,r3,$sp
addi r3,r3,32
stvx v28,r7,$sp
addi r7,r7,32
stvx v29,r3,$sp
addi r3,r3,32
stvx v30,r7,$sp
stvx v31,r3,$sp
li r0,-1
stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave
li $x10,0x10
$PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp)
li $x20,0x20
$PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp)
li $x30,0x30
$PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp)
li $x40,0x40
$PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp)
li $x50,0x50
$PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp)
li $x60,0x60
$PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp)
li $x70,0x70
mtspr 256,r0
subi $rounds,$rounds,3 # -4 in total
lvx $rndkey0,$x00,$key1 # load key schedule
lvx v30,$x10,$key1
addi $key1,$key1,0x20
lvx v31,$x00,$key1
?vperm $rndkey0,$rndkey0,v30,$keyperm
addi $key_,$sp,$FRAME+15
mtctr $rounds
Load_xts_enc_key:
?vperm v24,v30,v31,$keyperm
lvx v30,$x10,$key1
addi $key1,$key1,0x20
stvx v24,$x00,$key_ # off-load round[1]
?vperm v25,v31,v30,$keyperm
lvx v31,$x00,$key1
stvx v25,$x10,$key_ # off-load round[2]
addi $key_,$key_,0x20
bdnz Load_xts_enc_key
lvx v26,$x10,$key1
?vperm v24,v30,v31,$keyperm
lvx v27,$x20,$key1
stvx v24,$x00,$key_ # off-load round[3]
?vperm v25,v31,v26,$keyperm
lvx v28,$x30,$key1
stvx v25,$x10,$key_ # off-load round[4]
addi $key_,$sp,$FRAME+15 # rewind $key_
?vperm v26,v26,v27,$keyperm
lvx v29,$x40,$key1
?vperm v27,v27,v28,$keyperm
lvx v30,$x50,$key1
?vperm v28,v28,v29,$keyperm
lvx v31,$x60,$key1
?vperm v29,v29,v30,$keyperm
lvx $twk5,$x70,$key1 # borrow $twk5
?vperm v30,v30,v31,$keyperm
lvx v24,$x00,$key_ # pre-load round[1]
?vperm v31,v31,$twk5,$keyperm
lvx v25,$x10,$key_ # pre-load round[2]
vperm $in0,$inout,$inptail,$inpperm
subi $inp,$inp,31 # undo "caller"
vxor $twk0,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $out0,$in0,$twk0
vxor $tweak,$tweak,$tmp
lvx_u $in1,$x10,$inp
vxor $twk1,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in1,$in1,$in1,$leperm
vand $tmp,$tmp,$eighty7
vxor $out1,$in1,$twk1
vxor $tweak,$tweak,$tmp
lvx_u $in2,$x20,$inp
andi. $taillen,$len,15
vxor $twk2,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in2,$in2,$in2,$leperm
vand $tmp,$tmp,$eighty7
vxor $out2,$in2,$twk2
vxor $tweak,$tweak,$tmp
lvx_u $in3,$x30,$inp
sub $len,$len,$taillen
vxor $twk3,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in3,$in3,$in3,$leperm
vand $tmp,$tmp,$eighty7
vxor $out3,$in3,$twk3
vxor $tweak,$tweak,$tmp
lvx_u $in4,$x40,$inp
subi $len,$len,0x60
vxor $twk4,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in4,$in4,$in4,$leperm
vand $tmp,$tmp,$eighty7
vxor $out4,$in4,$twk4
vxor $tweak,$tweak,$tmp
lvx_u $in5,$x50,$inp
addi $inp,$inp,0x60
vxor $twk5,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in5,$in5,$in5,$leperm
vand $tmp,$tmp,$eighty7
vxor $out5,$in5,$twk5
vxor $tweak,$tweak,$tmp
vxor v31,v31,$rndkey0
mtctr $rounds
b Loop_xts_enc6x
.align 5
Loop_xts_enc6x:
vcipher $out0,$out0,v24
vcipher $out1,$out1,v24
vcipher $out2,$out2,v24
vcipher $out3,$out3,v24
vcipher $out4,$out4,v24
vcipher $out5,$out5,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vcipher $out0,$out0,v25
vcipher $out1,$out1,v25
vcipher $out2,$out2,v25
vcipher $out3,$out3,v25
vcipher $out4,$out4,v25
vcipher $out5,$out5,v25
lvx v25,$x10,$key_ # round[4]
bdnz Loop_xts_enc6x
subic $len,$len,96 # $len-=96
vxor $in0,$twk0,v31 # xor with last round key
vcipher $out0,$out0,v24
vcipher $out1,$out1,v24
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk0,$tweak,$rndkey0
vaddubm $tweak,$tweak,$tweak
vcipher $out2,$out2,v24
vcipher $out3,$out3,v24
vsldoi $tmp,$tmp,$tmp,15
vcipher $out4,$out4,v24
vcipher $out5,$out5,v24
subfe. r0,r0,r0 # borrow?-1:0
vand $tmp,$tmp,$eighty7
vcipher $out0,$out0,v25
vcipher $out1,$out1,v25
vxor $tweak,$tweak,$tmp
vcipher $out2,$out2,v25
vcipher $out3,$out3,v25
vxor $in1,$twk1,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk1,$tweak,$rndkey0
vcipher $out4,$out4,v25
vcipher $out5,$out5,v25
and r0,r0,$len
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vcipher $out0,$out0,v26
vcipher $out1,$out1,v26
vand $tmp,$tmp,$eighty7
vcipher $out2,$out2,v26
vcipher $out3,$out3,v26
vxor $tweak,$tweak,$tmp
vcipher $out4,$out4,v26
vcipher $out5,$out5,v26
add $inp,$inp,r0 # $inp is adjusted in such
# way that at exit from the
# loop inX-in5 are loaded
# with last "words"
vxor $in2,$twk2,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk2,$tweak,$rndkey0
vaddubm $tweak,$tweak,$tweak
vcipher $out0,$out0,v27
vcipher $out1,$out1,v27
vsldoi $tmp,$tmp,$tmp,15
vcipher $out2,$out2,v27
vcipher $out3,$out3,v27
vand $tmp,$tmp,$eighty7
vcipher $out4,$out4,v27
vcipher $out5,$out5,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
vxor $tweak,$tweak,$tmp
vcipher $out0,$out0,v28
vcipher $out1,$out1,v28
vxor $in3,$twk3,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk3,$tweak,$rndkey0
vcipher $out2,$out2,v28
vcipher $out3,$out3,v28
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vcipher $out4,$out4,v28
vcipher $out5,$out5,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
vand $tmp,$tmp,$eighty7
vcipher $out0,$out0,v29
vcipher $out1,$out1,v29
vxor $tweak,$tweak,$tmp
vcipher $out2,$out2,v29
vcipher $out3,$out3,v29
vxor $in4,$twk4,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk4,$tweak,$rndkey0
vcipher $out4,$out4,v29
vcipher $out5,$out5,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vcipher $out0,$out0,v30
vcipher $out1,$out1,v30
vand $tmp,$tmp,$eighty7
vcipher $out2,$out2,v30
vcipher $out3,$out3,v30
vxor $tweak,$tweak,$tmp
vcipher $out4,$out4,v30
vcipher $out5,$out5,v30
vxor $in5,$twk5,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk5,$tweak,$rndkey0
vcipherlast $out0,$out0,$in0
lvx_u $in0,$x00,$inp # load next input block
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vcipherlast $out1,$out1,$in1
lvx_u $in1,$x10,$inp
vcipherlast $out2,$out2,$in2
le?vperm $in0,$in0,$in0,$leperm
lvx_u $in2,$x20,$inp
vand $tmp,$tmp,$eighty7
vcipherlast $out3,$out3,$in3
le?vperm $in1,$in1,$in1,$leperm
lvx_u $in3,$x30,$inp
vcipherlast $out4,$out4,$in4
le?vperm $in2,$in2,$in2,$leperm
lvx_u $in4,$x40,$inp
vxor $tweak,$tweak,$tmp
vcipherlast $tmp,$out5,$in5 # last block might be needed
# in stealing mode
le?vperm $in3,$in3,$in3,$leperm
lvx_u $in5,$x50,$inp
addi $inp,$inp,0x60
le?vperm $in4,$in4,$in4,$leperm
le?vperm $in5,$in5,$in5,$leperm
le?vperm $out0,$out0,$out0,$leperm
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
vxor $out0,$in0,$twk0
le?vperm $out2,$out2,$out2,$leperm
stvx_u $out1,$x10,$out
vxor $out1,$in1,$twk1
le?vperm $out3,$out3,$out3,$leperm
stvx_u $out2,$x20,$out
vxor $out2,$in2,$twk2
le?vperm $out4,$out4,$out4,$leperm
stvx_u $out3,$x30,$out
vxor $out3,$in3,$twk3
le?vperm $out5,$tmp,$tmp,$leperm
stvx_u $out4,$x40,$out
vxor $out4,$in4,$twk4
le?stvx_u $out5,$x50,$out
be?stvx_u $tmp, $x50,$out
vxor $out5,$in5,$twk5
addi $out,$out,0x60
mtctr $rounds
beq Loop_xts_enc6x # did $len-=96 borrow?
addic. $len,$len,0x60
beq Lxts_enc6x_zero
cmpwi $len,0x20
blt Lxts_enc6x_one
nop
beq Lxts_enc6x_two
cmpwi $len,0x40
blt Lxts_enc6x_three
nop
beq Lxts_enc6x_four
Lxts_enc6x_five:
vxor $out0,$in1,$twk0
vxor $out1,$in2,$twk1
vxor $out2,$in3,$twk2
vxor $out3,$in4,$twk3
vxor $out4,$in5,$twk4
bl _aesp8_xts_enc5x
le?vperm $out0,$out0,$out0,$leperm
vmr $twk0,$twk5 # unused tweak
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
le?vperm $out2,$out2,$out2,$leperm
stvx_u $out1,$x10,$out
le?vperm $out3,$out3,$out3,$leperm
stvx_u $out2,$x20,$out
vxor $tmp,$out4,$twk5 # last block prep for stealing
le?vperm $out4,$out4,$out4,$leperm
stvx_u $out3,$x30,$out
stvx_u $out4,$x40,$out
addi $out,$out,0x50
bne Lxts_enc6x_steal
b Lxts_enc6x_done
.align 4
Lxts_enc6x_four:
vxor $out0,$in2,$twk0
vxor $out1,$in3,$twk1
vxor $out2,$in4,$twk2
vxor $out3,$in5,$twk3
vxor $out4,$out4,$out4
bl _aesp8_xts_enc5x
le?vperm $out0,$out0,$out0,$leperm
vmr $twk0,$twk4 # unused tweak
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
le?vperm $out2,$out2,$out2,$leperm
stvx_u $out1,$x10,$out
vxor $tmp,$out3,$twk4 # last block prep for stealing
le?vperm $out3,$out3,$out3,$leperm
stvx_u $out2,$x20,$out
stvx_u $out3,$x30,$out
addi $out,$out,0x40
bne Lxts_enc6x_steal
b Lxts_enc6x_done
.align 4
Lxts_enc6x_three:
vxor $out0,$in3,$twk0
vxor $out1,$in4,$twk1
vxor $out2,$in5,$twk2
vxor $out3,$out3,$out3
vxor $out4,$out4,$out4
bl _aesp8_xts_enc5x
le?vperm $out0,$out0,$out0,$leperm
vmr $twk0,$twk3 # unused tweak
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
vxor $tmp,$out2,$twk3 # last block prep for stealing
le?vperm $out2,$out2,$out2,$leperm
stvx_u $out1,$x10,$out
stvx_u $out2,$x20,$out
addi $out,$out,0x30
bne Lxts_enc6x_steal
b Lxts_enc6x_done
.align 4
Lxts_enc6x_two:
vxor $out0,$in4,$twk0
vxor $out1,$in5,$twk1
vxor $out2,$out2,$out2
vxor $out3,$out3,$out3
vxor $out4,$out4,$out4
bl _aesp8_xts_enc5x
le?vperm $out0,$out0,$out0,$leperm
vmr $twk0,$twk2 # unused tweak
vxor $tmp,$out1,$twk2 # last block prep for stealing
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
stvx_u $out1,$x10,$out
addi $out,$out,0x20
bne Lxts_enc6x_steal
b Lxts_enc6x_done
.align 4
Lxts_enc6x_one:
vxor $out0,$in5,$twk0
nop
Loop_xts_enc1x:
vcipher $out0,$out0,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vcipher $out0,$out0,v25
lvx v25,$x10,$key_ # round[4]
bdnz Loop_xts_enc1x
add $inp,$inp,$taillen
cmpwi $taillen,0
vcipher $out0,$out0,v24
subi $inp,$inp,16
vcipher $out0,$out0,v25
lvsr $inpperm,0,$taillen
vcipher $out0,$out0,v26
lvx_u $in0,0,$inp
vcipher $out0,$out0,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
vcipher $out0,$out0,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
vcipher $out0,$out0,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vxor $twk0,$twk0,v31
le?vperm $in0,$in0,$in0,$leperm
vcipher $out0,$out0,v30
vperm $in0,$in0,$in0,$inpperm
vcipherlast $out0,$out0,$twk0
vmr $twk0,$twk1 # unused tweak
vxor $tmp,$out0,$twk1 # last block prep for stealing
le?vperm $out0,$out0,$out0,$leperm
stvx_u $out0,$x00,$out # store output
addi $out,$out,0x10
bne Lxts_enc6x_steal
b Lxts_enc6x_done
.align 4
Lxts_enc6x_zero:
cmpwi $taillen,0
beq Lxts_enc6x_done
add $inp,$inp,$taillen
subi $inp,$inp,16
lvx_u $in0,0,$inp
lvsr $inpperm,0,$taillen # $in5 is no more
le?vperm $in0,$in0,$in0,$leperm
vperm $in0,$in0,$in0,$inpperm
vxor $tmp,$tmp,$twk0
Lxts_enc6x_steal:
vxor $in0,$in0,$twk0
vxor $out0,$out0,$out0
vspltisb $out1,-1
vperm $out0,$out0,$out1,$inpperm
vsel $out0,$in0,$tmp,$out0 # $tmp is last block, remember?
subi r30,$out,17
subi $out,$out,16
mtctr $taillen
Loop_xts_enc6x_steal:
lbzu r0,1(r30)
stb r0,16(r30)
bdnz Loop_xts_enc6x_steal
li $taillen,0
mtctr $rounds
b Loop_xts_enc1x # one more time...
.align 4
Lxts_enc6x_done:
${UCMP}i $ivp,0
beq Lxts_enc6x_ret
vxor $tweak,$twk0,$rndkey0
le?vperm $tweak,$tweak,$tweak,$leperm
stvx_u $tweak,0,$ivp
Lxts_enc6x_ret:
mtlr r11
li r10,`$FRAME+15`
li r11,`$FRAME+31`
stvx $seven,r10,$sp # wipe copies of round keys
addi r10,r10,32
stvx $seven,r11,$sp
addi r11,r11,32
stvx $seven,r10,$sp
addi r10,r10,32
stvx $seven,r11,$sp
addi r11,r11,32
stvx $seven,r10,$sp
addi r10,r10,32
stvx $seven,r11,$sp
addi r11,r11,32
stvx $seven,r10,$sp
addi r10,r10,32
stvx $seven,r11,$sp
addi r11,r11,32
mtspr 256,$vrsave
lvx v20,r10,$sp # ABI says so
addi r10,r10,32
lvx v21,r11,$sp
addi r11,r11,32
lvx v22,r10,$sp
addi r10,r10,32
lvx v23,r11,$sp
addi r11,r11,32
lvx v24,r10,$sp
addi r10,r10,32
lvx v25,r11,$sp
addi r11,r11,32
lvx v26,r10,$sp
addi r10,r10,32
lvx v27,r11,$sp
addi r11,r11,32
lvx v28,r10,$sp
addi r10,r10,32
lvx v29,r11,$sp
addi r11,r11,32
lvx v30,r10,$sp
lvx v31,r11,$sp
$POP r26,`$FRAME+21*16+0*$SIZE_T`($sp)
$POP r27,`$FRAME+21*16+1*$SIZE_T`($sp)
$POP r28,`$FRAME+21*16+2*$SIZE_T`($sp)
$POP r29,`$FRAME+21*16+3*$SIZE_T`($sp)
$POP r30,`$FRAME+21*16+4*$SIZE_T`($sp)
$POP r31,`$FRAME+21*16+5*$SIZE_T`($sp)
addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T`
blr
.long 0
.byte 0,12,0x04,1,0x80,6,6,0
.long 0
.align 5
_aesp8_xts_enc5x:
vcipher $out0,$out0,v24
vcipher $out1,$out1,v24
vcipher $out2,$out2,v24
vcipher $out3,$out3,v24
vcipher $out4,$out4,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vcipher $out0,$out0,v25
vcipher $out1,$out1,v25
vcipher $out2,$out2,v25
vcipher $out3,$out3,v25
vcipher $out4,$out4,v25
lvx v25,$x10,$key_ # round[4]
bdnz _aesp8_xts_enc5x
add $inp,$inp,$taillen
cmpwi $taillen,0
vcipher $out0,$out0,v24
vcipher $out1,$out1,v24
vcipher $out2,$out2,v24
vcipher $out3,$out3,v24
vcipher $out4,$out4,v24
subi $inp,$inp,16
vcipher $out0,$out0,v25
vcipher $out1,$out1,v25
vcipher $out2,$out2,v25
vcipher $out3,$out3,v25
vcipher $out4,$out4,v25
vxor $twk0,$twk0,v31
vcipher $out0,$out0,v26
lvsr $inpperm,0,$taillen # $in5 is no more
vcipher $out1,$out1,v26
vcipher $out2,$out2,v26
vcipher $out3,$out3,v26
vcipher $out4,$out4,v26
vxor $in1,$twk1,v31
vcipher $out0,$out0,v27
lvx_u $in0,0,$inp
vcipher $out1,$out1,v27
vcipher $out2,$out2,v27
vcipher $out3,$out3,v27
vcipher $out4,$out4,v27
vxor $in2,$twk2,v31
addi $key_,$sp,$FRAME+15 # rewind $key_
vcipher $out0,$out0,v28
vcipher $out1,$out1,v28
vcipher $out2,$out2,v28
vcipher $out3,$out3,v28
vcipher $out4,$out4,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
vxor $in3,$twk3,v31
vcipher $out0,$out0,v29
le?vperm $in0,$in0,$in0,$leperm
vcipher $out1,$out1,v29
vcipher $out2,$out2,v29
vcipher $out3,$out3,v29
vcipher $out4,$out4,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vxor $in4,$twk4,v31
vcipher $out0,$out0,v30
vperm $in0,$in0,$in0,$inpperm
vcipher $out1,$out1,v30
vcipher $out2,$out2,v30
vcipher $out3,$out3,v30
vcipher $out4,$out4,v30
vcipherlast $out0,$out0,$twk0
vcipherlast $out1,$out1,$in1
vcipherlast $out2,$out2,$in2
vcipherlast $out3,$out3,$in3
vcipherlast $out4,$out4,$in4
blr
.long 0
.byte 0,12,0x14,0,0,0,0,0
.align 5
_aesp8_xts_decrypt6x:
$STU $sp,-`($FRAME+21*16+6*$SIZE_T)`($sp)
mflr r11
li r7,`$FRAME+8*16+15`
li r3,`$FRAME+8*16+31`
$PUSH r11,`$FRAME+21*16+6*$SIZE_T+$LRSAVE`($sp)
stvx v20,r7,$sp # ABI says so
addi r7,r7,32
stvx v21,r3,$sp
addi r3,r3,32
stvx v22,r7,$sp
addi r7,r7,32
stvx v23,r3,$sp
addi r3,r3,32
stvx v24,r7,$sp
addi r7,r7,32
stvx v25,r3,$sp
addi r3,r3,32
stvx v26,r7,$sp
addi r7,r7,32
stvx v27,r3,$sp
addi r3,r3,32
stvx v28,r7,$sp
addi r7,r7,32
stvx v29,r3,$sp
addi r3,r3,32
stvx v30,r7,$sp
stvx v31,r3,$sp
li r0,-1
stw $vrsave,`$FRAME+21*16-4`($sp) # save vrsave
li $x10,0x10
$PUSH r26,`$FRAME+21*16+0*$SIZE_T`($sp)
li $x20,0x20
$PUSH r27,`$FRAME+21*16+1*$SIZE_T`($sp)
li $x30,0x30
$PUSH r28,`$FRAME+21*16+2*$SIZE_T`($sp)
li $x40,0x40
$PUSH r29,`$FRAME+21*16+3*$SIZE_T`($sp)
li $x50,0x50
$PUSH r30,`$FRAME+21*16+4*$SIZE_T`($sp)
li $x60,0x60
$PUSH r31,`$FRAME+21*16+5*$SIZE_T`($sp)
li $x70,0x70
mtspr 256,r0
subi $rounds,$rounds,3 # -4 in total
lvx $rndkey0,$x00,$key1 # load key schedule
lvx v30,$x10,$key1
addi $key1,$key1,0x20
lvx v31,$x00,$key1
?vperm $rndkey0,$rndkey0,v30,$keyperm
addi $key_,$sp,$FRAME+15
mtctr $rounds
Load_xts_dec_key:
?vperm v24,v30,v31,$keyperm
lvx v30,$x10,$key1
addi $key1,$key1,0x20
stvx v24,$x00,$key_ # off-load round[1]
?vperm v25,v31,v30,$keyperm
lvx v31,$x00,$key1
stvx v25,$x10,$key_ # off-load round[2]
addi $key_,$key_,0x20
bdnz Load_xts_dec_key
lvx v26,$x10,$key1
?vperm v24,v30,v31,$keyperm
lvx v27,$x20,$key1
stvx v24,$x00,$key_ # off-load round[3]
?vperm v25,v31,v26,$keyperm
lvx v28,$x30,$key1
stvx v25,$x10,$key_ # off-load round[4]
addi $key_,$sp,$FRAME+15 # rewind $key_
?vperm v26,v26,v27,$keyperm
lvx v29,$x40,$key1
?vperm v27,v27,v28,$keyperm
lvx v30,$x50,$key1
?vperm v28,v28,v29,$keyperm
lvx v31,$x60,$key1
?vperm v29,v29,v30,$keyperm
lvx $twk5,$x70,$key1 # borrow $twk5
?vperm v30,v30,v31,$keyperm
lvx v24,$x00,$key_ # pre-load round[1]
?vperm v31,v31,$twk5,$keyperm
lvx v25,$x10,$key_ # pre-load round[2]
vperm $in0,$inout,$inptail,$inpperm
subi $inp,$inp,31 # undo "caller"
vxor $twk0,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vand $tmp,$tmp,$eighty7
vxor $out0,$in0,$twk0
vxor $tweak,$tweak,$tmp
lvx_u $in1,$x10,$inp
vxor $twk1,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in1,$in1,$in1,$leperm
vand $tmp,$tmp,$eighty7
vxor $out1,$in1,$twk1
vxor $tweak,$tweak,$tmp
lvx_u $in2,$x20,$inp
andi. $taillen,$len,15
vxor $twk2,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in2,$in2,$in2,$leperm
vand $tmp,$tmp,$eighty7
vxor $out2,$in2,$twk2
vxor $tweak,$tweak,$tmp
lvx_u $in3,$x30,$inp
sub $len,$len,$taillen
vxor $twk3,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in3,$in3,$in3,$leperm
vand $tmp,$tmp,$eighty7
vxor $out3,$in3,$twk3
vxor $tweak,$tweak,$tmp
lvx_u $in4,$x40,$inp
subi $len,$len,0x60
vxor $twk4,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in4,$in4,$in4,$leperm
vand $tmp,$tmp,$eighty7
vxor $out4,$in4,$twk4
vxor $tweak,$tweak,$tmp
lvx_u $in5,$x50,$inp
addi $inp,$inp,0x60
vxor $twk5,$tweak,$rndkey0
vsrab $tmp,$tweak,$seven # next tweak value
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
le?vperm $in5,$in5,$in5,$leperm
vand $tmp,$tmp,$eighty7
vxor $out5,$in5,$twk5
vxor $tweak,$tweak,$tmp
vxor v31,v31,$rndkey0
mtctr $rounds
b Loop_xts_dec6x
.align 5
Loop_xts_dec6x:
vncipher $out0,$out0,v24
vncipher $out1,$out1,v24
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
vncipher $out4,$out4,v24
vncipher $out5,$out5,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vncipher $out0,$out0,v25
vncipher $out1,$out1,v25
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vncipher $out4,$out4,v25
vncipher $out5,$out5,v25
lvx v25,$x10,$key_ # round[4]
bdnz Loop_xts_dec6x
subic $len,$len,96 # $len-=96
vxor $in0,$twk0,v31 # xor with last round key
vncipher $out0,$out0,v24
vncipher $out1,$out1,v24
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk0,$tweak,$rndkey0
vaddubm $tweak,$tweak,$tweak
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
vsldoi $tmp,$tmp,$tmp,15
vncipher $out4,$out4,v24
vncipher $out5,$out5,v24
subfe. r0,r0,r0 # borrow?-1:0
vand $tmp,$tmp,$eighty7
vncipher $out0,$out0,v25
vncipher $out1,$out1,v25
vxor $tweak,$tweak,$tmp
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vxor $in1,$twk1,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk1,$tweak,$rndkey0
vncipher $out4,$out4,v25
vncipher $out5,$out5,v25
and r0,r0,$len
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vncipher $out0,$out0,v26
vncipher $out1,$out1,v26
vand $tmp,$tmp,$eighty7
vncipher $out2,$out2,v26
vncipher $out3,$out3,v26
vxor $tweak,$tweak,$tmp
vncipher $out4,$out4,v26
vncipher $out5,$out5,v26
add $inp,$inp,r0 # $inp is adjusted in such
# way that at exit from the
# loop inX-in5 are loaded
# with last "words"
vxor $in2,$twk2,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk2,$tweak,$rndkey0
vaddubm $tweak,$tweak,$tweak
vncipher $out0,$out0,v27
vncipher $out1,$out1,v27
vsldoi $tmp,$tmp,$tmp,15
vncipher $out2,$out2,v27
vncipher $out3,$out3,v27
vand $tmp,$tmp,$eighty7
vncipher $out4,$out4,v27
vncipher $out5,$out5,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
vxor $tweak,$tweak,$tmp
vncipher $out0,$out0,v28
vncipher $out1,$out1,v28
vxor $in3,$twk3,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk3,$tweak,$rndkey0
vncipher $out2,$out2,v28
vncipher $out3,$out3,v28
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vncipher $out4,$out4,v28
vncipher $out5,$out5,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
vand $tmp,$tmp,$eighty7
vncipher $out0,$out0,v29
vncipher $out1,$out1,v29
vxor $tweak,$tweak,$tmp
vncipher $out2,$out2,v29
vncipher $out3,$out3,v29
vxor $in4,$twk4,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk4,$tweak,$rndkey0
vncipher $out4,$out4,v29
vncipher $out5,$out5,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vncipher $out0,$out0,v30
vncipher $out1,$out1,v30
vand $tmp,$tmp,$eighty7
vncipher $out2,$out2,v30
vncipher $out3,$out3,v30
vxor $tweak,$tweak,$tmp
vncipher $out4,$out4,v30
vncipher $out5,$out5,v30
vxor $in5,$twk5,v31
vsrab $tmp,$tweak,$seven # next tweak value
vxor $twk5,$tweak,$rndkey0
vncipherlast $out0,$out0,$in0
lvx_u $in0,$x00,$inp # load next input block
vaddubm $tweak,$tweak,$tweak
vsldoi $tmp,$tmp,$tmp,15
vncipherlast $out1,$out1,$in1
lvx_u $in1,$x10,$inp
vncipherlast $out2,$out2,$in2
le?vperm $in0,$in0,$in0,$leperm
lvx_u $in2,$x20,$inp
vand $tmp,$tmp,$eighty7
vncipherlast $out3,$out3,$in3
le?vperm $in1,$in1,$in1,$leperm
lvx_u $in3,$x30,$inp
vncipherlast $out4,$out4,$in4
le?vperm $in2,$in2,$in2,$leperm
lvx_u $in4,$x40,$inp
vxor $tweak,$tweak,$tmp
vncipherlast $out5,$out5,$in5
le?vperm $in3,$in3,$in3,$leperm
lvx_u $in5,$x50,$inp
addi $inp,$inp,0x60
le?vperm $in4,$in4,$in4,$leperm
le?vperm $in5,$in5,$in5,$leperm
le?vperm $out0,$out0,$out0,$leperm
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
vxor $out0,$in0,$twk0
le?vperm $out2,$out2,$out2,$leperm
stvx_u $out1,$x10,$out
vxor $out1,$in1,$twk1
le?vperm $out3,$out3,$out3,$leperm
stvx_u $out2,$x20,$out
vxor $out2,$in2,$twk2
le?vperm $out4,$out4,$out4,$leperm
stvx_u $out3,$x30,$out
vxor $out3,$in3,$twk3
le?vperm $out5,$out5,$out5,$leperm
stvx_u $out4,$x40,$out
vxor $out4,$in4,$twk4
stvx_u $out5,$x50,$out
vxor $out5,$in5,$twk5
addi $out,$out,0x60
mtctr $rounds
beq Loop_xts_dec6x # did $len-=96 borrow?
addic. $len,$len,0x60
beq Lxts_dec6x_zero
cmpwi $len,0x20
blt Lxts_dec6x_one
nop
beq Lxts_dec6x_two
cmpwi $len,0x40
blt Lxts_dec6x_three
nop
beq Lxts_dec6x_four
Lxts_dec6x_five:
vxor $out0,$in1,$twk0
vxor $out1,$in2,$twk1
vxor $out2,$in3,$twk2
vxor $out3,$in4,$twk3
vxor $out4,$in5,$twk4
bl _aesp8_xts_dec5x
le?vperm $out0,$out0,$out0,$leperm
vmr $twk0,$twk5 # unused tweak
vxor $twk1,$tweak,$rndkey0
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
vxor $out0,$in0,$twk1
le?vperm $out2,$out2,$out2,$leperm
stvx_u $out1,$x10,$out
le?vperm $out3,$out3,$out3,$leperm
stvx_u $out2,$x20,$out
le?vperm $out4,$out4,$out4,$leperm
stvx_u $out3,$x30,$out
stvx_u $out4,$x40,$out
addi $out,$out,0x50
bne Lxts_dec6x_steal
b Lxts_dec6x_done
.align 4
Lxts_dec6x_four:
vxor $out0,$in2,$twk0
vxor $out1,$in3,$twk1
vxor $out2,$in4,$twk2
vxor $out3,$in5,$twk3
vxor $out4,$out4,$out4
bl _aesp8_xts_dec5x
le?vperm $out0,$out0,$out0,$leperm
vmr $twk0,$twk4 # unused tweak
vmr $twk1,$twk5
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
vxor $out0,$in0,$twk5
le?vperm $out2,$out2,$out2,$leperm
stvx_u $out1,$x10,$out
le?vperm $out3,$out3,$out3,$leperm
stvx_u $out2,$x20,$out
stvx_u $out3,$x30,$out
addi $out,$out,0x40
bne Lxts_dec6x_steal
b Lxts_dec6x_done
.align 4
Lxts_dec6x_three:
vxor $out0,$in3,$twk0
vxor $out1,$in4,$twk1
vxor $out2,$in5,$twk2
vxor $out3,$out3,$out3
vxor $out4,$out4,$out4
bl _aesp8_xts_dec5x
le?vperm $out0,$out0,$out0,$leperm
vmr $twk0,$twk3 # unused tweak
vmr $twk1,$twk4
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
vxor $out0,$in0,$twk4
le?vperm $out2,$out2,$out2,$leperm
stvx_u $out1,$x10,$out
stvx_u $out2,$x20,$out
addi $out,$out,0x30
bne Lxts_dec6x_steal
b Lxts_dec6x_done
.align 4
Lxts_dec6x_two:
vxor $out0,$in4,$twk0
vxor $out1,$in5,$twk1
vxor $out2,$out2,$out2
vxor $out3,$out3,$out3
vxor $out4,$out4,$out4
bl _aesp8_xts_dec5x
le?vperm $out0,$out0,$out0,$leperm
vmr $twk0,$twk2 # unused tweak
vmr $twk1,$twk3
le?vperm $out1,$out1,$out1,$leperm
stvx_u $out0,$x00,$out # store output
vxor $out0,$in0,$twk3
stvx_u $out1,$x10,$out
addi $out,$out,0x20
bne Lxts_dec6x_steal
b Lxts_dec6x_done
.align 4
Lxts_dec6x_one:
vxor $out0,$in5,$twk0
nop
Loop_xts_dec1x:
vncipher $out0,$out0,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vncipher $out0,$out0,v25
lvx v25,$x10,$key_ # round[4]
bdnz Loop_xts_dec1x
subi r0,$taillen,1
vncipher $out0,$out0,v24
andi. r0,r0,16
cmpwi $taillen,0
vncipher $out0,$out0,v25
sub $inp,$inp,r0
vncipher $out0,$out0,v26
lvx_u $in0,0,$inp
vncipher $out0,$out0,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
vncipher $out0,$out0,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
vncipher $out0,$out0,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vxor $twk0,$twk0,v31
le?vperm $in0,$in0,$in0,$leperm
vncipher $out0,$out0,v30
mtctr $rounds
vncipherlast $out0,$out0,$twk0
vmr $twk0,$twk1 # unused tweak
vmr $twk1,$twk2
le?vperm $out0,$out0,$out0,$leperm
stvx_u $out0,$x00,$out # store output
addi $out,$out,0x10
vxor $out0,$in0,$twk2
bne Lxts_dec6x_steal
b Lxts_dec6x_done
.align 4
Lxts_dec6x_zero:
cmpwi $taillen,0
beq Lxts_dec6x_done
lvx_u $in0,0,$inp
le?vperm $in0,$in0,$in0,$leperm
vxor $out0,$in0,$twk1
Lxts_dec6x_steal:
vncipher $out0,$out0,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vncipher $out0,$out0,v25
lvx v25,$x10,$key_ # round[4]
bdnz Lxts_dec6x_steal
add $inp,$inp,$taillen
vncipher $out0,$out0,v24
cmpwi $taillen,0
vncipher $out0,$out0,v25
lvx_u $in0,0,$inp
vncipher $out0,$out0,v26
lvsr $inpperm,0,$taillen # $in5 is no more
vncipher $out0,$out0,v27
addi $key_,$sp,$FRAME+15 # rewind $key_
vncipher $out0,$out0,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
vncipher $out0,$out0,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vxor $twk1,$twk1,v31
le?vperm $in0,$in0,$in0,$leperm
vncipher $out0,$out0,v30
vperm $in0,$in0,$in0,$inpperm
vncipherlast $tmp,$out0,$twk1
le?vperm $out0,$tmp,$tmp,$leperm
le?stvx_u $out0,0,$out
be?stvx_u $tmp,0,$out
vxor $out0,$out0,$out0
vspltisb $out1,-1
vperm $out0,$out0,$out1,$inpperm
vsel $out0,$in0,$tmp,$out0
vxor $out0,$out0,$twk0
subi r30,$out,1
mtctr $taillen
Loop_xts_dec6x_steal:
lbzu r0,1(r30)
stb r0,16(r30)
bdnz Loop_xts_dec6x_steal
li $taillen,0
mtctr $rounds
b Loop_xts_dec1x # one more time...
.align 4
Lxts_dec6x_done:
${UCMP}i $ivp,0
beq Lxts_dec6x_ret
vxor $tweak,$twk0,$rndkey0
le?vperm $tweak,$tweak,$tweak,$leperm
stvx_u $tweak,0,$ivp
Lxts_dec6x_ret:
mtlr r11
li r10,`$FRAME+15`
li r11,`$FRAME+31`
stvx $seven,r10,$sp # wipe copies of round keys
addi r10,r10,32
stvx $seven,r11,$sp
addi r11,r11,32
stvx $seven,r10,$sp
addi r10,r10,32
stvx $seven,r11,$sp
addi r11,r11,32
stvx $seven,r10,$sp
addi r10,r10,32
stvx $seven,r11,$sp
addi r11,r11,32
stvx $seven,r10,$sp
addi r10,r10,32
stvx $seven,r11,$sp
addi r11,r11,32
mtspr 256,$vrsave
lvx v20,r10,$sp # ABI says so
addi r10,r10,32
lvx v21,r11,$sp
addi r11,r11,32
lvx v22,r10,$sp
addi r10,r10,32
lvx v23,r11,$sp
addi r11,r11,32
lvx v24,r10,$sp
addi r10,r10,32
lvx v25,r11,$sp
addi r11,r11,32
lvx v26,r10,$sp
addi r10,r10,32
lvx v27,r11,$sp
addi r11,r11,32
lvx v28,r10,$sp
addi r10,r10,32
lvx v29,r11,$sp
addi r11,r11,32
lvx v30,r10,$sp
lvx v31,r11,$sp
$POP r26,`$FRAME+21*16+0*$SIZE_T`($sp)
$POP r27,`$FRAME+21*16+1*$SIZE_T`($sp)
$POP r28,`$FRAME+21*16+2*$SIZE_T`($sp)
$POP r29,`$FRAME+21*16+3*$SIZE_T`($sp)
$POP r30,`$FRAME+21*16+4*$SIZE_T`($sp)
$POP r31,`$FRAME+21*16+5*$SIZE_T`($sp)
addi $sp,$sp,`$FRAME+21*16+6*$SIZE_T`
blr
.long 0
.byte 0,12,0x04,1,0x80,6,6,0
.long 0
.align 5
_aesp8_xts_dec5x:
vncipher $out0,$out0,v24
vncipher $out1,$out1,v24
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
vncipher $out4,$out4,v24
lvx v24,$x20,$key_ # round[3]
addi $key_,$key_,0x20
vncipher $out0,$out0,v25
vncipher $out1,$out1,v25
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vncipher $out4,$out4,v25
lvx v25,$x10,$key_ # round[4]
bdnz _aesp8_xts_dec5x
subi r0,$taillen,1
vncipher $out0,$out0,v24
vncipher $out1,$out1,v24
vncipher $out2,$out2,v24
vncipher $out3,$out3,v24
vncipher $out4,$out4,v24
andi. r0,r0,16
cmpwi $taillen,0
vncipher $out0,$out0,v25
vncipher $out1,$out1,v25
vncipher $out2,$out2,v25
vncipher $out3,$out3,v25
vncipher $out4,$out4,v25
vxor $twk0,$twk0,v31
sub $inp,$inp,r0
vncipher $out0,$out0,v26
vncipher $out1,$out1,v26
vncipher $out2,$out2,v26
vncipher $out3,$out3,v26
vncipher $out4,$out4,v26
vxor $in1,$twk1,v31
vncipher $out0,$out0,v27
lvx_u $in0,0,$inp
vncipher $out1,$out1,v27
vncipher $out2,$out2,v27
vncipher $out3,$out3,v27
vncipher $out4,$out4,v27
vxor $in2,$twk2,v31
addi $key_,$sp,$FRAME+15 # rewind $key_
vncipher $out0,$out0,v28
vncipher $out1,$out1,v28
vncipher $out2,$out2,v28
vncipher $out3,$out3,v28
vncipher $out4,$out4,v28
lvx v24,$x00,$key_ # re-pre-load round[1]
vxor $in3,$twk3,v31
vncipher $out0,$out0,v29
le?vperm $in0,$in0,$in0,$leperm
vncipher $out1,$out1,v29
vncipher $out2,$out2,v29
vncipher $out3,$out3,v29
vncipher $out4,$out4,v29
lvx v25,$x10,$key_ # re-pre-load round[2]
vxor $in4,$twk4,v31
vncipher $out0,$out0,v30
vncipher $out1,$out1,v30
vncipher $out2,$out2,v30
vncipher $out3,$out3,v30
vncipher $out4,$out4,v30
vncipherlast $out0,$out0,$twk0
vncipherlast $out1,$out1,$in1
vncipherlast $out2,$out2,$in2
vncipherlast $out3,$out3,$in3
vncipherlast $out4,$out4,$in4
mtctr $rounds
blr
.long 0
.byte 0,12,0x14,0,0,0,0,0
___
}} }}}
my $consts=1;
foreach(split("\n",$code)) {
s/\`([^\`]*)\`/eval($1)/geo;
# constants table endian-specific conversion
if ($consts && m/\.(long|byte)\s+(.+)\s+(\?[a-z]*)$/o) {
my $conv=$3;
my @bytes=();
# convert to endian-agnostic format
if ($1 eq "long") {
foreach (split(/,\s*/,$2)) {
my $l = /^0/?oct:int;
push @bytes,($l>>24)&0xff,($l>>16)&0xff,($l>>8)&0xff,$l&0xff;
}
} else {
@bytes = map(/^0/?oct:int,split(/,\s*/,$2));
}
# little-endian conversion
if ($flavour =~ /le$/o) {
SWITCH: for($conv) {
/\?inv/ && do { @bytes=map($_^0xf,@bytes); last; };
/\?rev/ && do { @bytes=reverse(@bytes); last; };
}
}
#emit
print ".byte\t",join(',',map (sprintf("0x%02x",$_),@bytes)),"\n";
next;
}
$consts=0 if (m/Lconsts:/o); # end of table
# instructions prefixed with '?' are endian-specific and need
# to be adjusted accordingly...
if ($flavour =~ /le$/o) { # little-endian
s/le\?//o or
s/be\?/#be#/o or
s/\?lvsr/lvsl/o or
s/\?lvsl/lvsr/o or
s/\?(vperm\s+v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+,\s*)(v[0-9]+)/$1$3$2$4/o or
s/\?(vsldoi\s+v[0-9]+,\s*)(v[0-9]+,)\s*(v[0-9]+,\s*)([0-9]+)/$1$3$2 16-$4/o or
s/\?(vspltw\s+v[0-9]+,\s*)(v[0-9]+,)\s*([0-9])/$1$2 3-$3/o;
} else { # big-endian
s/le\?/#le#/o or
s/be\?//o or
s/\?([a-z]+)/$1/o;
}
print $_,"\n";
}
close STDOUT;
diff --git a/crypto/bio/b_addr.c b/crypto/bio/b_addr.c
index 4395ab7a0683..f295b766fa73 100644
--- a/crypto/bio/b_addr.c
+++ b/crypto/bio/b_addr.c
@@ -1,902 +1,908 @@
/*
* Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <assert.h>
#include <string.h>
#include "bio_lcl.h"
#include <openssl/crypto.h>
#ifndef OPENSSL_NO_SOCK
#include <openssl/err.h>
#include <openssl/buffer.h>
#include "internal/thread_once.h"
CRYPTO_RWLOCK *bio_lookup_lock;
static CRYPTO_ONCE bio_lookup_init = CRYPTO_ONCE_STATIC_INIT;
/*
* Throughout this file and bio_lcl.h, the existence of the macro
* AI_PASSIVE is used to detect the availability of struct addrinfo,
* getnameinfo() and getaddrinfo(). If that macro doesn't exist,
* we use our own implementation instead, using gethostbyname,
* getservbyname and a few other.
*/
/**********************************************************************
*
* Address structure
*
*/
BIO_ADDR *BIO_ADDR_new(void)
{
BIO_ADDR *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
BIOerr(BIO_F_BIO_ADDR_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->sa.sa_family = AF_UNSPEC;
return ret;
}
void BIO_ADDR_free(BIO_ADDR *ap)
{
OPENSSL_free(ap);
}
void BIO_ADDR_clear(BIO_ADDR *ap)
{
memset(ap, 0, sizeof(*ap));
ap->sa.sa_family = AF_UNSPEC;
}
/*
* BIO_ADDR_make - non-public routine to fill a BIO_ADDR with the contents
* of a struct sockaddr.
*/
int BIO_ADDR_make(BIO_ADDR *ap, const struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
memcpy(&(ap->s_in), sa, sizeof(struct sockaddr_in));
return 1;
}
#ifdef AF_INET6
if (sa->sa_family == AF_INET6) {
memcpy(&(ap->s_in6), sa, sizeof(struct sockaddr_in6));
return 1;
}
#endif
#ifdef AF_UNIX
if (sa->sa_family == AF_UNIX) {
memcpy(&(ap->s_un), sa, sizeof(struct sockaddr_un));
return 1;
}
#endif
return 0;
}
int BIO_ADDR_rawmake(BIO_ADDR *ap, int family,
const void *where, size_t wherelen,
unsigned short port)
{
#ifdef AF_UNIX
if (family == AF_UNIX) {
if (wherelen + 1 > sizeof(ap->s_un.sun_path))
return 0;
memset(&ap->s_un, 0, sizeof(ap->s_un));
ap->s_un.sun_family = family;
strncpy(ap->s_un.sun_path, where, sizeof(ap->s_un.sun_path) - 1);
return 1;
}
#endif
if (family == AF_INET) {
if (wherelen != sizeof(struct in_addr))
return 0;
memset(&ap->s_in, 0, sizeof(ap->s_in));
ap->s_in.sin_family = family;
ap->s_in.sin_port = port;
ap->s_in.sin_addr = *(struct in_addr *)where;
return 1;
}
#ifdef AF_INET6
if (family == AF_INET6) {
if (wherelen != sizeof(struct in6_addr))
return 0;
memset(&ap->s_in6, 0, sizeof(ap->s_in6));
ap->s_in6.sin6_family = family;
ap->s_in6.sin6_port = port;
ap->s_in6.sin6_addr = *(struct in6_addr *)where;
return 1;
}
#endif
return 0;
}
int BIO_ADDR_family(const BIO_ADDR *ap)
{
return ap->sa.sa_family;
}
int BIO_ADDR_rawaddress(const BIO_ADDR *ap, void *p, size_t *l)
{
size_t len = 0;
const void *addrptr = NULL;
if (ap->sa.sa_family == AF_INET) {
len = sizeof(ap->s_in.sin_addr);
addrptr = &ap->s_in.sin_addr;
}
#ifdef AF_INET6
else if (ap->sa.sa_family == AF_INET6) {
len = sizeof(ap->s_in6.sin6_addr);
addrptr = &ap->s_in6.sin6_addr;
}
#endif
#ifdef AF_UNIX
else if (ap->sa.sa_family == AF_UNIX) {
len = strlen(ap->s_un.sun_path);
addrptr = &ap->s_un.sun_path;
}
#endif
if (addrptr == NULL)
return 0;
if (p != NULL) {
memcpy(p, addrptr, len);
}
if (l != NULL)
*l = len;
return 1;
}
unsigned short BIO_ADDR_rawport(const BIO_ADDR *ap)
{
if (ap->sa.sa_family == AF_INET)
return ap->s_in.sin_port;
#ifdef AF_INET6
if (ap->sa.sa_family == AF_INET6)
return ap->s_in6.sin6_port;
#endif
return 0;
}
/*-
* addr_strings - helper function to get host and service names
* @ap: the BIO_ADDR that has the input info
* @numeric: 0 if actual names should be returned, 1 if the numeric
* representation should be returned.
* @hostname: a pointer to a pointer to a memory area to store the
* host name or numeric representation. Unused if NULL.
* @service: a pointer to a pointer to a memory area to store the
* service name or numeric representation. Unused if NULL.
*
* The return value is 0 on failure, with the error code in the error
* stack, and 1 on success.
*/
static int addr_strings(const BIO_ADDR *ap, int numeric,
char **hostname, char **service)
{
if (BIO_sock_init() != 1)
return 0;
if (1) {
#ifdef AI_PASSIVE
int ret = 0;
char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
int flags = 0;
if (numeric)
flags |= NI_NUMERICHOST | NI_NUMERICSERV;
if ((ret = getnameinfo(BIO_ADDR_sockaddr(ap),
BIO_ADDR_sockaddr_size(ap),
host, sizeof(host), serv, sizeof(serv),
flags)) != 0) {
# ifdef EAI_SYSTEM
if (ret == EAI_SYSTEM) {
SYSerr(SYS_F_GETNAMEINFO, get_last_socket_error());
BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
} else
# endif
{
BIOerr(BIO_F_ADDR_STRINGS, ERR_R_SYS_LIB);
ERR_add_error_data(1, gai_strerror(ret));
}
return 0;
}
/* VMS getnameinfo() has a bug, it doesn't fill in serv, which
* leaves it with whatever garbage that happens to be there.
* However, we initialise serv with the empty string (serv[0]
* is therefore NUL), so it gets real easy to detect when things
* didn't go the way one might expect.
*/
if (serv[0] == '\0') {
BIO_snprintf(serv, sizeof(serv), "%d",
ntohs(BIO_ADDR_rawport(ap)));
}
if (hostname != NULL)
*hostname = OPENSSL_strdup(host);
if (service != NULL)
*service = OPENSSL_strdup(serv);
} else {
#endif
if (hostname != NULL)
*hostname = OPENSSL_strdup(inet_ntoa(ap->s_in.sin_addr));
if (service != NULL) {
char serv[6]; /* port is 16 bits => max 5 decimal digits */
BIO_snprintf(serv, sizeof(serv), "%d", ntohs(ap->s_in.sin_port));
*service = OPENSSL_strdup(serv);
}
}
if ((hostname != NULL && *hostname == NULL)
|| (service != NULL && *service == NULL)) {
if (hostname != NULL) {
OPENSSL_free(*hostname);
*hostname = NULL;
}
if (service != NULL) {
OPENSSL_free(*service);
*service = NULL;
}
BIOerr(BIO_F_ADDR_STRINGS, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
char *BIO_ADDR_hostname_string(const BIO_ADDR *ap, int numeric)
{
char *hostname = NULL;
if (addr_strings(ap, numeric, &hostname, NULL))
return hostname;
return NULL;
}
char *BIO_ADDR_service_string(const BIO_ADDR *ap, int numeric)
{
char *service = NULL;
if (addr_strings(ap, numeric, NULL, &service))
return service;
return NULL;
}
char *BIO_ADDR_path_string(const BIO_ADDR *ap)
{
#ifdef AF_UNIX
if (ap->sa.sa_family == AF_UNIX)
return OPENSSL_strdup(ap->s_un.sun_path);
#endif
return NULL;
}
/*
* BIO_ADDR_sockaddr - non-public routine to return the struct sockaddr
* for a given BIO_ADDR. In reality, this is simply a type safe cast.
* The returned struct sockaddr is const, so it can't be tampered with.
*/
const struct sockaddr *BIO_ADDR_sockaddr(const BIO_ADDR *ap)
{
return &(ap->sa);
}
/*
* BIO_ADDR_sockaddr_noconst - non-public function that does the same
* as BIO_ADDR_sockaddr, but returns a non-const. USE WITH CARE, as
* it allows you to tamper with the data (and thereby the contents
* of the input BIO_ADDR).
*/
struct sockaddr *BIO_ADDR_sockaddr_noconst(BIO_ADDR *ap)
{
return &(ap->sa);
}
/*
* BIO_ADDR_sockaddr_size - non-public function that returns the size
* of the struct sockaddr the BIO_ADDR is using. If the protocol family
* isn't set or is something other than AF_INET, AF_INET6 or AF_UNIX,
* the size of the BIO_ADDR type is returned.
*/
socklen_t BIO_ADDR_sockaddr_size(const BIO_ADDR *ap)
{
if (ap->sa.sa_family == AF_INET)
return sizeof(ap->s_in);
#ifdef AF_INET6
if (ap->sa.sa_family == AF_INET6)
return sizeof(ap->s_in6);
#endif
#ifdef AF_UNIX
if (ap->sa.sa_family == AF_UNIX)
return sizeof(ap->s_un);
#endif
return sizeof(*ap);
}
/**********************************************************************
*
* Address info database
*
*/
const BIO_ADDRINFO *BIO_ADDRINFO_next(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_next;
return NULL;
}
int BIO_ADDRINFO_family(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_family;
return 0;
}
int BIO_ADDRINFO_socktype(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_socktype;
return 0;
}
int BIO_ADDRINFO_protocol(const BIO_ADDRINFO *bai)
{
if (bai != NULL) {
if (bai->bai_protocol != 0)
return bai->bai_protocol;
#ifdef AF_UNIX
if (bai->bai_family == AF_UNIX)
return 0;
#endif
switch (bai->bai_socktype) {
case SOCK_STREAM:
return IPPROTO_TCP;
case SOCK_DGRAM:
return IPPROTO_UDP;
default:
break;
}
}
return 0;
}
/*
* BIO_ADDRINFO_sockaddr_size - non-public function that returns the size
* of the struct sockaddr inside the BIO_ADDRINFO.
*/
socklen_t BIO_ADDRINFO_sockaddr_size(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_addrlen;
return 0;
}
/*
* BIO_ADDRINFO_sockaddr - non-public function that returns bai_addr
* as the struct sockaddr it is.
*/
const struct sockaddr *BIO_ADDRINFO_sockaddr(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return bai->bai_addr;
return NULL;
}
const BIO_ADDR *BIO_ADDRINFO_address(const BIO_ADDRINFO *bai)
{
if (bai != NULL)
return (BIO_ADDR *)bai->bai_addr;
return NULL;
}
void BIO_ADDRINFO_free(BIO_ADDRINFO *bai)
{
if (bai == NULL)
return;
#ifdef AI_PASSIVE
# ifdef AF_UNIX
# define _cond bai->bai_family != AF_UNIX
# else
# define _cond 1
# endif
if (_cond) {
freeaddrinfo(bai);
return;
}
#endif
/* Free manually when we know that addrinfo_wrap() was used.
* See further comment above addrinfo_wrap()
*/
while (bai != NULL) {
BIO_ADDRINFO *next = bai->bai_next;
OPENSSL_free(bai->bai_addr);
OPENSSL_free(bai);
bai = next;
}
}
/**********************************************************************
*
* Service functions
*
*/
/*-
* The specs in hostserv can take these forms:
*
* host:service => *host = "host", *service = "service"
* host:* => *host = "host", *service = NULL
* host: => *host = "host", *service = NULL
* :service => *host = NULL, *service = "service"
* *:service => *host = NULL, *service = "service"
*
* in case no : is present in the string, the result depends on
* hostserv_prio, as follows:
*
* when hostserv_prio == BIO_PARSE_PRIO_HOST
* host => *host = "host", *service untouched
*
* when hostserv_prio == BIO_PARSE_PRIO_SERV
* service => *host untouched, *service = "service"
*
*/
int BIO_parse_hostserv(const char *hostserv, char **host, char **service,
enum BIO_hostserv_priorities hostserv_prio)
{
const char *h = NULL; size_t hl = 0;
const char *p = NULL; size_t pl = 0;
if (*hostserv == '[') {
if ((p = strchr(hostserv, ']')) == NULL)
goto spec_err;
h = hostserv + 1;
hl = p - h;
p++;
if (*p == '\0')
p = NULL;
else if (*p != ':')
goto spec_err;
else {
p++;
pl = strlen(p);
}
} else {
const char *p2 = strrchr(hostserv, ':');
p = strchr(hostserv, ':');
/*-
* Check for more than one colon. There are three possible
* interpretations:
* 1. IPv6 address with port number, last colon being separator.
* 2. IPv6 address only.
* 3. IPv6 address only if hostserv_prio == BIO_PARSE_PRIO_HOST,
* IPv6 address and port number if hostserv_prio == BIO_PARSE_PRIO_SERV
* Because of this ambiguity, we currently choose to make it an
* error.
*/
if (p != p2)
goto amb_err;
if (p != NULL) {
h = hostserv;
hl = p - h;
p++;
pl = strlen(p);
} else if (hostserv_prio == BIO_PARSE_PRIO_HOST) {
h = hostserv;
hl = strlen(h);
} else {
p = hostserv;
pl = strlen(p);
}
}
if (p != NULL && strchr(p, ':'))
goto spec_err;
if (h != NULL && host != NULL) {
if (hl == 0
|| (hl == 1 && h[0] == '*')) {
*host = NULL;
} else {
*host = OPENSSL_strndup(h, hl);
if (*host == NULL)
goto memerr;
}
}
if (p != NULL && service != NULL) {
if (pl == 0
|| (pl == 1 && p[0] == '*')) {
*service = NULL;
} else {
*service = OPENSSL_strndup(p, pl);
if (*service == NULL)
goto memerr;
}
}
return 1;
amb_err:
BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_AMBIGUOUS_HOST_OR_SERVICE);
return 0;
spec_err:
BIOerr(BIO_F_BIO_PARSE_HOSTSERV, BIO_R_MALFORMED_HOST_OR_SERVICE);
return 0;
memerr:
BIOerr(BIO_F_BIO_PARSE_HOSTSERV, ERR_R_MALLOC_FAILURE);
return 0;
}
/* addrinfo_wrap is used to build our own addrinfo "chain".
* (it has only one entry, so calling it a chain may be a stretch)
* It should ONLY be called when getaddrinfo() and friends
* aren't available, OR when dealing with a non IP protocol
* family, such as AF_UNIX
*
* the return value is 1 on success, or 0 on failure, which
* only happens if a memory allocation error occurred.
*/
static int addrinfo_wrap(int family, int socktype,
const void *where, size_t wherelen,
unsigned short port,
BIO_ADDRINFO **bai)
{
if ((*bai = OPENSSL_zalloc(sizeof(**bai))) == NULL) {
BIOerr(BIO_F_ADDRINFO_WRAP, ERR_R_MALLOC_FAILURE);
return 0;
}
(*bai)->bai_family = family;
(*bai)->bai_socktype = socktype;
if (socktype == SOCK_STREAM)
(*bai)->bai_protocol = IPPROTO_TCP;
if (socktype == SOCK_DGRAM)
(*bai)->bai_protocol = IPPROTO_UDP;
#ifdef AF_UNIX
if (family == AF_UNIX)
(*bai)->bai_protocol = 0;
#endif
{
/* Magic: We know that BIO_ADDR_sockaddr_noconst is really
just an advanced cast of BIO_ADDR* to struct sockaddr *
by the power of union, so while it may seem that we're
creating a memory leak here, we are not. It will be
all right. */
BIO_ADDR *addr = BIO_ADDR_new();
if (addr != NULL) {
BIO_ADDR_rawmake(addr, family, where, wherelen, port);
(*bai)->bai_addr = BIO_ADDR_sockaddr_noconst(addr);
}
}
(*bai)->bai_next = NULL;
if ((*bai)->bai_addr == NULL) {
BIO_ADDRINFO_free(*bai);
*bai = NULL;
return 0;
}
return 1;
}
DEFINE_RUN_ONCE_STATIC(do_bio_lookup_init)
{
if (!OPENSSL_init_crypto(0, NULL))
return 0;
bio_lookup_lock = CRYPTO_THREAD_lock_new();
return bio_lookup_lock != NULL;
}
int BIO_lookup(const char *host, const char *service,
enum BIO_lookup_type lookup_type,
int family, int socktype, BIO_ADDRINFO **res)
{
return BIO_lookup_ex(host, service, lookup_type, family, socktype, 0, res);
}
/*-
* BIO_lookup_ex - look up the node and service you want to connect to.
* @node: the node you want to connect to.
* @service: the service you want to connect to.
* @lookup_type: declare intent with the result, client or server.
* @family: the address family you want to use. Use AF_UNSPEC for any, or
* AF_INET, AF_INET6 or AF_UNIX.
* @socktype: The socket type you want to use. Can be SOCK_STREAM, SOCK_DGRAM
* or 0 for all.
* @protocol: The protocol to use, e.g. IPPROTO_TCP or IPPROTO_UDP or 0 for all.
* Note that some platforms may not return IPPROTO_SCTP without
* explicitly requesting it (i.e. IPPROTO_SCTP may not be returned
* with 0 for the protocol)
* @res: Storage place for the resulting list of returned addresses
*
* This will do a lookup of the node and service that you want to connect to.
* It returns a linked list of different addresses you can try to connect to.
*
* When no longer needed you should call BIO_ADDRINFO_free() to free the result.
*
* The return value is 1 on success or 0 in case of error.
*/
int BIO_lookup_ex(const char *host, const char *service, int lookup_type,
int family, int socktype, int protocol, BIO_ADDRINFO **res)
{
int ret = 0; /* Assume failure */
switch(family) {
case AF_INET:
#ifdef AF_INET6
case AF_INET6:
#endif
#ifdef AF_UNIX
case AF_UNIX:
#endif
#ifdef AF_UNSPEC
case AF_UNSPEC:
#endif
break;
default:
BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_UNSUPPORTED_PROTOCOL_FAMILY);
return 0;
}
#ifdef AF_UNIX
if (family == AF_UNIX) {
if (addrinfo_wrap(family, socktype, host, strlen(host), 0, res))
return 1;
else
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
return 0;
}
#endif
if (BIO_sock_init() != 1)
return 0;
if (1) {
#ifdef AI_PASSIVE
int gai_ret = 0;
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = family;
hints.ai_socktype = socktype;
hints.ai_protocol = protocol;
+#ifdef AI_ADDRCONFIG
+#ifdef AF_UNSPEC
+ if (family == AF_UNSPEC)
+#endif
+ hints.ai_flags |= AI_ADDRCONFIG;
+#endif
if (lookup_type == BIO_LOOKUP_SERVER)
hints.ai_flags |= AI_PASSIVE;
/* Note that |res| SHOULD be a 'struct addrinfo **' thanks to
* macro magic in bio_lcl.h
*/
switch ((gai_ret = getaddrinfo(host, service, &hints, res))) {
# ifdef EAI_SYSTEM
case EAI_SYSTEM:
SYSerr(SYS_F_GETADDRINFO, get_last_socket_error());
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB);
break;
# endif
case 0:
ret = 1; /* Success */
break;
default:
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_SYS_LIB);
ERR_add_error_data(1, gai_strerror(gai_ret));
break;
}
} else {
#endif
const struct hostent *he;
/*
* Because struct hostent is defined for 32-bit pointers only with
* VMS C, we need to make sure that '&he_fallback_address' and
* '&he_fallback_addresses' are 32-bit pointers
*/
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
/* Windows doesn't seem to have in_addr_t */
#ifdef OPENSSL_SYS_WINDOWS
static uint32_t he_fallback_address;
static const char *he_fallback_addresses[] =
{ (char *)&he_fallback_address, NULL };
#else
static in_addr_t he_fallback_address;
static const char *he_fallback_addresses[] =
{ (char *)&he_fallback_address, NULL };
#endif
static const struct hostent he_fallback =
{ NULL, NULL, AF_INET, sizeof(he_fallback_address),
(char **)&he_fallback_addresses };
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif
struct servent *se;
/* Apparently, on WIN64, s_proto and s_port have traded places... */
#ifdef _WIN64
struct servent se_fallback = { NULL, NULL, NULL, 0 };
#else
struct servent se_fallback = { NULL, NULL, 0, NULL };
#endif
if (!RUN_ONCE(&bio_lookup_init, do_bio_lookup_init)) {
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
ret = 0;
goto err;
}
CRYPTO_THREAD_write_lock(bio_lookup_lock);
he_fallback_address = INADDR_ANY;
if (host == NULL) {
he = &he_fallback;
switch(lookup_type) {
case BIO_LOOKUP_CLIENT:
he_fallback_address = INADDR_LOOPBACK;
break;
case BIO_LOOKUP_SERVER:
he_fallback_address = INADDR_ANY;
break;
default:
/* We forgot to handle a lookup type! */
assert("We forgot to handle a lookup type!" == NULL);
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_INTERNAL_ERROR);
ret = 0;
goto err;
}
} else {
he = gethostbyname(host);
if (he == NULL) {
#ifndef OPENSSL_SYS_WINDOWS
/*
* This might be misleading, because h_errno is used as if
* it was errno. To minimize mixup add 1000. Underlying
* reason for this is that hstrerror is declared obsolete,
* not to mention that a) h_errno is not always guaranteed
* to be meaningless; b) hstrerror can reside in yet another
* library, linking for sake of hstrerror is an overkill;
* c) this path is not executed on contemporary systems
* anyway [above getaddrinfo/gai_strerror is]. We just let
* system administrator figure this out...
*/
# if defined(OPENSSL_SYS_VXWORKS)
/* h_errno doesn't exist on VxWorks */
SYSerr(SYS_F_GETHOSTBYNAME, 1000 );
# else
SYSerr(SYS_F_GETHOSTBYNAME, 1000 + h_errno);
# endif
#else
SYSerr(SYS_F_GETHOSTBYNAME, WSAGetLastError());
#endif
ret = 0;
goto err;
}
}
if (service == NULL) {
se_fallback.s_port = 0;
se_fallback.s_proto = NULL;
se = &se_fallback;
} else {
char *endp = NULL;
long portnum = strtol(service, &endp, 10);
/*
* Because struct servent is defined for 32-bit pointers only with
* VMS C, we need to make sure that 'proto' is a 32-bit pointer.
*/
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
char *proto = NULL;
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif
switch (socktype) {
case SOCK_STREAM:
proto = "tcp";
break;
case SOCK_DGRAM:
proto = "udp";
break;
}
if (endp != service && *endp == '\0'
&& portnum > 0 && portnum < 65536) {
se_fallback.s_port = htons((unsigned short)portnum);
se_fallback.s_proto = proto;
se = &se_fallback;
} else if (endp == service) {
se = getservbyname(service, proto);
if (se == NULL) {
#ifndef OPENSSL_SYS_WINDOWS
SYSerr(SYS_F_GETSERVBYNAME, errno);
#else
SYSerr(SYS_F_GETSERVBYNAME, WSAGetLastError());
#endif
goto err;
}
} else {
BIOerr(BIO_F_BIO_LOOKUP_EX, BIO_R_MALFORMED_HOST_OR_SERVICE);
goto err;
}
}
*res = NULL;
{
/*
* Because hostent::h_addr_list is an array of 32-bit pointers with VMS C,
* we must make sure our iterator designates the same element type, hence
* the pointer size dance.
*/
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size save
# pragma pointer_size 32
#endif
char **addrlistp;
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma pointer_size restore
#endif
size_t addresses;
BIO_ADDRINFO *tmp_bai = NULL;
/* The easiest way to create a linked list from an
array is to start from the back */
for(addrlistp = he->h_addr_list; *addrlistp != NULL;
addrlistp++)
;
for(addresses = addrlistp - he->h_addr_list;
addrlistp--, addresses-- > 0; ) {
if (!addrinfo_wrap(he->h_addrtype, socktype,
*addrlistp, he->h_length,
se->s_port, &tmp_bai))
goto addrinfo_malloc_err;
tmp_bai->bai_next = *res;
*res = tmp_bai;
continue;
addrinfo_malloc_err:
BIO_ADDRINFO_free(*res);
*res = NULL;
BIOerr(BIO_F_BIO_LOOKUP_EX, ERR_R_MALLOC_FAILURE);
ret = 0;
goto err;
}
ret = 1;
}
err:
CRYPTO_THREAD_unlock(bio_lookup_lock);
}
return ret;
}
#endif /* OPENSSL_NO_SOCK */
diff --git a/crypto/bio/bss_mem.c b/crypto/bio/bss_mem.c
index 10fcbf7a7c4f..8c621d6c1e88 100644
--- a/crypto/bio/bss_mem.c
+++ b/crypto/bio/bss_mem.c
@@ -1,357 +1,374 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <errno.h>
#include "bio_lcl.h"
#include "internal/cryptlib.h"
static int mem_write(BIO *h, const char *buf, int num);
static int mem_read(BIO *h, char *buf, int size);
static int mem_puts(BIO *h, const char *str);
static int mem_gets(BIO *h, char *str, int size);
static long mem_ctrl(BIO *h, int cmd, long arg1, void *arg2);
static int mem_new(BIO *h);
static int secmem_new(BIO *h);
static int mem_free(BIO *data);
static int mem_buf_free(BIO *data);
static int mem_buf_sync(BIO *h);
static const BIO_METHOD mem_method = {
BIO_TYPE_MEM,
"memory buffer",
/* TODO: Convert to new style write function */
bwrite_conv,
mem_write,
/* TODO: Convert to new style read function */
bread_conv,
mem_read,
mem_puts,
mem_gets,
mem_ctrl,
mem_new,
mem_free,
NULL, /* mem_callback_ctrl */
};
static const BIO_METHOD secmem_method = {
BIO_TYPE_MEM,
"secure memory buffer",
/* TODO: Convert to new style write function */
bwrite_conv,
mem_write,
/* TODO: Convert to new style read function */
bread_conv,
mem_read,
mem_puts,
mem_gets,
mem_ctrl,
secmem_new,
mem_free,
NULL, /* mem_callback_ctrl */
};
-/* BIO memory stores buffer and read pointer */
+/*
+ * BIO memory stores buffer and read pointer
+ * however the roles are different for read only BIOs.
+ * In that case the readp just stores the original state
+ * to be used for reset.
+ */
typedef struct bio_buf_mem_st {
struct buf_mem_st *buf; /* allocated buffer */
struct buf_mem_st *readp; /* read pointer */
} BIO_BUF_MEM;
/*
* bio->num is used to hold the value to return on 'empty', if it is 0,
* should_retry is not set
*/
const BIO_METHOD *BIO_s_mem(void)
{
return &mem_method;
}
const BIO_METHOD *BIO_s_secmem(void)
{
return(&secmem_method);
}
BIO *BIO_new_mem_buf(const void *buf, int len)
{
BIO *ret;
BUF_MEM *b;
BIO_BUF_MEM *bb;
size_t sz;
if (buf == NULL) {
BIOerr(BIO_F_BIO_NEW_MEM_BUF, BIO_R_NULL_PARAMETER);
return NULL;
}
sz = (len < 0) ? strlen(buf) : (size_t)len;
if ((ret = BIO_new(BIO_s_mem())) == NULL)
return NULL;
bb = (BIO_BUF_MEM *)ret->ptr;
b = bb->buf;
/* Cast away const and trust in the MEM_RDONLY flag. */
b->data = (void *)buf;
b->length = sz;
b->max = sz;
*bb->readp = *bb->buf;
ret->flags |= BIO_FLAGS_MEM_RDONLY;
/* Since this is static data retrying won't help */
ret->num = 0;
return ret;
}
static int mem_init(BIO *bi, unsigned long flags)
{
BIO_BUF_MEM *bb = OPENSSL_zalloc(sizeof(*bb));
if (bb == NULL)
return 0;
if ((bb->buf = BUF_MEM_new_ex(flags)) == NULL) {
OPENSSL_free(bb);
return 0;
}
if ((bb->readp = OPENSSL_zalloc(sizeof(*bb->readp))) == NULL) {
BUF_MEM_free(bb->buf);
OPENSSL_free(bb);
return 0;
}
*bb->readp = *bb->buf;
bi->shutdown = 1;
bi->init = 1;
bi->num = -1;
bi->ptr = (char *)bb;
return 1;
}
static int mem_new(BIO *bi)
{
return mem_init(bi, 0L);
}
static int secmem_new(BIO *bi)
{
return mem_init(bi, BUF_MEM_FLAG_SECURE);
}
static int mem_free(BIO *a)
{
BIO_BUF_MEM *bb;
if (a == NULL)
return 0;
bb = (BIO_BUF_MEM *)a->ptr;
if (!mem_buf_free(a))
return 0;
OPENSSL_free(bb->readp);
OPENSSL_free(bb);
return 1;
}
static int mem_buf_free(BIO *a)
{
if (a == NULL)
return 0;
if (a->shutdown && a->init && a->ptr != NULL) {
BIO_BUF_MEM *bb = (BIO_BUF_MEM *)a->ptr;
BUF_MEM *b = bb->buf;
if (a->flags & BIO_FLAGS_MEM_RDONLY)
b->data = NULL;
BUF_MEM_free(b);
}
return 1;
}
/*
* Reallocate memory buffer if read pointer differs
*/
static int mem_buf_sync(BIO *b)
{
if (b != NULL && b->init != 0 && b->ptr != NULL) {
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
if (bbm->readp->data != bbm->buf->data) {
memmove(bbm->buf->data, bbm->readp->data, bbm->readp->length);
bbm->buf->length = bbm->readp->length;
bbm->readp->data = bbm->buf->data;
}
}
return 0;
}
static int mem_read(BIO *b, char *out, int outl)
{
int ret = -1;
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
BUF_MEM *bm = bbm->readp;
+ if (b->flags & BIO_FLAGS_MEM_RDONLY)
+ bm = bbm->buf;
BIO_clear_retry_flags(b);
ret = (outl >= 0 && (size_t)outl > bm->length) ? (int)bm->length : outl;
if ((out != NULL) && (ret > 0)) {
memcpy(out, bm->data, ret);
bm->length -= ret;
+ bm->max -= ret;
bm->data += ret;
} else if (bm->length == 0) {
ret = b->num;
if (ret != 0)
BIO_set_retry_read(b);
}
return ret;
}
static int mem_write(BIO *b, const char *in, int inl)
{
int ret = -1;
int blen;
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
if (in == NULL) {
BIOerr(BIO_F_MEM_WRITE, BIO_R_NULL_PARAMETER);
goto end;
}
if (b->flags & BIO_FLAGS_MEM_RDONLY) {
BIOerr(BIO_F_MEM_WRITE, BIO_R_WRITE_TO_READ_ONLY_BIO);
goto end;
}
BIO_clear_retry_flags(b);
if (inl == 0)
return 0;
blen = bbm->readp->length;
mem_buf_sync(b);
if (BUF_MEM_grow_clean(bbm->buf, blen + inl) == 0)
goto end;
memcpy(bbm->buf->data + blen, in, inl);
*bbm->readp = *bbm->buf;
ret = inl;
end:
return ret;
}
static long mem_ctrl(BIO *b, int cmd, long num, void *ptr)
{
long ret = 1;
char **pptr;
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)b->ptr;
BUF_MEM *bm;
+ if (b->flags & BIO_FLAGS_MEM_RDONLY)
+ bm = bbm->buf;
+ else
+ bm = bbm->readp;
+
switch (cmd) {
case BIO_CTRL_RESET:
bm = bbm->buf;
if (bm->data != NULL) {
- /* For read only case reset to the start again */
- if ((b->flags & BIO_FLAGS_MEM_RDONLY) || (b->flags & BIO_FLAGS_NONCLEAR_RST)) {
- bm->length = bm->max;
+ if (!(b->flags & BIO_FLAGS_MEM_RDONLY)) {
+ if (b->flags & BIO_FLAGS_NONCLEAR_RST) {
+ bm->length = bm->max;
+ } else {
+ memset(bm->data, 0, bm->max);
+ bm->length = 0;
+ }
+ *bbm->readp = *bbm->buf;
} else {
- memset(bm->data, 0, bm->max);
- bm->length = 0;
+ /* For read only case just reset to the start again */
+ *bbm->buf = *bbm->readp;
}
- *bbm->readp = *bbm->buf;
}
break;
case BIO_CTRL_EOF:
- bm = bbm->readp;
ret = (long)(bm->length == 0);
break;
case BIO_C_SET_BUF_MEM_EOF_RETURN:
b->num = (int)num;
break;
case BIO_CTRL_INFO:
- bm = bbm->readp;
ret = (long)bm->length;
if (ptr != NULL) {
pptr = (char **)ptr;
*pptr = (char *)&(bm->data[0]);
}
break;
case BIO_C_SET_BUF_MEM:
mem_buf_free(b);
b->shutdown = (int)num;
bbm->buf = ptr;
*bbm->readp = *bbm->buf;
break;
case BIO_C_GET_BUF_MEM_PTR:
if (ptr != NULL) {
- mem_buf_sync(b);
- bm = bbm->readp;
+ if (!(b->flags & BIO_FLAGS_MEM_RDONLY))
+ mem_buf_sync(b);
+ bm = bbm->buf;
pptr = (char **)ptr;
*pptr = (char *)bm;
}
break;
case BIO_CTRL_GET_CLOSE:
ret = (long)b->shutdown;
break;
case BIO_CTRL_SET_CLOSE:
b->shutdown = (int)num;
break;
case BIO_CTRL_WPENDING:
ret = 0L;
break;
case BIO_CTRL_PENDING:
- bm = bbm->readp;
ret = (long)bm->length;
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
case BIO_CTRL_PUSH:
case BIO_CTRL_POP:
default:
ret = 0;
break;
}
return ret;
}
static int mem_gets(BIO *bp, char *buf, int size)
{
int i, j;
int ret = -1;
char *p;
BIO_BUF_MEM *bbm = (BIO_BUF_MEM *)bp->ptr;
BUF_MEM *bm = bbm->readp;
+ if (bp->flags & BIO_FLAGS_MEM_RDONLY)
+ bm = bbm->buf;
BIO_clear_retry_flags(bp);
j = bm->length;
if ((size - 1) < j)
j = size - 1;
if (j <= 0) {
*buf = '\0';
return 0;
}
p = bm->data;
for (i = 0; i < j; i++) {
if (p[i] == '\n') {
i++;
break;
}
}
/*
* i is now the max num of bytes to copy, either j or up to
* and including the first newline
*/
i = mem_read(bp, buf, i);
if (i > 0)
buf[i] = '\0';
ret = i;
return ret;
}
static int mem_puts(BIO *bp, const char *str)
{
int n, ret;
n = strlen(str);
ret = mem_write(bp, str, n);
/* memory semantics is that it will always work */
return ret;
}
diff --git a/crypto/blake2/blake2b.c b/crypto/blake2/blake2b.c
index 829ba5b50a5c..4b353dd498bb 100644
--- a/crypto/blake2/blake2b.c
+++ b/crypto/blake2/blake2b.c
@@ -1,269 +1,269 @@
/*
- * Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Derived from the BLAKE2 reference implementation written by Samuel Neves.
* Copyright 2012, Samuel Neves <sneves@dei.uc.pt>
* More information about the BLAKE2 hash function and its implementations
* can be found at https://blake2.net.
*/
#include <assert.h>
#include <string.h>
#include <openssl/crypto.h>
#include "blake2_locl.h"
#include "blake2_impl.h"
static const uint64_t blake2b_IV[8] =
{
- 0x6a09e667f3bcc908U, 0xbb67ae8584caa73bU,
- 0x3c6ef372fe94f82bU, 0xa54ff53a5f1d36f1U,
- 0x510e527fade682d1U, 0x9b05688c2b3e6c1fU,
- 0x1f83d9abfb41bd6bU, 0x5be0cd19137e2179U
+ 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const uint8_t 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 }
};
/* Set that it's the last block we'll compress */
static ossl_inline void blake2b_set_lastblock(BLAKE2B_CTX *S)
{
S->f[0] = -1;
}
/* Initialize the hashing state. */
static ossl_inline void blake2b_init0(BLAKE2B_CTX *S)
{
int i;
memset(S, 0, sizeof(BLAKE2B_CTX));
for (i = 0; i < 8; ++i) {
S->h[i] = blake2b_IV[i];
}
}
/* init xors IV with input parameter block */
static void blake2b_init_param(BLAKE2B_CTX *S, const BLAKE2B_PARAM *P)
{
size_t i;
const uint8_t *p = (const uint8_t *)(P);
blake2b_init0(S);
/* The param struct is carefully hand packed, and should be 64 bytes on
* every platform. */
assert(sizeof(BLAKE2B_PARAM) == 64);
/* IV XOR ParamBlock */
for (i = 0; i < 8; ++i) {
S->h[i] ^= load64(p + sizeof(S->h[i]) * i);
}
}
/* Initialize the hashing context. Always returns 1. */
int BLAKE2b_Init(BLAKE2B_CTX *c)
{
BLAKE2B_PARAM P[1];
P->digest_length = BLAKE2B_DIGEST_LENGTH;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32(P->leaf_length, 0);
store64(P->node_offset, 0);
P->node_depth = 0;
P->inner_length = 0;
memset(P->reserved, 0, sizeof(P->reserved));
memset(P->salt, 0, sizeof(P->salt));
memset(P->personal, 0, sizeof(P->personal));
blake2b_init_param(c, P);
return 1;
}
/* Permute the state while xoring in the block of data. */
static void blake2b_compress(BLAKE2B_CTX *S,
const uint8_t *blocks,
size_t len)
{
uint64_t m[16];
uint64_t v[16];
int i;
size_t increment;
/*
* There are two distinct usage vectors for this function:
*
* a) BLAKE2b_Update uses it to process complete blocks,
* possibly more than one at a time;
*
* b) BLAK2b_Final uses it to process last block, always
* single but possibly incomplete, in which case caller
* pads input with zeros.
*/
assert(len < BLAKE2B_BLOCKBYTES || len % BLAKE2B_BLOCKBYTES == 0);
/*
* Since last block is always processed with separate call,
* |len| not being multiple of complete blocks can be observed
* only with |len| being less than BLAKE2B_BLOCKBYTES ("less"
* including even zero), which is why following assignment doesn't
* have to reside inside the main loop below.
*/
increment = len < BLAKE2B_BLOCKBYTES ? len : BLAKE2B_BLOCKBYTES;
for (i = 0; i < 8; ++i) {
v[i] = S->h[i];
}
do {
for (i = 0; i < 16; ++i) {
m[i] = load64(blocks + i * sizeof(m[i]));
}
/* blake2b_increment_counter */
S->t[0] += increment;
S->t[1] += (S->t[0] < increment);
v[8] = blake2b_IV[0];
v[9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = S->t[0] ^ blake2b_IV[4];
v[13] = S->t[1] ^ blake2b_IV[5];
v[14] = S->f[0] ^ blake2b_IV[6];
v[15] = S->f[1] ^ blake2b_IV[7];
#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)
#if defined(OPENSSL_SMALL_FOOTPRINT)
/* 3x size reduction on x86_64, almost 7x on ARMv8, 9x on ARMv4 */
for (i = 0; i < 12; i++) {
ROUND(i);
}
#else
ROUND(0);
ROUND(1);
ROUND(2);
ROUND(3);
ROUND(4);
ROUND(5);
ROUND(6);
ROUND(7);
ROUND(8);
ROUND(9);
ROUND(10);
ROUND(11);
#endif
for (i = 0; i < 8; ++i) {
S->h[i] = v[i] ^= v[i + 8] ^ S->h[i];
}
#undef G
#undef ROUND
blocks += increment;
len -= increment;
} while (len);
}
/* Absorb the input data into the hash state. Always returns 1. */
int BLAKE2b_Update(BLAKE2B_CTX *c, const void *data, size_t datalen)
{
const uint8_t *in = data;
size_t fill;
/*
* Intuitively one would expect intermediate buffer, c->buf, to
* store incomplete blocks. But in this case we are interested to
* temporarily stash even complete blocks, because last one in the
* stream has to be treated in special way, and at this point we
* don't know if last block in *this* call is last one "ever". This
* is the reason for why |datalen| is compared as >, and not >=.
*/
fill = sizeof(c->buf) - c->buflen;
if (datalen > fill) {
if (c->buflen) {
memcpy(c->buf + c->buflen, in, fill); /* Fill buffer */
blake2b_compress(c, c->buf, BLAKE2B_BLOCKBYTES);
c->buflen = 0;
in += fill;
datalen -= fill;
}
if (datalen > BLAKE2B_BLOCKBYTES) {
size_t stashlen = datalen % BLAKE2B_BLOCKBYTES;
/*
* If |datalen| is a multiple of the blocksize, stash
* last complete block, it can be final one...
*/
stashlen = stashlen ? stashlen : BLAKE2B_BLOCKBYTES;
datalen -= stashlen;
blake2b_compress(c, in, datalen);
in += datalen;
datalen = stashlen;
}
}
assert(datalen <= BLAKE2B_BLOCKBYTES);
memcpy(c->buf + c->buflen, in, datalen);
c->buflen += datalen; /* Be lazy, do not compress */
return 1;
}
/*
* Calculate the final hash and save it in md.
* Always returns 1.
*/
int BLAKE2b_Final(unsigned char *md, BLAKE2B_CTX *c)
{
int i;
blake2b_set_lastblock(c);
/* Padding */
memset(c->buf + c->buflen, 0, sizeof(c->buf) - c->buflen);
blake2b_compress(c, c->buf, c->buflen);
/* Output full hash to message digest */
for (i = 0; i < 8; ++i) {
store64(md + sizeof(c->h[i]) * i, c->h[i]);
}
OPENSSL_cleanse(c, sizeof(BLAKE2B_CTX));
return 1;
}
diff --git a/crypto/bn/asm/mips.pl b/crypto/bn/asm/mips.pl
index 3875132bd25d..38b796e375fe 100755
--- a/crypto/bn/asm/mips.pl
+++ b/crypto/bn/asm/mips.pl
@@ -1,2263 +1,2263 @@
#! /usr/bin/env perl
-# Copyright 2010-2016 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2010-2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project.
#
# Rights for redistribution and usage in source and binary forms are
# granted according to the OpenSSL license. Warranty of any kind is
# disclaimed.
# ====================================================================
# July 1999
#
# This is drop-in MIPS III/IV ISA replacement for crypto/bn/bn_asm.c.
#
# The module is designed to work with either of the "new" MIPS ABI(5),
# namely N32 or N64, offered by IRIX 6.x. It's not meant to work under
# IRIX 5.x not only because it doesn't support new ABIs but also
# because 5.x kernels put R4x00 CPU into 32-bit mode and all those
# 64-bit instructions (daddu, dmultu, etc.) found below gonna only
# cause illegal instruction exception:-(
#
# In addition the code depends on preprocessor flags set up by MIPSpro
# compiler driver (either as or cc) and therefore (probably?) can't be
# compiled by the GNU assembler. GNU C driver manages fine though...
# I mean as long as -mmips-as is specified or is the default option,
# because then it simply invokes /usr/bin/as which in turn takes
# perfect care of the preprocessor definitions. Another neat feature
# offered by the MIPSpro assembler is an optimization pass. This gave
# me the opportunity to have the code looking more regular as all those
# architecture dependent instruction rescheduling details were left to
# the assembler. Cool, huh?
#
# Performance improvement is astonishing! 'apps/openssl speed rsa dsa'
# goes way over 3 times faster!
#
# <appro@openssl.org>
# October 2010
#
# Adapt the module even for 32-bit ABIs and other OSes. The former was
# achieved by mechanical replacement of 64-bit arithmetic instructions
# such as dmultu, daddu, etc. with their 32-bit counterparts and
# adjusting offsets denoting multiples of BN_ULONG. Above mentioned
# >3x performance improvement naturally does not apply to 32-bit code
# [because there is no instruction 32-bit compiler can't use], one
# has to content with 40-85% improvement depending on benchmark and
# key length, more for longer keys.
$flavour = shift || "o32";
while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {}
open STDOUT,">$output";
if ($flavour =~ /64|n32/i) {
$LD="ld";
$ST="sd";
$MULTU="dmultu";
$DIVU="ddivu";
$ADDU="daddu";
$SUBU="dsubu";
$SRL="dsrl";
$SLL="dsll";
$BNSZ=8;
$PTR_ADD="daddu";
$PTR_SUB="dsubu";
$SZREG=8;
$REG_S="sd";
$REG_L="ld";
} else {
$LD="lw";
$ST="sw";
$MULTU="multu";
$DIVU="divu";
$ADDU="addu";
$SUBU="subu";
$SRL="srl";
$SLL="sll";
$BNSZ=4;
$PTR_ADD="addu";
$PTR_SUB="subu";
$SZREG=4;
$REG_S="sw";
$REG_L="lw";
- $code=".set mips2\n";
+ $code="#if !(defined (__mips_isa_rev) && (__mips_isa_rev >= 6))\n.set mips2\n#endif\n";
}
# Below is N32/64 register layout used in the original module.
#
($zero,$at,$v0,$v1)=map("\$$_",(0..3));
($a0,$a1,$a2,$a3,$a4,$a5,$a6,$a7)=map("\$$_",(4..11));
($t0,$t1,$t2,$t3,$t8,$t9)=map("\$$_",(12..15,24,25));
($s0,$s1,$s2,$s3,$s4,$s5,$s6,$s7)=map("\$$_",(16..23));
($gp,$sp,$fp,$ra)=map("\$$_",(28..31));
($ta0,$ta1,$ta2,$ta3)=($a4,$a5,$a6,$a7);
#
# No special adaptation is required for O32. NUBI on the other hand
# is treated by saving/restoring ($v1,$t0..$t3).
$gp=$v1 if ($flavour =~ /nubi/i);
$minus4=$v1;
$code.=<<___;
#include "mips_arch.h"
#if defined(_MIPS_ARCH_MIPS64R6)
# define ddivu(rs,rt)
# define mfqt(rd,rs,rt) ddivu rd,rs,rt
# define mfrm(rd,rs,rt) dmodu rd,rs,rt
#elif defined(_MIPS_ARCH_MIPS32R6)
# define divu(rs,rt)
# define mfqt(rd,rs,rt) divu rd,rs,rt
# define mfrm(rd,rs,rt) modu rd,rs,rt
#else
# define $DIVU(rs,rt) $DIVU $zero,rs,rt
# define mfqt(rd,rs,rt) mflo rd
# define mfrm(rd,rs,rt) mfhi rd
#endif
.rdata
.asciiz "mips3.s, Version 1.2"
.asciiz "MIPS II/III/IV ISA artwork by Andy Polyakov <appro\@fy.chalmers.se>"
.text
.set noat
.align 5
.globl bn_mul_add_words
.ent bn_mul_add_words
bn_mul_add_words:
.set noreorder
bgtz $a2,bn_mul_add_words_internal
move $v0,$zero
jr $ra
move $a0,$v0
.end bn_mul_add_words
.align 5
.ent bn_mul_add_words_internal
bn_mul_add_words_internal:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
li $minus4,-4
and $ta0,$a2,$minus4
beqz $ta0,.L_bn_mul_add_words_tail
.L_bn_mul_add_words_loop:
$LD $t0,0($a1)
$MULTU ($t0,$a3)
$LD $t1,0($a0)
$LD $t2,$BNSZ($a1)
$LD $t3,$BNSZ($a0)
$LD $ta0,2*$BNSZ($a1)
$LD $ta1,2*$BNSZ($a0)
$ADDU $t1,$v0
sltu $v0,$t1,$v0 # All manuals say it "compares 32-bit
# values", but it seems to work fine
# even on 64-bit registers.
mflo ($at,$t0,$a3)
mfhi ($t0,$t0,$a3)
$ADDU $t1,$at
$ADDU $v0,$t0
$MULTU ($t2,$a3)
sltu $at,$t1,$at
$ST $t1,0($a0)
$ADDU $v0,$at
$LD $ta2,3*$BNSZ($a1)
$LD $ta3,3*$BNSZ($a0)
$ADDU $t3,$v0
sltu $v0,$t3,$v0
mflo ($at,$t2,$a3)
mfhi ($t2,$t2,$a3)
$ADDU $t3,$at
$ADDU $v0,$t2
$MULTU ($ta0,$a3)
sltu $at,$t3,$at
$ST $t3,$BNSZ($a0)
$ADDU $v0,$at
subu $a2,4
$PTR_ADD $a0,4*$BNSZ
$PTR_ADD $a1,4*$BNSZ
$ADDU $ta1,$v0
sltu $v0,$ta1,$v0
mflo ($at,$ta0,$a3)
mfhi ($ta0,$ta0,$a3)
$ADDU $ta1,$at
$ADDU $v0,$ta0
$MULTU ($ta2,$a3)
sltu $at,$ta1,$at
$ST $ta1,-2*$BNSZ($a0)
$ADDU $v0,$at
and $ta0,$a2,$minus4
$ADDU $ta3,$v0
sltu $v0,$ta3,$v0
mflo ($at,$ta2,$a3)
mfhi ($ta2,$ta2,$a3)
$ADDU $ta3,$at
$ADDU $v0,$ta2
sltu $at,$ta3,$at
$ST $ta3,-$BNSZ($a0)
.set noreorder
bgtz $ta0,.L_bn_mul_add_words_loop
$ADDU $v0,$at
beqz $a2,.L_bn_mul_add_words_return
nop
.L_bn_mul_add_words_tail:
.set reorder
$LD $t0,0($a1)
$MULTU ($t0,$a3)
$LD $t1,0($a0)
subu $a2,1
$ADDU $t1,$v0
sltu $v0,$t1,$v0
mflo ($at,$t0,$a3)
mfhi ($t0,$t0,$a3)
$ADDU $t1,$at
$ADDU $v0,$t0
sltu $at,$t1,$at
$ST $t1,0($a0)
$ADDU $v0,$at
beqz $a2,.L_bn_mul_add_words_return
$LD $t0,$BNSZ($a1)
$MULTU ($t0,$a3)
$LD $t1,$BNSZ($a0)
subu $a2,1
$ADDU $t1,$v0
sltu $v0,$t1,$v0
mflo ($at,$t0,$a3)
mfhi ($t0,$t0,$a3)
$ADDU $t1,$at
$ADDU $v0,$t0
sltu $at,$t1,$at
$ST $t1,$BNSZ($a0)
$ADDU $v0,$at
beqz $a2,.L_bn_mul_add_words_return
$LD $t0,2*$BNSZ($a1)
$MULTU ($t0,$a3)
$LD $t1,2*$BNSZ($a0)
$ADDU $t1,$v0
sltu $v0,$t1,$v0
mflo ($at,$t0,$a3)
mfhi ($t0,$t0,$a3)
$ADDU $t1,$at
$ADDU $v0,$t0
sltu $at,$t1,$at
$ST $t1,2*$BNSZ($a0)
$ADDU $v0,$at
.L_bn_mul_add_words_return:
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
move $a0,$v0
.end bn_mul_add_words_internal
.align 5
.globl bn_mul_words
.ent bn_mul_words
bn_mul_words:
.set noreorder
bgtz $a2,bn_mul_words_internal
move $v0,$zero
jr $ra
move $a0,$v0
.end bn_mul_words
.align 5
.ent bn_mul_words_internal
bn_mul_words_internal:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
li $minus4,-4
and $ta0,$a2,$minus4
beqz $ta0,.L_bn_mul_words_tail
.L_bn_mul_words_loop:
$LD $t0,0($a1)
$MULTU ($t0,$a3)
$LD $t2,$BNSZ($a1)
$LD $ta0,2*$BNSZ($a1)
$LD $ta2,3*$BNSZ($a1)
mflo ($at,$t0,$a3)
mfhi ($t0,$t0,$a3)
$ADDU $v0,$at
sltu $t1,$v0,$at
$MULTU ($t2,$a3)
$ST $v0,0($a0)
$ADDU $v0,$t1,$t0
subu $a2,4
$PTR_ADD $a0,4*$BNSZ
$PTR_ADD $a1,4*$BNSZ
mflo ($at,$t2,$a3)
mfhi ($t2,$t2,$a3)
$ADDU $v0,$at
sltu $t3,$v0,$at
$MULTU ($ta0,$a3)
$ST $v0,-3*$BNSZ($a0)
$ADDU $v0,$t3,$t2
mflo ($at,$ta0,$a3)
mfhi ($ta0,$ta0,$a3)
$ADDU $v0,$at
sltu $ta1,$v0,$at
$MULTU ($ta2,$a3)
$ST $v0,-2*$BNSZ($a0)
$ADDU $v0,$ta1,$ta0
and $ta0,$a2,$minus4
mflo ($at,$ta2,$a3)
mfhi ($ta2,$ta2,$a3)
$ADDU $v0,$at
sltu $ta3,$v0,$at
$ST $v0,-$BNSZ($a0)
.set noreorder
bgtz $ta0,.L_bn_mul_words_loop
$ADDU $v0,$ta3,$ta2
beqz $a2,.L_bn_mul_words_return
nop
.L_bn_mul_words_tail:
.set reorder
$LD $t0,0($a1)
$MULTU ($t0,$a3)
subu $a2,1
mflo ($at,$t0,$a3)
mfhi ($t0,$t0,$a3)
$ADDU $v0,$at
sltu $t1,$v0,$at
$ST $v0,0($a0)
$ADDU $v0,$t1,$t0
beqz $a2,.L_bn_mul_words_return
$LD $t0,$BNSZ($a1)
$MULTU ($t0,$a3)
subu $a2,1
mflo ($at,$t0,$a3)
mfhi ($t0,$t0,$a3)
$ADDU $v0,$at
sltu $t1,$v0,$at
$ST $v0,$BNSZ($a0)
$ADDU $v0,$t1,$t0
beqz $a2,.L_bn_mul_words_return
$LD $t0,2*$BNSZ($a1)
$MULTU ($t0,$a3)
mflo ($at,$t0,$a3)
mfhi ($t0,$t0,$a3)
$ADDU $v0,$at
sltu $t1,$v0,$at
$ST $v0,2*$BNSZ($a0)
$ADDU $v0,$t1,$t0
.L_bn_mul_words_return:
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
move $a0,$v0
.end bn_mul_words_internal
.align 5
.globl bn_sqr_words
.ent bn_sqr_words
bn_sqr_words:
.set noreorder
bgtz $a2,bn_sqr_words_internal
move $v0,$zero
jr $ra
move $a0,$v0
.end bn_sqr_words
.align 5
.ent bn_sqr_words_internal
bn_sqr_words_internal:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
li $minus4,-4
and $ta0,$a2,$minus4
beqz $ta0,.L_bn_sqr_words_tail
.L_bn_sqr_words_loop:
$LD $t0,0($a1)
$MULTU ($t0,$t0)
$LD $t2,$BNSZ($a1)
$LD $ta0,2*$BNSZ($a1)
$LD $ta2,3*$BNSZ($a1)
mflo ($t1,$t0,$t0)
mfhi ($t0,$t0,$t0)
$ST $t1,0($a0)
$ST $t0,$BNSZ($a0)
$MULTU ($t2,$t2)
subu $a2,4
$PTR_ADD $a0,8*$BNSZ
$PTR_ADD $a1,4*$BNSZ
mflo ($t3,$t2,$t2)
mfhi ($t2,$t2,$t2)
$ST $t3,-6*$BNSZ($a0)
$ST $t2,-5*$BNSZ($a0)
$MULTU ($ta0,$ta0)
mflo ($ta1,$ta0,$ta0)
mfhi ($ta0,$ta0,$ta0)
$ST $ta1,-4*$BNSZ($a0)
$ST $ta0,-3*$BNSZ($a0)
$MULTU ($ta2,$ta2)
and $ta0,$a2,$minus4
mflo ($ta3,$ta2,$ta2)
mfhi ($ta2,$ta2,$ta2)
$ST $ta3,-2*$BNSZ($a0)
.set noreorder
bgtz $ta0,.L_bn_sqr_words_loop
$ST $ta2,-$BNSZ($a0)
beqz $a2,.L_bn_sqr_words_return
nop
.L_bn_sqr_words_tail:
.set reorder
$LD $t0,0($a1)
$MULTU ($t0,$t0)
subu $a2,1
mflo ($t1,$t0,$t0)
mfhi ($t0,$t0,$t0)
$ST $t1,0($a0)
$ST $t0,$BNSZ($a0)
beqz $a2,.L_bn_sqr_words_return
$LD $t0,$BNSZ($a1)
$MULTU ($t0,$t0)
subu $a2,1
mflo ($t1,$t0,$t0)
mfhi ($t0,$t0,$t0)
$ST $t1,2*$BNSZ($a0)
$ST $t0,3*$BNSZ($a0)
beqz $a2,.L_bn_sqr_words_return
$LD $t0,2*$BNSZ($a1)
$MULTU ($t0,$t0)
mflo ($t1,$t0,$t0)
mfhi ($t0,$t0,$t0)
$ST $t1,4*$BNSZ($a0)
$ST $t0,5*$BNSZ($a0)
.L_bn_sqr_words_return:
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
move $a0,$v0
.end bn_sqr_words_internal
.align 5
.globl bn_add_words
.ent bn_add_words
bn_add_words:
.set noreorder
bgtz $a3,bn_add_words_internal
move $v0,$zero
jr $ra
move $a0,$v0
.end bn_add_words
.align 5
.ent bn_add_words_internal
bn_add_words_internal:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
li $minus4,-4
and $at,$a3,$minus4
beqz $at,.L_bn_add_words_tail
.L_bn_add_words_loop:
$LD $t0,0($a1)
$LD $ta0,0($a2)
subu $a3,4
$LD $t1,$BNSZ($a1)
and $at,$a3,$minus4
$LD $t2,2*$BNSZ($a1)
$PTR_ADD $a2,4*$BNSZ
$LD $t3,3*$BNSZ($a1)
$PTR_ADD $a0,4*$BNSZ
$LD $ta1,-3*$BNSZ($a2)
$PTR_ADD $a1,4*$BNSZ
$LD $ta2,-2*$BNSZ($a2)
$LD $ta3,-$BNSZ($a2)
$ADDU $ta0,$t0
sltu $t8,$ta0,$t0
$ADDU $t0,$ta0,$v0
sltu $v0,$t0,$ta0
$ST $t0,-4*$BNSZ($a0)
$ADDU $v0,$t8
$ADDU $ta1,$t1
sltu $t9,$ta1,$t1
$ADDU $t1,$ta1,$v0
sltu $v0,$t1,$ta1
$ST $t1,-3*$BNSZ($a0)
$ADDU $v0,$t9
$ADDU $ta2,$t2
sltu $t8,$ta2,$t2
$ADDU $t2,$ta2,$v0
sltu $v0,$t2,$ta2
$ST $t2,-2*$BNSZ($a0)
$ADDU $v0,$t8
$ADDU $ta3,$t3
sltu $t9,$ta3,$t3
$ADDU $t3,$ta3,$v0
sltu $v0,$t3,$ta3
$ST $t3,-$BNSZ($a0)
.set noreorder
bgtz $at,.L_bn_add_words_loop
$ADDU $v0,$t9
beqz $a3,.L_bn_add_words_return
nop
.L_bn_add_words_tail:
.set reorder
$LD $t0,0($a1)
$LD $ta0,0($a2)
$ADDU $ta0,$t0
subu $a3,1
sltu $t8,$ta0,$t0
$ADDU $t0,$ta0,$v0
sltu $v0,$t0,$ta0
$ST $t0,0($a0)
$ADDU $v0,$t8
beqz $a3,.L_bn_add_words_return
$LD $t1,$BNSZ($a1)
$LD $ta1,$BNSZ($a2)
$ADDU $ta1,$t1
subu $a3,1
sltu $t9,$ta1,$t1
$ADDU $t1,$ta1,$v0
sltu $v0,$t1,$ta1
$ST $t1,$BNSZ($a0)
$ADDU $v0,$t9
beqz $a3,.L_bn_add_words_return
$LD $t2,2*$BNSZ($a1)
$LD $ta2,2*$BNSZ($a2)
$ADDU $ta2,$t2
sltu $t8,$ta2,$t2
$ADDU $t2,$ta2,$v0
sltu $v0,$t2,$ta2
$ST $t2,2*$BNSZ($a0)
$ADDU $v0,$t8
.L_bn_add_words_return:
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
move $a0,$v0
.end bn_add_words_internal
.align 5
.globl bn_sub_words
.ent bn_sub_words
bn_sub_words:
.set noreorder
bgtz $a3,bn_sub_words_internal
move $v0,$zero
jr $ra
move $a0,$zero
.end bn_sub_words
.align 5
.ent bn_sub_words_internal
bn_sub_words_internal:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
li $minus4,-4
and $at,$a3,$minus4
beqz $at,.L_bn_sub_words_tail
.L_bn_sub_words_loop:
$LD $t0,0($a1)
$LD $ta0,0($a2)
subu $a3,4
$LD $t1,$BNSZ($a1)
and $at,$a3,$minus4
$LD $t2,2*$BNSZ($a1)
$PTR_ADD $a2,4*$BNSZ
$LD $t3,3*$BNSZ($a1)
$PTR_ADD $a0,4*$BNSZ
$LD $ta1,-3*$BNSZ($a2)
$PTR_ADD $a1,4*$BNSZ
$LD $ta2,-2*$BNSZ($a2)
$LD $ta3,-$BNSZ($a2)
sltu $t8,$t0,$ta0
$SUBU $ta0,$t0,$ta0
$SUBU $t0,$ta0,$v0
sgtu $v0,$t0,$ta0
$ST $t0,-4*$BNSZ($a0)
$ADDU $v0,$t8
sltu $t9,$t1,$ta1
$SUBU $ta1,$t1,$ta1
$SUBU $t1,$ta1,$v0
sgtu $v0,$t1,$ta1
$ST $t1,-3*$BNSZ($a0)
$ADDU $v0,$t9
sltu $t8,$t2,$ta2
$SUBU $ta2,$t2,$ta2
$SUBU $t2,$ta2,$v0
sgtu $v0,$t2,$ta2
$ST $t2,-2*$BNSZ($a0)
$ADDU $v0,$t8
sltu $t9,$t3,$ta3
$SUBU $ta3,$t3,$ta3
$SUBU $t3,$ta3,$v0
sgtu $v0,$t3,$ta3
$ST $t3,-$BNSZ($a0)
.set noreorder
bgtz $at,.L_bn_sub_words_loop
$ADDU $v0,$t9
beqz $a3,.L_bn_sub_words_return
nop
.L_bn_sub_words_tail:
.set reorder
$LD $t0,0($a1)
$LD $ta0,0($a2)
subu $a3,1
sltu $t8,$t0,$ta0
$SUBU $ta0,$t0,$ta0
$SUBU $t0,$ta0,$v0
sgtu $v0,$t0,$ta0
$ST $t0,0($a0)
$ADDU $v0,$t8
beqz $a3,.L_bn_sub_words_return
$LD $t1,$BNSZ($a1)
subu $a3,1
$LD $ta1,$BNSZ($a2)
sltu $t9,$t1,$ta1
$SUBU $ta1,$t1,$ta1
$SUBU $t1,$ta1,$v0
sgtu $v0,$t1,$ta1
$ST $t1,$BNSZ($a0)
$ADDU $v0,$t9
beqz $a3,.L_bn_sub_words_return
$LD $t2,2*$BNSZ($a1)
$LD $ta2,2*$BNSZ($a2)
sltu $t8,$t2,$ta2
$SUBU $ta2,$t2,$ta2
$SUBU $t2,$ta2,$v0
sgtu $v0,$t2,$ta2
$ST $t2,2*$BNSZ($a0)
$ADDU $v0,$t8
.L_bn_sub_words_return:
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
move $a0,$v0
.end bn_sub_words_internal
#if 0
/*
* The bn_div_3_words entry point is re-used for constant-time interface.
* Implementation is retained as hystorical reference.
*/
.align 5
.globl bn_div_3_words
.ent bn_div_3_words
bn_div_3_words:
.set noreorder
move $a3,$a0 # we know that bn_div_words does not
# touch $a3, $ta2, $ta3 and preserves $a2
# so that we can save two arguments
# and return address in registers
# instead of stack:-)
$LD $a0,($a3)
move $ta2,$a1
bne $a0,$a2,bn_div_3_words_internal
$LD $a1,-$BNSZ($a3)
li $v0,-1
jr $ra
move $a0,$v0
.end bn_div_3_words
.align 5
.ent bn_div_3_words_internal
bn_div_3_words_internal:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
move $ta3,$ra
bal bn_div_words_internal
move $ra,$ta3
$MULTU ($ta2,$v0)
$LD $t2,-2*$BNSZ($a3)
move $ta0,$zero
mfhi ($t1,$ta2,$v0)
mflo ($t0,$ta2,$v0)
sltu $t8,$t1,$a1
.L_bn_div_3_words_inner_loop:
bnez $t8,.L_bn_div_3_words_inner_loop_done
sgeu $at,$t2,$t0
seq $t9,$t1,$a1
and $at,$t9
sltu $t3,$t0,$ta2
$ADDU $a1,$a2
$SUBU $t1,$t3
$SUBU $t0,$ta2
sltu $t8,$t1,$a1
sltu $ta0,$a1,$a2
or $t8,$ta0
.set noreorder
beqz $at,.L_bn_div_3_words_inner_loop
$SUBU $v0,1
$ADDU $v0,1
.set reorder
.L_bn_div_3_words_inner_loop_done:
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
move $a0,$v0
.end bn_div_3_words_internal
#endif
.align 5
.globl bn_div_words
.ent bn_div_words
bn_div_words:
.set noreorder
bnez $a2,bn_div_words_internal
li $v0,-1 # I would rather signal div-by-zero
# which can be done with 'break 7'
jr $ra
move $a0,$v0
.end bn_div_words
.align 5
.ent bn_div_words_internal
bn_div_words_internal:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
move $v1,$zero
bltz $a2,.L_bn_div_words_body
move $t9,$v1
$SLL $a2,1
bgtz $a2,.-4
addu $t9,1
.set reorder
negu $t1,$t9
li $t2,-1
$SLL $t2,$t1
and $t2,$a0
$SRL $at,$a1,$t1
.set noreorder
beqz $t2,.+12
nop
break 6 # signal overflow
.set reorder
$SLL $a0,$t9
$SLL $a1,$t9
or $a0,$at
___
$QT=$ta0;
$HH=$ta1;
$DH=$v1;
$code.=<<___;
.L_bn_div_words_body:
$SRL $DH,$a2,4*$BNSZ # bits
sgeu $at,$a0,$a2
.set noreorder
beqz $at,.+12
nop
$SUBU $a0,$a2
.set reorder
li $QT,-1
$SRL $HH,$a0,4*$BNSZ # bits
$SRL $QT,4*$BNSZ # q=0xffffffff
beq $DH,$HH,.L_bn_div_words_skip_div1
$DIVU ($a0,$DH)
mfqt ($QT,$a0,$DH)
.L_bn_div_words_skip_div1:
$MULTU ($a2,$QT)
$SLL $t3,$a0,4*$BNSZ # bits
$SRL $at,$a1,4*$BNSZ # bits
or $t3,$at
mflo ($t0,$a2,$QT)
mfhi ($t1,$a2,$QT)
.L_bn_div_words_inner_loop1:
sltu $t2,$t3,$t0
seq $t8,$HH,$t1
sltu $at,$HH,$t1
and $t2,$t8
sltu $v0,$t0,$a2
or $at,$t2
.set noreorder
beqz $at,.L_bn_div_words_inner_loop1_done
$SUBU $t1,$v0
$SUBU $t0,$a2
b .L_bn_div_words_inner_loop1
$SUBU $QT,1
.set reorder
.L_bn_div_words_inner_loop1_done:
$SLL $a1,4*$BNSZ # bits
$SUBU $a0,$t3,$t0
$SLL $v0,$QT,4*$BNSZ # bits
li $QT,-1
$SRL $HH,$a0,4*$BNSZ # bits
$SRL $QT,4*$BNSZ # q=0xffffffff
beq $DH,$HH,.L_bn_div_words_skip_div2
$DIVU ($a0,$DH)
mfqt ($QT,$a0,$DH)
.L_bn_div_words_skip_div2:
$MULTU ($a2,$QT)
$SLL $t3,$a0,4*$BNSZ # bits
$SRL $at,$a1,4*$BNSZ # bits
or $t3,$at
mflo ($t0,$a2,$QT)
mfhi ($t1,$a2,$QT)
.L_bn_div_words_inner_loop2:
sltu $t2,$t3,$t0
seq $t8,$HH,$t1
sltu $at,$HH,$t1
and $t2,$t8
sltu $v1,$t0,$a2
or $at,$t2
.set noreorder
beqz $at,.L_bn_div_words_inner_loop2_done
$SUBU $t1,$v1
$SUBU $t0,$a2
b .L_bn_div_words_inner_loop2
$SUBU $QT,1
.set reorder
.L_bn_div_words_inner_loop2_done:
$SUBU $a0,$t3,$t0
or $v0,$QT
$SRL $v1,$a0,$t9 # $v1 contains remainder if anybody wants it
$SRL $a2,$t9 # restore $a2
.set noreorder
move $a1,$v1
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
move $a0,$v0
.end bn_div_words_internal
___
undef $HH; undef $QT; undef $DH;
($a_0,$a_1,$a_2,$a_3)=($t0,$t1,$t2,$t3);
($b_0,$b_1,$b_2,$b_3)=($ta0,$ta1,$ta2,$ta3);
($a_4,$a_5,$a_6,$a_7)=($s0,$s2,$s4,$a1); # once we load a[7], no use for $a1
($b_4,$b_5,$b_6,$b_7)=($s1,$s3,$s5,$a2); # once we load b[7], no use for $a2
($t_1,$t_2,$c_1,$c_2,$c_3)=($t8,$t9,$v0,$v1,$a3);
$code.=<<___;
.align 5
.globl bn_mul_comba8
.ent bn_mul_comba8
bn_mul_comba8:
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,12*$SZREG,$ra
.mask 0x803ff008,-$SZREG
$PTR_SUB $sp,12*$SZREG
$REG_S $ra,11*$SZREG($sp)
$REG_S $s5,10*$SZREG($sp)
$REG_S $s4,9*$SZREG($sp)
$REG_S $s3,8*$SZREG($sp)
$REG_S $s2,7*$SZREG($sp)
$REG_S $s1,6*$SZREG($sp)
$REG_S $s0,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___ if ($flavour !~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x003f0000,-$SZREG
$PTR_SUB $sp,6*$SZREG
$REG_S $s5,5*$SZREG($sp)
$REG_S $s4,4*$SZREG($sp)
$REG_S $s3,3*$SZREG($sp)
$REG_S $s2,2*$SZREG($sp)
$REG_S $s1,1*$SZREG($sp)
$REG_S $s0,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
$LD $a_0,0($a1) # If compiled with -mips3 option on
# R5000 box assembler barks on this
# 1ine with "should not have mult/div
# as last instruction in bb (R10K
# bug)" warning. If anybody out there
# has a clue about how to circumvent
# this do send me a note.
# <appro\@fy.chalmers.se>
$LD $b_0,0($a2)
$LD $a_1,$BNSZ($a1)
$LD $a_2,2*$BNSZ($a1)
$MULTU ($a_0,$b_0) # mul_add_c(a[0],b[0],c1,c2,c3);
$LD $a_3,3*$BNSZ($a1)
$LD $b_1,$BNSZ($a2)
$LD $b_2,2*$BNSZ($a2)
$LD $b_3,3*$BNSZ($a2)
mflo ($c_1,$a_0,$b_0)
mfhi ($c_2,$a_0,$b_0)
$LD $a_4,4*$BNSZ($a1)
$LD $a_5,5*$BNSZ($a1)
$MULTU ($a_0,$b_1) # mul_add_c(a[0],b[1],c2,c3,c1);
$LD $a_6,6*$BNSZ($a1)
$LD $a_7,7*$BNSZ($a1)
$LD $b_4,4*$BNSZ($a2)
$LD $b_5,5*$BNSZ($a2)
mflo ($t_1,$a_0,$b_1)
mfhi ($t_2,$a_0,$b_1)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_1,$b_0) # mul_add_c(a[1],b[0],c2,c3,c1);
$ADDU $c_3,$t_2,$at
$LD $b_6,6*$BNSZ($a2)
$LD $b_7,7*$BNSZ($a2)
$ST $c_1,0($a0) # r[0]=c1;
mflo ($t_1,$a_1,$b_0)
mfhi ($t_2,$a_1,$b_0)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_2,$b_0) # mul_add_c(a[2],b[0],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $c_1,$c_3,$t_2
$ST $c_2,$BNSZ($a0) # r[1]=c2;
mflo ($t_1,$a_2,$b_0)
mfhi ($t_2,$a_2,$b_0)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_1,$b_1) # mul_add_c(a[1],b[1],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
mflo ($t_1,$a_1,$b_1)
mfhi ($t_2,$a_1,$b_1)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_0,$b_2) # mul_add_c(a[0],b[2],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $c_2,$c_1,$t_2
mflo ($t_1,$a_0,$b_2)
mfhi ($t_2,$a_0,$b_2)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_0,$b_3) # mul_add_c(a[0],b[3],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,2*$BNSZ($a0) # r[2]=c3;
mflo ($t_1,$a_0,$b_3)
mfhi ($t_2,$a_0,$b_3)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_1,$b_2) # mul_add_c(a[1],b[2],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $c_3,$c_2,$t_2
mflo ($t_1,$a_1,$b_2)
mfhi ($t_2,$a_1,$b_2)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_2,$b_1) # mul_add_c(a[2],b[1],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_2,$b_1)
mfhi ($t_2,$a_2,$b_1)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_3,$b_0) # mul_add_c(a[3],b[0],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_3,$b_0)
mfhi ($t_2,$a_3,$b_0)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_4,$b_0) # mul_add_c(a[4],b[0],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
$ST $c_1,3*$BNSZ($a0) # r[3]=c1;
mflo ($t_1,$a_4,$b_0)
mfhi ($t_2,$a_4,$b_0)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_3,$b_1) # mul_add_c(a[3],b[1],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $c_1,$c_3,$t_2
mflo ($t_1,$a_3,$b_1)
mfhi ($t_2,$a_3,$b_1)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_2,$b_2) # mul_add_c(a[2],b[2],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_2,$b_2)
mfhi ($t_2,$a_2,$b_2)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_1,$b_3) # mul_add_c(a[1],b[3],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_1,$b_3)
mfhi ($t_2,$a_1,$b_3)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_0,$b_4) # mul_add_c(a[0],b[4],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_0,$b_4)
mfhi ($t_2,$a_0,$b_4)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_0,$b_5) # mul_add_c(a[0],b[5],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
$ST $c_2,4*$BNSZ($a0) # r[4]=c2;
mflo ($t_1,$a_0,$b_5)
mfhi ($t_2,$a_0,$b_5)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_1,$b_4) # mul_add_c(a[1],b[4],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $c_2,$c_1,$t_2
mflo ($t_1,$a_1,$b_4)
mfhi ($t_2,$a_1,$b_4)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_2,$b_3) # mul_add_c(a[2],b[3],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_2,$b_3)
mfhi ($t_2,$a_2,$b_3)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_3,$b_2) # mul_add_c(a[3],b[2],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_3,$b_2)
mfhi ($t_2,$a_3,$b_2)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_4,$b_1) # mul_add_c(a[4],b[1],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_4,$b_1)
mfhi ($t_2,$a_4,$b_1)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_5,$b_0) # mul_add_c(a[5],b[0],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_5,$b_0)
mfhi ($t_2,$a_5,$b_0)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_6,$b_0) # mul_add_c(a[6],b[0],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,5*$BNSZ($a0) # r[5]=c3;
mflo ($t_1,$a_6,$b_0)
mfhi ($t_2,$a_6,$b_0)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_5,$b_1) # mul_add_c(a[5],b[1],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $c_3,$c_2,$t_2
mflo ($t_1,$a_5,$b_1)
mfhi ($t_2,$a_5,$b_1)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_4,$b_2) # mul_add_c(a[4],b[2],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_4,$b_2)
mfhi ($t_2,$a_4,$b_2)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_3,$b_3) # mul_add_c(a[3],b[3],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_3,$b_3)
mfhi ($t_2,$a_3,$b_3)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_2,$b_4) # mul_add_c(a[2],b[4],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_2,$b_4)
mfhi ($t_2,$a_2,$b_4)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_1,$b_5) # mul_add_c(a[1],b[5],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_1,$b_5)
mfhi ($t_2,$a_1,$b_5)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_0,$b_6) # mul_add_c(a[0],b[6],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_0,$b_6)
mfhi ($t_2,$a_0,$b_6)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_0,$b_7) # mul_add_c(a[0],b[7],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
$ST $c_1,6*$BNSZ($a0) # r[6]=c1;
mflo ($t_1,$a_0,$b_7)
mfhi ($t_2,$a_0,$b_7)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_1,$b_6) # mul_add_c(a[1],b[6],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $c_1,$c_3,$t_2
mflo ($t_1,$a_1,$b_6)
mfhi ($t_2,$a_1,$b_6)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_2,$b_5) # mul_add_c(a[2],b[5],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_2,$b_5)
mfhi ($t_2,$a_2,$b_5)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_3,$b_4) # mul_add_c(a[3],b[4],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_3,$b_4)
mfhi ($t_2,$a_3,$b_4)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_4,$b_3) # mul_add_c(a[4],b[3],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_4,$b_3)
mfhi ($t_2,$a_4,$b_3)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_5,$b_2) # mul_add_c(a[5],b[2],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_5,$b_2)
mfhi ($t_2,$a_5,$b_2)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_6,$b_1) # mul_add_c(a[6],b[1],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_6,$b_1)
mfhi ($t_2,$a_6,$b_1)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_7,$b_0) # mul_add_c(a[7],b[0],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_7,$b_0)
mfhi ($t_2,$a_7,$b_0)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_7,$b_1) # mul_add_c(a[7],b[1],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
$ST $c_2,7*$BNSZ($a0) # r[7]=c2;
mflo ($t_1,$a_7,$b_1)
mfhi ($t_2,$a_7,$b_1)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_6,$b_2) # mul_add_c(a[6],b[2],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $c_2,$c_1,$t_2
mflo ($t_1,$a_6,$b_2)
mfhi ($t_2,$a_6,$b_2)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_5,$b_3) # mul_add_c(a[5],b[3],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_5,$b_3)
mfhi ($t_2,$a_5,$b_3)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_4,$b_4) # mul_add_c(a[4],b[4],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_4,$b_4)
mfhi ($t_2,$a_4,$b_4)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_3,$b_5) # mul_add_c(a[3],b[5],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_3,$b_5)
mfhi ($t_2,$a_3,$b_5)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_2,$b_6) # mul_add_c(a[2],b[6],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_2,$b_6)
mfhi ($t_2,$a_2,$b_6)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_1,$b_7) # mul_add_c(a[1],b[7],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_1,$b_7)
mfhi ($t_2,$a_1,$b_7)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_2,$b_7) # mul_add_c(a[2],b[7],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,8*$BNSZ($a0) # r[8]=c3;
mflo ($t_1,$a_2,$b_7)
mfhi ($t_2,$a_2,$b_7)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_3,$b_6) # mul_add_c(a[3],b[6],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $c_3,$c_2,$t_2
mflo ($t_1,$a_3,$b_6)
mfhi ($t_2,$a_3,$b_6)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_4,$b_5) # mul_add_c(a[4],b[5],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_4,$b_5)
mfhi ($t_2,$a_4,$b_5)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_5,$b_4) # mul_add_c(a[5],b[4],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_5,$b_4)
mfhi ($t_2,$a_5,$b_4)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_6,$b_3) # mul_add_c(a[6],b[3],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_6,$b_3)
mfhi ($t_2,$a_6,$b_3)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_7,$b_2) # mul_add_c(a[7],b[2],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_7,$b_2)
mfhi ($t_2,$a_7,$b_2)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_7,$b_3) # mul_add_c(a[7],b[3],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
$ST $c_1,9*$BNSZ($a0) # r[9]=c1;
mflo ($t_1,$a_7,$b_3)
mfhi ($t_2,$a_7,$b_3)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_6,$b_4) # mul_add_c(a[6],b[4],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $c_1,$c_3,$t_2
mflo ($t_1,$a_6,$b_4)
mfhi ($t_2,$a_6,$b_4)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_5,$b_5) # mul_add_c(a[5],b[5],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_5,$b_5)
mfhi ($t_2,$a_5,$b_5)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_4,$b_6) # mul_add_c(a[4],b[6],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_4,$b_6)
mfhi ($t_2,$a_4,$b_6)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_3,$b_7) # mul_add_c(a[3],b[7],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_3,$b_7)
mfhi ($t_2,$a_3,$b_7)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_4,$b_7) # mul_add_c(a[4],b[7],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
$ST $c_2,10*$BNSZ($a0) # r[10]=c2;
mflo ($t_1,$a_4,$b_7)
mfhi ($t_2,$a_4,$b_7)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_5,$b_6) # mul_add_c(a[5],b[6],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $c_2,$c_1,$t_2
mflo ($t_1,$a_5,$b_6)
mfhi ($t_2,$a_5,$b_6)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_6,$b_5) # mul_add_c(a[6],b[5],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_6,$b_5)
mfhi ($t_2,$a_6,$b_5)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_7,$b_4) # mul_add_c(a[7],b[4],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
mflo ($t_1,$a_7,$b_4)
mfhi ($t_2,$a_7,$b_4)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_7,$b_5) # mul_add_c(a[7],b[5],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,11*$BNSZ($a0) # r[11]=c3;
mflo ($t_1,$a_7,$b_5)
mfhi ($t_2,$a_7,$b_5)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_6,$b_6) # mul_add_c(a[6],b[6],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $c_3,$c_2,$t_2
mflo ($t_1,$a_6,$b_6)
mfhi ($t_2,$a_6,$b_6)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_5,$b_7) # mul_add_c(a[5],b[7],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_5,$b_7)
mfhi ($t_2,$a_5,$b_7)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_6,$b_7) # mul_add_c(a[6],b[7],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
$ST $c_1,12*$BNSZ($a0) # r[12]=c1;
mflo ($t_1,$a_6,$b_7)
mfhi ($t_2,$a_6,$b_7)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_7,$b_6) # mul_add_c(a[7],b[6],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $c_1,$c_3,$t_2
mflo ($t_1,$a_7,$b_6)
mfhi ($t_2,$a_7,$b_6)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_7,$b_7) # mul_add_c(a[7],b[7],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
$ST $c_2,13*$BNSZ($a0) # r[13]=c2;
mflo ($t_1,$a_7,$b_7)
mfhi ($t_2,$a_7,$b_7)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$ADDU $t_2,$at
$ADDU $c_1,$t_2
$ST $c_3,14*$BNSZ($a0) # r[14]=c3;
$ST $c_1,15*$BNSZ($a0) # r[15]=c1;
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $s5,10*$SZREG($sp)
$REG_L $s4,9*$SZREG($sp)
$REG_L $s3,8*$SZREG($sp)
$REG_L $s2,7*$SZREG($sp)
$REG_L $s1,6*$SZREG($sp)
$REG_L $s0,5*$SZREG($sp)
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
jr $ra
$PTR_ADD $sp,12*$SZREG
___
$code.=<<___ if ($flavour !~ /nubi/i);
$REG_L $s5,5*$SZREG($sp)
$REG_L $s4,4*$SZREG($sp)
$REG_L $s3,3*$SZREG($sp)
$REG_L $s2,2*$SZREG($sp)
$REG_L $s1,1*$SZREG($sp)
$REG_L $s0,0*$SZREG($sp)
jr $ra
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
.end bn_mul_comba8
.align 5
.globl bn_mul_comba4
.ent bn_mul_comba4
bn_mul_comba4:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
$LD $a_0,0($a1)
$LD $b_0,0($a2)
$LD $a_1,$BNSZ($a1)
$LD $a_2,2*$BNSZ($a1)
$MULTU ($a_0,$b_0) # mul_add_c(a[0],b[0],c1,c2,c3);
$LD $a_3,3*$BNSZ($a1)
$LD $b_1,$BNSZ($a2)
$LD $b_2,2*$BNSZ($a2)
$LD $b_3,3*$BNSZ($a2)
mflo ($c_1,$a_0,$b_0)
mfhi ($c_2,$a_0,$b_0)
$ST $c_1,0($a0)
$MULTU ($a_0,$b_1) # mul_add_c(a[0],b[1],c2,c3,c1);
mflo ($t_1,$a_0,$b_1)
mfhi ($t_2,$a_0,$b_1)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_1,$b_0) # mul_add_c(a[1],b[0],c2,c3,c1);
$ADDU $c_3,$t_2,$at
mflo ($t_1,$a_1,$b_0)
mfhi ($t_2,$a_1,$b_0)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_2,$b_0) # mul_add_c(a[2],b[0],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $c_1,$c_3,$t_2
$ST $c_2,$BNSZ($a0)
mflo ($t_1,$a_2,$b_0)
mfhi ($t_2,$a_2,$b_0)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_1,$b_1) # mul_add_c(a[1],b[1],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
mflo ($t_1,$a_1,$b_1)
mfhi ($t_2,$a_1,$b_1)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_0,$b_2) # mul_add_c(a[0],b[2],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $c_2,$c_1,$t_2
mflo ($t_1,$a_0,$b_2)
mfhi ($t_2,$a_0,$b_2)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_0,$b_3) # mul_add_c(a[0],b[3],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,2*$BNSZ($a0)
mflo ($t_1,$a_0,$b_3)
mfhi ($t_2,$a_0,$b_3)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_1,$b_2) # mul_add_c(a[1],b[2],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $c_3,$c_2,$t_2
mflo ($t_1,$a_1,$b_2)
mfhi ($t_2,$a_1,$b_2)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_2,$b_1) # mul_add_c(a[2],b[1],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_2,$b_1)
mfhi ($t_2,$a_2,$b_1)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_3,$b_0) # mul_add_c(a[3],b[0],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
mflo ($t_1,$a_3,$b_0)
mfhi ($t_2,$a_3,$b_0)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_3,$b_1) # mul_add_c(a[3],b[1],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
$ST $c_1,3*$BNSZ($a0)
mflo ($t_1,$a_3,$b_1)
mfhi ($t_2,$a_3,$b_1)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_2,$b_2) # mul_add_c(a[2],b[2],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $c_1,$c_3,$t_2
mflo ($t_1,$a_2,$b_2)
mfhi ($t_2,$a_2,$b_2)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_1,$b_3) # mul_add_c(a[1],b[3],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
mflo ($t_1,$a_1,$b_3)
mfhi ($t_2,$a_1,$b_3)
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_2,$b_3) # mul_add_c(a[2],b[3],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
$ST $c_2,4*$BNSZ($a0)
mflo ($t_1,$a_2,$b_3)
mfhi ($t_2,$a_2,$b_3)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_3,$b_2) # mul_add_c(a[3],b[2],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $c_2,$c_1,$t_2
mflo ($t_1,$a_3,$b_2)
mfhi ($t_2,$a_3,$b_2)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_3,$b_3) # mul_add_c(a[3],b[3],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,5*$BNSZ($a0)
mflo ($t_1,$a_3,$b_3)
mfhi ($t_2,$a_3,$b_3)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$ADDU $t_2,$at
$ADDU $c_2,$t_2
$ST $c_1,6*$BNSZ($a0)
$ST $c_2,7*$BNSZ($a0)
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
nop
.end bn_mul_comba4
___
($a_4,$a_5,$a_6,$a_7)=($b_0,$b_1,$b_2,$b_3);
sub add_c2 () {
my ($hi,$lo,$c0,$c1,$c2,
$warm, # !$warm denotes first call with specific sequence of
# $c_[XYZ] when there is no Z-carry to accumulate yet;
$an,$bn # these two are arguments for multiplication which
# result is used in *next* step [which is why it's
# commented as "forward multiplication" below];
)=@_;
$code.=<<___;
$ADDU $c0,$lo
sltu $at,$c0,$lo
$MULTU ($an,$bn) # forward multiplication
$ADDU $c0,$lo
$ADDU $at,$hi
sltu $lo,$c0,$lo
$ADDU $c1,$at
$ADDU $hi,$lo
___
$code.=<<___ if (!$warm);
sltu $c2,$c1,$at
$ADDU $c1,$hi
___
$code.=<<___ if ($warm);
sltu $at,$c1,$at
$ADDU $c1,$hi
$ADDU $c2,$at
___
$code.=<<___;
sltu $hi,$c1,$hi
$ADDU $c2,$hi
mflo ($lo,$an,$bn)
mfhi ($hi,$an,$bn)
___
}
$code.=<<___;
.align 5
.globl bn_sqr_comba8
.ent bn_sqr_comba8
bn_sqr_comba8:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
$LD $a_0,0($a1)
$LD $a_1,$BNSZ($a1)
$LD $a_2,2*$BNSZ($a1)
$LD $a_3,3*$BNSZ($a1)
$MULTU ($a_0,$a_0) # mul_add_c(a[0],b[0],c1,c2,c3);
$LD $a_4,4*$BNSZ($a1)
$LD $a_5,5*$BNSZ($a1)
$LD $a_6,6*$BNSZ($a1)
$LD $a_7,7*$BNSZ($a1)
mflo ($c_1,$a_0,$a_0)
mfhi ($c_2,$a_0,$a_0)
$ST $c_1,0($a0)
$MULTU ($a_0,$a_1) # mul_add_c2(a[0],b[1],c2,c3,c1);
mflo ($t_1,$a_0,$a_1)
mfhi ($t_2,$a_0,$a_1)
slt $c_1,$t_2,$zero
$SLL $t_2,1
$MULTU ($a_2,$a_0) # mul_add_c2(a[2],b[0],c3,c1,c2);
slt $a2,$t_1,$zero
$ADDU $t_2,$a2
$SLL $t_1,1
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$ADDU $c_3,$t_2,$at
$ST $c_2,$BNSZ($a0)
mflo ($t_1,$a_2,$a_0)
mfhi ($t_2,$a_2,$a_0)
___
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
$a_1,$a_1); # mul_add_c(a[1],b[1],c3,c1,c2);
$code.=<<___;
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_0,$a_3) # mul_add_c2(a[0],b[3],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,2*$BNSZ($a0)
mflo ($t_1,$a_0,$a_3)
mfhi ($t_2,$a_0,$a_3)
___
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
$a_1,$a_2); # mul_add_c2(a[1],b[2],c1,c2,c3);
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
$a_4,$a_0); # mul_add_c2(a[4],b[0],c2,c3,c1);
$code.=<<___;
$ST $c_1,3*$BNSZ($a0)
___
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
$a_3,$a_1); # mul_add_c2(a[3],b[1],c2,c3,c1);
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
$a_2,$a_2); # mul_add_c(a[2],b[2],c2,c3,c1);
$code.=<<___;
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_0,$a_5) # mul_add_c2(a[0],b[5],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
$ST $c_2,4*$BNSZ($a0)
mflo ($t_1,$a_0,$a_5)
mfhi ($t_2,$a_0,$a_5)
___
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
$a_1,$a_4); # mul_add_c2(a[1],b[4],c3,c1,c2);
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
$a_2,$a_3); # mul_add_c2(a[2],b[3],c3,c1,c2);
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
$a_6,$a_0); # mul_add_c2(a[6],b[0],c1,c2,c3);
$code.=<<___;
$ST $c_3,5*$BNSZ($a0)
___
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
$a_5,$a_1); # mul_add_c2(a[5],b[1],c1,c2,c3);
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
$a_4,$a_2); # mul_add_c2(a[4],b[2],c1,c2,c3);
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
$a_3,$a_3); # mul_add_c(a[3],b[3],c1,c2,c3);
$code.=<<___;
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_0,$a_7) # mul_add_c2(a[0],b[7],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
$ST $c_1,6*$BNSZ($a0)
mflo ($t_1,$a_0,$a_7)
mfhi ($t_2,$a_0,$a_7)
___
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
$a_1,$a_6); # mul_add_c2(a[1],b[6],c2,c3,c1);
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
$a_2,$a_5); # mul_add_c2(a[2],b[5],c2,c3,c1);
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
$a_3,$a_4); # mul_add_c2(a[3],b[4],c2,c3,c1);
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
$a_7,$a_1); # mul_add_c2(a[7],b[1],c3,c1,c2);
$code.=<<___;
$ST $c_2,7*$BNSZ($a0)
___
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
$a_6,$a_2); # mul_add_c2(a[6],b[2],c3,c1,c2);
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
$a_5,$a_3); # mul_add_c2(a[5],b[3],c3,c1,c2);
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
$a_4,$a_4); # mul_add_c(a[4],b[4],c3,c1,c2);
$code.=<<___;
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_2,$a_7) # mul_add_c2(a[2],b[7],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,8*$BNSZ($a0)
mflo ($t_1,$a_2,$a_7)
mfhi ($t_2,$a_2,$a_7)
___
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
$a_3,$a_6); # mul_add_c2(a[3],b[6],c1,c2,c3);
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
$a_4,$a_5); # mul_add_c2(a[4],b[5],c1,c2,c3);
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
$a_7,$a_3); # mul_add_c2(a[7],b[3],c2,c3,c1);
$code.=<<___;
$ST $c_1,9*$BNSZ($a0)
___
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
$a_6,$a_4); # mul_add_c2(a[6],b[4],c2,c3,c1);
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,1,
$a_5,$a_5); # mul_add_c(a[5],b[5],c2,c3,c1);
$code.=<<___;
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_4,$a_7) # mul_add_c2(a[4],b[7],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
$ST $c_2,10*$BNSZ($a0)
mflo ($t_1,$a_4,$a_7)
mfhi ($t_2,$a_4,$a_7)
___
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
$a_5,$a_6); # mul_add_c2(a[5],b[6],c3,c1,c2);
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,1,
$a_7,$a_5); # mul_add_c2(a[7],b[5],c1,c2,c3);
$code.=<<___;
$ST $c_3,11*$BNSZ($a0)
___
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
$a_6,$a_6); # mul_add_c(a[6],b[6],c1,c2,c3);
$code.=<<___;
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$MULTU ($a_6,$a_7) # mul_add_c2(a[6],b[7],c2,c3,c1);
$ADDU $t_2,$at
$ADDU $c_2,$t_2
sltu $at,$c_2,$t_2
$ADDU $c_3,$at
$ST $c_1,12*$BNSZ($a0)
mflo ($t_1,$a_6,$a_7)
mfhi ($t_2,$a_6,$a_7)
___
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
$a_7,$a_7); # mul_add_c(a[7],b[7],c3,c1,c2);
$code.=<<___;
$ST $c_2,13*$BNSZ($a0)
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$ADDU $t_2,$at
$ADDU $c_1,$t_2
$ST $c_3,14*$BNSZ($a0)
$ST $c_1,15*$BNSZ($a0)
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
nop
.end bn_sqr_comba8
.align 5
.globl bn_sqr_comba4
.ent bn_sqr_comba4
bn_sqr_comba4:
___
$code.=<<___ if ($flavour =~ /nubi/i);
.frame $sp,6*$SZREG,$ra
.mask 0x8000f008,-$SZREG
.set noreorder
$PTR_SUB $sp,6*$SZREG
$REG_S $ra,5*$SZREG($sp)
$REG_S $t3,4*$SZREG($sp)
$REG_S $t2,3*$SZREG($sp)
$REG_S $t1,2*$SZREG($sp)
$REG_S $t0,1*$SZREG($sp)
$REG_S $gp,0*$SZREG($sp)
___
$code.=<<___;
.set reorder
$LD $a_0,0($a1)
$LD $a_1,$BNSZ($a1)
$MULTU ($a_0,$a_0) # mul_add_c(a[0],b[0],c1,c2,c3);
$LD $a_2,2*$BNSZ($a1)
$LD $a_3,3*$BNSZ($a1)
mflo ($c_1,$a_0,$a_0)
mfhi ($c_2,$a_0,$a_0)
$ST $c_1,0($a0)
$MULTU ($a_0,$a_1) # mul_add_c2(a[0],b[1],c2,c3,c1);
mflo ($t_1,$a_0,$a_1)
mfhi ($t_2,$a_0,$a_1)
slt $c_1,$t_2,$zero
$SLL $t_2,1
$MULTU ($a_2,$a_0) # mul_add_c2(a[2],b[0],c3,c1,c2);
slt $a2,$t_1,$zero
$ADDU $t_2,$a2
$SLL $t_1,1
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$ADDU $c_3,$t_2,$at
$ST $c_2,$BNSZ($a0)
mflo ($t_1,$a_2,$a_0)
mfhi ($t_2,$a_2,$a_0)
___
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
$a_1,$a_1); # mul_add_c(a[1],b[1],c3,c1,c2);
$code.=<<___;
$ADDU $c_3,$t_1
sltu $at,$c_3,$t_1
$MULTU ($a_0,$a_3) # mul_add_c2(a[0],b[3],c1,c2,c3);
$ADDU $t_2,$at
$ADDU $c_1,$t_2
sltu $at,$c_1,$t_2
$ADDU $c_2,$at
$ST $c_3,2*$BNSZ($a0)
mflo ($t_1,$a_0,$a_3)
mfhi ($t_2,$a_0,$a_3)
___
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,0,
$a_1,$a_2); # mul_add_c2(a2[1],b[2],c1,c2,c3);
&add_c2($t_2,$t_1,$c_1,$c_2,$c_3,1,
$a_3,$a_1); # mul_add_c2(a[3],b[1],c2,c3,c1);
$code.=<<___;
$ST $c_1,3*$BNSZ($a0)
___
&add_c2($t_2,$t_1,$c_2,$c_3,$c_1,0,
$a_2,$a_2); # mul_add_c(a[2],b[2],c2,c3,c1);
$code.=<<___;
$ADDU $c_2,$t_1
sltu $at,$c_2,$t_1
$MULTU ($a_2,$a_3) # mul_add_c2(a[2],b[3],c3,c1,c2);
$ADDU $t_2,$at
$ADDU $c_3,$t_2
sltu $at,$c_3,$t_2
$ADDU $c_1,$at
$ST $c_2,4*$BNSZ($a0)
mflo ($t_1,$a_2,$a_3)
mfhi ($t_2,$a_2,$a_3)
___
&add_c2($t_2,$t_1,$c_3,$c_1,$c_2,0,
$a_3,$a_3); # mul_add_c(a[3],b[3],c1,c2,c3);
$code.=<<___;
$ST $c_3,5*$BNSZ($a0)
$ADDU $c_1,$t_1
sltu $at,$c_1,$t_1
$ADDU $t_2,$at
$ADDU $c_2,$t_2
$ST $c_1,6*$BNSZ($a0)
$ST $c_2,7*$BNSZ($a0)
.set noreorder
___
$code.=<<___ if ($flavour =~ /nubi/i);
$REG_L $t3,4*$SZREG($sp)
$REG_L $t2,3*$SZREG($sp)
$REG_L $t1,2*$SZREG($sp)
$REG_L $t0,1*$SZREG($sp)
$REG_L $gp,0*$SZREG($sp)
$PTR_ADD $sp,6*$SZREG
___
$code.=<<___;
jr $ra
nop
.end bn_sqr_comba4
___
print $code;
close STDOUT;
diff --git a/crypto/bn/asm/ppc.pl b/crypto/bn/asm/ppc.pl
index e37068192f2f..d6d4e66f92e9 100644
--- a/crypto/bn/asm/ppc.pl
+++ b/crypto/bn/asm/ppc.pl
@@ -1,2011 +1,2012 @@
#! /usr/bin/env perl
-# Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
# Implemented as a Perl wrapper as we want to support several different
# architectures with single file. We pick up the target based on the
# file name we are asked to generate.
#
# It should be noted though that this perl code is nothing like
# <openssl>/crypto/perlasm/x86*. In this case perl is used pretty much
# as pre-processor to cover for platform differences in name decoration,
# linker tables, 32-/64-bit instruction sets...
#
# As you might know there're several PowerPC ABI in use. Most notably
# Linux and AIX use different 32-bit ABIs. Good news are that these ABIs
# are similar enough to implement leaf(!) functions, which would be ABI
# neutral. And that's what you find here: ABI neutral leaf functions.
# In case you wonder what that is...
#
# AIX performance
#
# MEASUREMENTS WITH cc ON a 200 MhZ PowerPC 604e.
#
# The following is the performance of 32-bit compiler
# generated code:
#
# OpenSSL 0.9.6c 21 dec 2001
# built on: Tue Jun 11 11:06:51 EDT 2002
# options:bn(64,32) ...
#compiler: cc -DTHREADS -DAIX -DB_ENDIAN -DBN_LLONG -O3
# sign verify sign/s verify/s
#rsa 512 bits 0.0098s 0.0009s 102.0 1170.6
#rsa 1024 bits 0.0507s 0.0026s 19.7 387.5
#rsa 2048 bits 0.3036s 0.0085s 3.3 117.1
#rsa 4096 bits 2.0040s 0.0299s 0.5 33.4
#dsa 512 bits 0.0087s 0.0106s 114.3 94.5
#dsa 1024 bits 0.0256s 0.0313s 39.0 32.0
#
# Same benchmark with this assembler code:
#
#rsa 512 bits 0.0056s 0.0005s 178.6 2049.2
#rsa 1024 bits 0.0283s 0.0015s 35.3 674.1
#rsa 2048 bits 0.1744s 0.0050s 5.7 201.2
#rsa 4096 bits 1.1644s 0.0179s 0.9 55.7
#dsa 512 bits 0.0052s 0.0062s 191.6 162.0
#dsa 1024 bits 0.0149s 0.0180s 67.0 55.5
#
# Number of operations increases by at almost 75%
#
# Here are performance numbers for 64-bit compiler
# generated code:
#
# OpenSSL 0.9.6g [engine] 9 Aug 2002
# built on: Fri Apr 18 16:59:20 EDT 2003
# options:bn(64,64) ...
# compiler: cc -DTHREADS -D_REENTRANT -q64 -DB_ENDIAN -O3
# sign verify sign/s verify/s
#rsa 512 bits 0.0028s 0.0003s 357.1 3844.4
#rsa 1024 bits 0.0148s 0.0008s 67.5 1239.7
#rsa 2048 bits 0.0963s 0.0028s 10.4 353.0
#rsa 4096 bits 0.6538s 0.0102s 1.5 98.1
#dsa 512 bits 0.0026s 0.0032s 382.5 313.7
#dsa 1024 bits 0.0081s 0.0099s 122.8 100.6
#
# Same benchmark with this assembler code:
#
#rsa 512 bits 0.0020s 0.0002s 510.4 6273.7
#rsa 1024 bits 0.0088s 0.0005s 114.1 2128.3
#rsa 2048 bits 0.0540s 0.0016s 18.5 622.5
#rsa 4096 bits 0.3700s 0.0058s 2.7 171.0
#dsa 512 bits 0.0016s 0.0020s 610.7 507.1
#dsa 1024 bits 0.0047s 0.0058s 212.5 173.2
#
# Again, performance increases by at about 75%
#
# Mac OS X, Apple G5 1.8GHz (Note this is 32 bit code)
# OpenSSL 0.9.7c 30 Sep 2003
#
# Original code.
#
#rsa 512 bits 0.0011s 0.0001s 906.1 11012.5
#rsa 1024 bits 0.0060s 0.0003s 166.6 3363.1
#rsa 2048 bits 0.0370s 0.0010s 27.1 982.4
#rsa 4096 bits 0.2426s 0.0036s 4.1 280.4
#dsa 512 bits 0.0010s 0.0012s 1038.1 841.5
#dsa 1024 bits 0.0030s 0.0037s 329.6 269.7
#dsa 2048 bits 0.0101s 0.0127s 98.9 78.6
#
# Same benchmark with this assembler code:
#
#rsa 512 bits 0.0007s 0.0001s 1416.2 16645.9
#rsa 1024 bits 0.0036s 0.0002s 274.4 5380.6
#rsa 2048 bits 0.0222s 0.0006s 45.1 1589.5
#rsa 4096 bits 0.1469s 0.0022s 6.8 449.6
#dsa 512 bits 0.0006s 0.0007s 1664.2 1376.2
#dsa 1024 bits 0.0018s 0.0023s 545.0 442.2
#dsa 2048 bits 0.0061s 0.0075s 163.5 132.8
#
# Performance increase of ~60%
# Based on submission from Suresh N. Chari of IBM
$flavour = shift;
if ($flavour =~ /32/) {
$BITS= 32;
$BNSZ= $BITS/8;
$ISA= "\"ppc\"";
$LD= "lwz"; # load
$LDU= "lwzu"; # load and update
$ST= "stw"; # store
$STU= "stwu"; # store and update
$UMULL= "mullw"; # unsigned multiply low
$UMULH= "mulhwu"; # unsigned multiply high
$UDIV= "divwu"; # unsigned divide
$UCMPI= "cmplwi"; # unsigned compare with immediate
$UCMP= "cmplw"; # unsigned compare
$CNTLZ= "cntlzw"; # count leading zeros
$SHL= "slw"; # shift left
$SHR= "srw"; # unsigned shift right
$SHRI= "srwi"; # unsigned shift right by immediate
$SHLI= "slwi"; # shift left by immediate
$CLRU= "clrlwi"; # clear upper bits
$INSR= "insrwi"; # insert right
$ROTL= "rotlwi"; # rotate left by immediate
$TR= "tw"; # conditional trap
} elsif ($flavour =~ /64/) {
$BITS= 64;
$BNSZ= $BITS/8;
$ISA= "\"ppc64\"";
# same as above, but 64-bit mnemonics...
$LD= "ld"; # load
$LDU= "ldu"; # load and update
$ST= "std"; # store
$STU= "stdu"; # store and update
$UMULL= "mulld"; # unsigned multiply low
$UMULH= "mulhdu"; # unsigned multiply high
$UDIV= "divdu"; # unsigned divide
$UCMPI= "cmpldi"; # unsigned compare with immediate
$UCMP= "cmpld"; # unsigned compare
$CNTLZ= "cntlzd"; # count leading zeros
$SHL= "sld"; # shift left
$SHR= "srd"; # unsigned shift right
$SHRI= "srdi"; # unsigned shift right by immediate
$SHLI= "sldi"; # shift left by immediate
$CLRU= "clrldi"; # clear upper bits
$INSR= "insrdi"; # insert right
$ROTL= "rotldi"; # rotate left by immediate
$TR= "td"; # conditional trap
} else { die "nonsense $flavour"; }
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}ppc-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/ppc-xlate.pl" and -f $xlate) or
die "can't locate ppc-xlate.pl";
open STDOUT,"| $^X $xlate $flavour ".shift || die "can't call $xlate: $!";
$data=<<EOF;
#--------------------------------------------------------------------
#
#
#
#
# File: ppc32.s
#
# Created by: Suresh Chari
# IBM Thomas J. Watson Research Library
# Hawthorne, NY
#
#
# Description: Optimized assembly routines for OpenSSL crypto
# on the 32 bitPowerPC platform.
#
#
# Version History
#
# 2. Fixed bn_add,bn_sub and bn_div_words, added comments,
# cleaned up code. Also made a single version which can
# be used for both the AIX and Linux compilers. See NOTE
# below.
# 12/05/03 Suresh Chari
# (with lots of help from) Andy Polyakov
##
# 1. Initial version 10/20/02 Suresh Chari
#
#
# The following file works for the xlc,cc
# and gcc compilers.
#
# NOTE: To get the file to link correctly with the gcc compiler
# you have to change the names of the routines and remove
# the first .(dot) character. This should automatically
# be done in the build process.
#
# Hand optimized assembly code for the following routines
#
# bn_sqr_comba4
# bn_sqr_comba8
# bn_mul_comba4
# bn_mul_comba8
# bn_sub_words
# bn_add_words
# bn_div_words
# bn_sqr_words
# bn_mul_words
# bn_mul_add_words
#
# NOTE: It is possible to optimize this code more for
# specific PowerPC or Power architectures. On the Northstar
# architecture the optimizations in this file do
# NOT provide much improvement.
#
# If you have comments or suggestions to improve code send
# me a note at schari\@us.ibm.com
#
#--------------------------------------------------------------------------
#
# Defines to be used in the assembly code.
#
#.set r0,0 # we use it as storage for value of 0
#.set SP,1 # preserved
#.set RTOC,2 # preserved
#.set r3,3 # 1st argument/return value
#.set r4,4 # 2nd argument/volatile register
#.set r5,5 # 3rd argument/volatile register
#.set r6,6 # ...
#.set r7,7
#.set r8,8
#.set r9,9
#.set r10,10
#.set r11,11
#.set r12,12
#.set r13,13 # not used, nor any other "below" it...
# Declare function names to be global
# NOTE: For gcc these names MUST be changed to remove
# the first . i.e. for example change ".bn_sqr_comba4"
# to "bn_sqr_comba4". This should be automatically done
# in the build.
.globl .bn_sqr_comba4
.globl .bn_sqr_comba8
.globl .bn_mul_comba4
.globl .bn_mul_comba8
.globl .bn_sub_words
.globl .bn_add_words
.globl .bn_div_words
.globl .bn_sqr_words
.globl .bn_mul_words
.globl .bn_mul_add_words
# .text section
.machine "any"
+ .text
#
# NOTE: The following label name should be changed to
# "bn_sqr_comba4" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_sqr_comba4:
#
# Optimized version of bn_sqr_comba4.
#
# void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a)
# r3 contains r
# r4 contains a
#
# Freely use registers r5,r6,r7,r8,r9,r10,r11 as follows:
#
# r5,r6 are the two BN_ULONGs being multiplied.
# r7,r8 are the results of the 32x32 giving 64 bit multiply.
# r9,r10, r11 are the equivalents of c1,c2, c3.
# Here's the assembly
#
#
xor r0,r0,r0 # set r0 = 0. Used in the addze
# instructions below
#sqr_add_c(a,0,c1,c2,c3)
$LD r5,`0*$BNSZ`(r4)
$UMULL r9,r5,r5
$UMULH r10,r5,r5 #in first iteration. No need
#to add since c1=c2=c3=0.
# Note c3(r11) is NOT set to 0
# but will be.
$ST r9,`0*$BNSZ`(r3) # r[0]=c1;
# sqr_add_c2(a,1,0,c2,c3,c1);
$LD r6,`1*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r7,r7,r7 # compute (r7,r8)=2*(r7,r8)
adde r8,r8,r8
addze r9,r0 # catch carry if any.
# r9= r0(=0) and carry
addc r10,r7,r10 # now add to temp result.
addze r11,r8 # r8 added to r11 which is 0
addze r9,r9
$ST r10,`1*$BNSZ`(r3) #r[1]=c2;
#sqr_add_c(a,1,c3,c1,c2)
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r0
#sqr_add_c2(a,2,0,c3,c1,c2)
$LD r6,`2*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r7,r7,r7
adde r8,r8,r8
addze r10,r10
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
$ST r11,`2*$BNSZ`(r3) #r[2]=c3
#sqr_add_c2(a,3,0,c1,c2,c3);
$LD r6,`3*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r7,r7,r7
adde r8,r8,r8
addze r11,r0
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
#sqr_add_c2(a,2,1,c1,c2,c3);
$LD r5,`1*$BNSZ`(r4)
$LD r6,`2*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r7,r7,r7
adde r8,r8,r8
addze r11,r11
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
$ST r9,`3*$BNSZ`(r3) #r[3]=c1
#sqr_add_c(a,2,c2,c3,c1);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r0
#sqr_add_c2(a,3,1,c2,c3,c1);
$LD r6,`3*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r7,r7,r7
adde r8,r8,r8
addze r9,r9
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
$ST r10,`4*$BNSZ`(r3) #r[4]=c2
#sqr_add_c2(a,3,2,c3,c1,c2);
$LD r5,`2*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r7,r7,r7
adde r8,r8,r8
addze r10,r0
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
$ST r11,`5*$BNSZ`(r3) #r[5] = c3
#sqr_add_c(a,3,c1,c2,c3);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r9,r7,r9
adde r10,r8,r10
$ST r9,`6*$BNSZ`(r3) #r[6]=c1
$ST r10,`7*$BNSZ`(r3) #r[7]=c2
blr
.long 0
.byte 0,12,0x14,0,0,0,2,0
.long 0
.size .bn_sqr_comba4,.-.bn_sqr_comba4
#
# NOTE: The following label name should be changed to
# "bn_sqr_comba8" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_sqr_comba8:
#
# This is an optimized version of the bn_sqr_comba8 routine.
# Tightly uses the adde instruction
#
#
# void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a)
# r3 contains r
# r4 contains a
#
# Freely use registers r5,r6,r7,r8,r9,r10,r11 as follows:
#
# r5,r6 are the two BN_ULONGs being multiplied.
# r7,r8 are the results of the 32x32 giving 64 bit multiply.
# r9,r10, r11 are the equivalents of c1,c2, c3.
#
# Possible optimization of loading all 8 longs of a into registers
# doesn't provide any speedup
#
xor r0,r0,r0 #set r0 = 0.Used in addze
#instructions below.
#sqr_add_c(a,0,c1,c2,c3);
$LD r5,`0*$BNSZ`(r4)
$UMULL r9,r5,r5 #1st iteration: no carries.
$UMULH r10,r5,r5
$ST r9,`0*$BNSZ`(r3) # r[0]=c1;
#sqr_add_c2(a,1,0,c2,c3,c1);
$LD r6,`1*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10 #add the two register number
adde r11,r8,r0 # (r8,r7) to the three register
addze r9,r0 # number (r9,r11,r10).NOTE:r0=0
addc r10,r7,r10 #add the two register number
adde r11,r8,r11 # (r8,r7) to the three register
addze r9,r9 # number (r9,r11,r10).
$ST r10,`1*$BNSZ`(r3) # r[1]=c2
#sqr_add_c(a,1,c3,c1,c2);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r0
#sqr_add_c2(a,2,0,c3,c1,c2);
$LD r6,`2*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
$ST r11,`2*$BNSZ`(r3) #r[2]=c3
#sqr_add_c2(a,3,0,c1,c2,c3);
$LD r6,`3*$BNSZ`(r4) #r6 = a[3]. r5 is already a[0].
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r0
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
#sqr_add_c2(a,2,1,c1,c2,c3);
$LD r5,`1*$BNSZ`(r4)
$LD r6,`2*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
$ST r9,`3*$BNSZ`(r3) #r[3]=c1;
#sqr_add_c(a,2,c2,c3,c1);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r0
#sqr_add_c2(a,3,1,c2,c3,c1);
$LD r6,`3*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
#sqr_add_c2(a,4,0,c2,c3,c1);
$LD r5,`0*$BNSZ`(r4)
$LD r6,`4*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
$ST r10,`4*$BNSZ`(r3) #r[4]=c2;
#sqr_add_c2(a,5,0,c3,c1,c2);
$LD r6,`5*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r0
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
#sqr_add_c2(a,4,1,c3,c1,c2);
$LD r5,`1*$BNSZ`(r4)
$LD r6,`4*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
#sqr_add_c2(a,3,2,c3,c1,c2);
$LD r5,`2*$BNSZ`(r4)
$LD r6,`3*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
$ST r11,`5*$BNSZ`(r3) #r[5]=c3;
#sqr_add_c(a,3,c1,c2,c3);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r0
#sqr_add_c2(a,4,2,c1,c2,c3);
$LD r6,`4*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
#sqr_add_c2(a,5,1,c1,c2,c3);
$LD r5,`1*$BNSZ`(r4)
$LD r6,`5*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
#sqr_add_c2(a,6,0,c1,c2,c3);
$LD r5,`0*$BNSZ`(r4)
$LD r6,`6*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
$ST r9,`6*$BNSZ`(r3) #r[6]=c1;
#sqr_add_c2(a,7,0,c2,c3,c1);
$LD r6,`7*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r0
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
#sqr_add_c2(a,6,1,c2,c3,c1);
$LD r5,`1*$BNSZ`(r4)
$LD r6,`6*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
#sqr_add_c2(a,5,2,c2,c3,c1);
$LD r5,`2*$BNSZ`(r4)
$LD r6,`5*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
#sqr_add_c2(a,4,3,c2,c3,c1);
$LD r5,`3*$BNSZ`(r4)
$LD r6,`4*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
$ST r10,`7*$BNSZ`(r3) #r[7]=c2;
#sqr_add_c(a,4,c3,c1,c2);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r0
#sqr_add_c2(a,5,3,c3,c1,c2);
$LD r6,`5*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
#sqr_add_c2(a,6,2,c3,c1,c2);
$LD r5,`2*$BNSZ`(r4)
$LD r6,`6*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
#sqr_add_c2(a,7,1,c3,c1,c2);
$LD r5,`1*$BNSZ`(r4)
$LD r6,`7*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
$ST r11,`8*$BNSZ`(r3) #r[8]=c3;
#sqr_add_c2(a,7,2,c1,c2,c3);
$LD r5,`2*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r0
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
#sqr_add_c2(a,6,3,c1,c2,c3);
$LD r5,`3*$BNSZ`(r4)
$LD r6,`6*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
#sqr_add_c2(a,5,4,c1,c2,c3);
$LD r5,`4*$BNSZ`(r4)
$LD r6,`5*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
$ST r9,`9*$BNSZ`(r3) #r[9]=c1;
#sqr_add_c(a,5,c2,c3,c1);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r0
#sqr_add_c2(a,6,4,c2,c3,c1);
$LD r6,`6*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
#sqr_add_c2(a,7,3,c2,c3,c1);
$LD r5,`3*$BNSZ`(r4)
$LD r6,`7*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
$ST r10,`10*$BNSZ`(r3) #r[10]=c2;
#sqr_add_c2(a,7,4,c3,c1,c2);
$LD r5,`4*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r0
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
#sqr_add_c2(a,6,5,c3,c1,c2);
$LD r5,`5*$BNSZ`(r4)
$LD r6,`6*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
addc r11,r7,r11
adde r9,r8,r9
addze r10,r10
$ST r11,`11*$BNSZ`(r3) #r[11]=c3;
#sqr_add_c(a,6,c1,c2,c3);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r0
#sqr_add_c2(a,7,5,c1,c2,c3)
$LD r6,`7*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
addc r9,r7,r9
adde r10,r8,r10
addze r11,r11
$ST r9,`12*$BNSZ`(r3) #r[12]=c1;
#sqr_add_c2(a,7,6,c2,c3,c1)
$LD r5,`6*$BNSZ`(r4)
$UMULL r7,r5,r6
$UMULH r8,r5,r6
addc r10,r7,r10
adde r11,r8,r11
addze r9,r0
addc r10,r7,r10
adde r11,r8,r11
addze r9,r9
$ST r10,`13*$BNSZ`(r3) #r[13]=c2;
#sqr_add_c(a,7,c3,c1,c2);
$UMULL r7,r6,r6
$UMULH r8,r6,r6
addc r11,r7,r11
adde r9,r8,r9
$ST r11,`14*$BNSZ`(r3) #r[14]=c3;
$ST r9, `15*$BNSZ`(r3) #r[15]=c1;
blr
.long 0
.byte 0,12,0x14,0,0,0,2,0
.long 0
.size .bn_sqr_comba8,.-.bn_sqr_comba8
#
# NOTE: The following label name should be changed to
# "bn_mul_comba4" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_mul_comba4:
#
# This is an optimized version of the bn_mul_comba4 routine.
#
# void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
# r3 contains r
# r4 contains a
# r5 contains b
# r6, r7 are the 2 BN_ULONGs being multiplied.
# r8, r9 are the results of the 32x32 giving 64 multiply.
# r10, r11, r12 are the equivalents of c1, c2, and c3.
#
xor r0,r0,r0 #r0=0. Used in addze below.
#mul_add_c(a[0],b[0],c1,c2,c3);
$LD r6,`0*$BNSZ`(r4)
$LD r7,`0*$BNSZ`(r5)
$UMULL r10,r6,r7
$UMULH r11,r6,r7
$ST r10,`0*$BNSZ`(r3) #r[0]=c1
#mul_add_c(a[0],b[1],c2,c3,c1);
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r8,r11
adde r12,r9,r0
addze r10,r0
#mul_add_c(a[1],b[0],c2,c3,c1);
$LD r6, `1*$BNSZ`(r4)
$LD r7, `0*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r8,r11
adde r12,r9,r12
addze r10,r10
$ST r11,`1*$BNSZ`(r3) #r[1]=c2
#mul_add_c(a[2],b[0],c3,c1,c2);
$LD r6,`2*$BNSZ`(r4)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r8,r12
adde r10,r9,r10
addze r11,r0
#mul_add_c(a[1],b[1],c3,c1,c2);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r8,r12
adde r10,r9,r10
addze r11,r11
#mul_add_c(a[0],b[2],c3,c1,c2);
$LD r6,`0*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r8,r12
adde r10,r9,r10
addze r11,r11
$ST r12,`2*$BNSZ`(r3) #r[2]=c3
#mul_add_c(a[0],b[3],c1,c2,c3);
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r8,r10
adde r11,r9,r11
addze r12,r0
#mul_add_c(a[1],b[2],c1,c2,c3);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r8,r10
adde r11,r9,r11
addze r12,r12
#mul_add_c(a[2],b[1],c1,c2,c3);
$LD r6,`2*$BNSZ`(r4)
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r8,r10
adde r11,r9,r11
addze r12,r12
#mul_add_c(a[3],b[0],c1,c2,c3);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`0*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r8,r10
adde r11,r9,r11
addze r12,r12
$ST r10,`3*$BNSZ`(r3) #r[3]=c1
#mul_add_c(a[3],b[1],c2,c3,c1);
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r8,r11
adde r12,r9,r12
addze r10,r0
#mul_add_c(a[2],b[2],c2,c3,c1);
$LD r6,`2*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r8,r11
adde r12,r9,r12
addze r10,r10
#mul_add_c(a[1],b[3],c2,c3,c1);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r8,r11
adde r12,r9,r12
addze r10,r10
$ST r11,`4*$BNSZ`(r3) #r[4]=c2
#mul_add_c(a[2],b[3],c3,c1,c2);
$LD r6,`2*$BNSZ`(r4)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r8,r12
adde r10,r9,r10
addze r11,r0
#mul_add_c(a[3],b[2],c3,c1,c2);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r8,r12
adde r10,r9,r10
addze r11,r11
$ST r12,`5*$BNSZ`(r3) #r[5]=c3
#mul_add_c(a[3],b[3],c1,c2,c3);
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r8,r10
adde r11,r9,r11
$ST r10,`6*$BNSZ`(r3) #r[6]=c1
$ST r11,`7*$BNSZ`(r3) #r[7]=c2
blr
.long 0
.byte 0,12,0x14,0,0,0,3,0
.long 0
.size .bn_mul_comba4,.-.bn_mul_comba4
#
# NOTE: The following label name should be changed to
# "bn_mul_comba8" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_mul_comba8:
#
# Optimized version of the bn_mul_comba8 routine.
#
# void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
# r3 contains r
# r4 contains a
# r5 contains b
# r6, r7 are the 2 BN_ULONGs being multiplied.
# r8, r9 are the results of the 32x32 giving 64 multiply.
# r10, r11, r12 are the equivalents of c1, c2, and c3.
#
xor r0,r0,r0 #r0=0. Used in addze below.
#mul_add_c(a[0],b[0],c1,c2,c3);
$LD r6,`0*$BNSZ`(r4) #a[0]
$LD r7,`0*$BNSZ`(r5) #b[0]
$UMULL r10,r6,r7
$UMULH r11,r6,r7
$ST r10,`0*$BNSZ`(r3) #r[0]=c1;
#mul_add_c(a[0],b[1],c2,c3,c1);
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
addze r12,r9 # since we didn't set r12 to zero before.
addze r10,r0
#mul_add_c(a[1],b[0],c2,c3,c1);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`0*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
$ST r11,`1*$BNSZ`(r3) #r[1]=c2;
#mul_add_c(a[2],b[0],c3,c1,c2);
$LD r6,`2*$BNSZ`(r4)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r0
#mul_add_c(a[1],b[1],c3,c1,c2);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[0],b[2],c3,c1,c2);
$LD r6,`0*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
$ST r12,`2*$BNSZ`(r3) #r[2]=c3;
#mul_add_c(a[0],b[3],c1,c2,c3);
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r0
#mul_add_c(a[1],b[2],c1,c2,c3);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[2],b[1],c1,c2,c3);
$LD r6,`2*$BNSZ`(r4)
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[3],b[0],c1,c2,c3);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`0*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
$ST r10,`3*$BNSZ`(r3) #r[3]=c1;
#mul_add_c(a[4],b[0],c2,c3,c1);
$LD r6,`4*$BNSZ`(r4)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r0
#mul_add_c(a[3],b[1],c2,c3,c1);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[2],b[2],c2,c3,c1);
$LD r6,`2*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[1],b[3],c2,c3,c1);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[0],b[4],c2,c3,c1);
$LD r6,`0*$BNSZ`(r4)
$LD r7,`4*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
$ST r11,`4*$BNSZ`(r3) #r[4]=c2;
#mul_add_c(a[0],b[5],c3,c1,c2);
$LD r7,`5*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r0
#mul_add_c(a[1],b[4],c3,c1,c2);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`4*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[2],b[3],c3,c1,c2);
$LD r6,`2*$BNSZ`(r4)
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[3],b[2],c3,c1,c2);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[4],b[1],c3,c1,c2);
$LD r6,`4*$BNSZ`(r4)
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[5],b[0],c3,c1,c2);
$LD r6,`5*$BNSZ`(r4)
$LD r7,`0*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
$ST r12,`5*$BNSZ`(r3) #r[5]=c3;
#mul_add_c(a[6],b[0],c1,c2,c3);
$LD r6,`6*$BNSZ`(r4)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r0
#mul_add_c(a[5],b[1],c1,c2,c3);
$LD r6,`5*$BNSZ`(r4)
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[4],b[2],c1,c2,c3);
$LD r6,`4*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[3],b[3],c1,c2,c3);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[2],b[4],c1,c2,c3);
$LD r6,`2*$BNSZ`(r4)
$LD r7,`4*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[1],b[5],c1,c2,c3);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`5*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[0],b[6],c1,c2,c3);
$LD r6,`0*$BNSZ`(r4)
$LD r7,`6*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
$ST r10,`6*$BNSZ`(r3) #r[6]=c1;
#mul_add_c(a[0],b[7],c2,c3,c1);
$LD r7,`7*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r0
#mul_add_c(a[1],b[6],c2,c3,c1);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`6*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[2],b[5],c2,c3,c1);
$LD r6,`2*$BNSZ`(r4)
$LD r7,`5*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[3],b[4],c2,c3,c1);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`4*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[4],b[3],c2,c3,c1);
$LD r6,`4*$BNSZ`(r4)
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[5],b[2],c2,c3,c1);
$LD r6,`5*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[6],b[1],c2,c3,c1);
$LD r6,`6*$BNSZ`(r4)
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[7],b[0],c2,c3,c1);
$LD r6,`7*$BNSZ`(r4)
$LD r7,`0*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
$ST r11,`7*$BNSZ`(r3) #r[7]=c2;
#mul_add_c(a[7],b[1],c3,c1,c2);
$LD r7,`1*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r0
#mul_add_c(a[6],b[2],c3,c1,c2);
$LD r6,`6*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[5],b[3],c3,c1,c2);
$LD r6,`5*$BNSZ`(r4)
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[4],b[4],c3,c1,c2);
$LD r6,`4*$BNSZ`(r4)
$LD r7,`4*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[3],b[5],c3,c1,c2);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`5*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[2],b[6],c3,c1,c2);
$LD r6,`2*$BNSZ`(r4)
$LD r7,`6*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[1],b[7],c3,c1,c2);
$LD r6,`1*$BNSZ`(r4)
$LD r7,`7*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
$ST r12,`8*$BNSZ`(r3) #r[8]=c3;
#mul_add_c(a[2],b[7],c1,c2,c3);
$LD r6,`2*$BNSZ`(r4)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r0
#mul_add_c(a[3],b[6],c1,c2,c3);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`6*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[4],b[5],c1,c2,c3);
$LD r6,`4*$BNSZ`(r4)
$LD r7,`5*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[5],b[4],c1,c2,c3);
$LD r6,`5*$BNSZ`(r4)
$LD r7,`4*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[6],b[3],c1,c2,c3);
$LD r6,`6*$BNSZ`(r4)
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[7],b[2],c1,c2,c3);
$LD r6,`7*$BNSZ`(r4)
$LD r7,`2*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
$ST r10,`9*$BNSZ`(r3) #r[9]=c1;
#mul_add_c(a[7],b[3],c2,c3,c1);
$LD r7,`3*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r0
#mul_add_c(a[6],b[4],c2,c3,c1);
$LD r6,`6*$BNSZ`(r4)
$LD r7,`4*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[5],b[5],c2,c3,c1);
$LD r6,`5*$BNSZ`(r4)
$LD r7,`5*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[4],b[6],c2,c3,c1);
$LD r6,`4*$BNSZ`(r4)
$LD r7,`6*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
#mul_add_c(a[3],b[7],c2,c3,c1);
$LD r6,`3*$BNSZ`(r4)
$LD r7,`7*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
$ST r11,`10*$BNSZ`(r3) #r[10]=c2;
#mul_add_c(a[4],b[7],c3,c1,c2);
$LD r6,`4*$BNSZ`(r4)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r0
#mul_add_c(a[5],b[6],c3,c1,c2);
$LD r6,`5*$BNSZ`(r4)
$LD r7,`6*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[6],b[5],c3,c1,c2);
$LD r6,`6*$BNSZ`(r4)
$LD r7,`5*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
#mul_add_c(a[7],b[4],c3,c1,c2);
$LD r6,`7*$BNSZ`(r4)
$LD r7,`4*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
addze r11,r11
$ST r12,`11*$BNSZ`(r3) #r[11]=c3;
#mul_add_c(a[7],b[5],c1,c2,c3);
$LD r7,`5*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r0
#mul_add_c(a[6],b[6],c1,c2,c3);
$LD r6,`6*$BNSZ`(r4)
$LD r7,`6*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
#mul_add_c(a[5],b[7],c1,c2,c3);
$LD r6,`5*$BNSZ`(r4)
$LD r7,`7*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r10,r10,r8
adde r11,r11,r9
addze r12,r12
$ST r10,`12*$BNSZ`(r3) #r[12]=c1;
#mul_add_c(a[6],b[7],c2,c3,c1);
$LD r6,`6*$BNSZ`(r4)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r0
#mul_add_c(a[7],b[6],c2,c3,c1);
$LD r6,`7*$BNSZ`(r4)
$LD r7,`6*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r11,r11,r8
adde r12,r12,r9
addze r10,r10
$ST r11,`13*$BNSZ`(r3) #r[13]=c2;
#mul_add_c(a[7],b[7],c3,c1,c2);
$LD r7,`7*$BNSZ`(r5)
$UMULL r8,r6,r7
$UMULH r9,r6,r7
addc r12,r12,r8
adde r10,r10,r9
$ST r12,`14*$BNSZ`(r3) #r[14]=c3;
$ST r10,`15*$BNSZ`(r3) #r[15]=c1;
blr
.long 0
.byte 0,12,0x14,0,0,0,3,0
.long 0
.size .bn_mul_comba8,.-.bn_mul_comba8
#
# NOTE: The following label name should be changed to
# "bn_sub_words" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
#
.align 4
.bn_sub_words:
#
# Handcoded version of bn_sub_words
#
#BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
#
# r3 = r
# r4 = a
# r5 = b
# r6 = n
#
# Note: No loop unrolling done since this is not a performance
# critical loop.
xor r0,r0,r0 #set r0 = 0
#
# check for r6 = 0 AND set carry bit.
#
subfc. r7,r0,r6 # If r6 is 0 then result is 0.
# if r6 > 0 then result !=0
# In either case carry bit is set.
beq Lppcasm_sub_adios
addi r4,r4,-$BNSZ
addi r3,r3,-$BNSZ
addi r5,r5,-$BNSZ
mtctr r6
Lppcasm_sub_mainloop:
$LDU r7,$BNSZ(r4)
$LDU r8,$BNSZ(r5)
subfe r6,r8,r7 # r6 = r7+carry bit + onescomplement(r8)
# if carry = 1 this is r7-r8. Else it
# is r7-r8 -1 as we need.
$STU r6,$BNSZ(r3)
bdnz Lppcasm_sub_mainloop
Lppcasm_sub_adios:
subfze r3,r0 # if carry bit is set then r3 = 0 else -1
andi. r3,r3,1 # keep only last bit.
blr
.long 0
.byte 0,12,0x14,0,0,0,4,0
.long 0
.size .bn_sub_words,.-.bn_sub_words
#
# NOTE: The following label name should be changed to
# "bn_add_words" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_add_words:
#
# Handcoded version of bn_add_words
#
#BN_ULONG bn_add_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
#
# r3 = r
# r4 = a
# r5 = b
# r6 = n
#
# Note: No loop unrolling done since this is not a performance
# critical loop.
xor r0,r0,r0
#
# check for r6 = 0. Is this needed?
#
addic. r6,r6,0 #test r6 and clear carry bit.
beq Lppcasm_add_adios
addi r4,r4,-$BNSZ
addi r3,r3,-$BNSZ
addi r5,r5,-$BNSZ
mtctr r6
Lppcasm_add_mainloop:
$LDU r7,$BNSZ(r4)
$LDU r8,$BNSZ(r5)
adde r8,r7,r8
$STU r8,$BNSZ(r3)
bdnz Lppcasm_add_mainloop
Lppcasm_add_adios:
addze r3,r0 #return carry bit.
blr
.long 0
.byte 0,12,0x14,0,0,0,4,0
.long 0
.size .bn_add_words,.-.bn_add_words
#
# NOTE: The following label name should be changed to
# "bn_div_words" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_div_words:
#
# This is a cleaned up version of code generated by
# the AIX compiler. The only optimization is to use
# the PPC instruction to count leading zeros instead
# of call to num_bits_word. Since this was compiled
# only at level -O2 we can possibly squeeze it more?
#
# r3 = h
# r4 = l
# r5 = d
$UCMPI 0,r5,0 # compare r5 and 0
bne Lppcasm_div1 # proceed if d!=0
li r3,-1 # d=0 return -1
blr
Lppcasm_div1:
xor r0,r0,r0 #r0=0
li r8,$BITS
$CNTLZ. r7,r5 #r7 = num leading 0s in d.
beq Lppcasm_div2 #proceed if no leading zeros
subf r8,r7,r8 #r8 = BN_num_bits_word(d)
$SHR. r9,r3,r8 #are there any bits above r8'th?
$TR 16,r9,r0 #if there're, signal to dump core...
Lppcasm_div2:
$UCMP 0,r3,r5 #h>=d?
blt Lppcasm_div3 #goto Lppcasm_div3 if not
subf r3,r5,r3 #h-=d ;
Lppcasm_div3: #r7 = BN_BITS2-i. so r7=i
cmpi 0,0,r7,0 # is (i == 0)?
beq Lppcasm_div4
$SHL r3,r3,r7 # h = (h<< i)
$SHR r8,r4,r8 # r8 = (l >> BN_BITS2 -i)
$SHL r5,r5,r7 # d<<=i
or r3,r3,r8 # h = (h<<i)|(l>>(BN_BITS2-i))
$SHL r4,r4,r7 # l <<=i
Lppcasm_div4:
$SHRI r9,r5,`$BITS/2` # r9 = dh
# dl will be computed when needed
# as it saves registers.
li r6,2 #r6=2
mtctr r6 #counter will be in count.
Lppcasm_divouterloop:
$SHRI r8,r3,`$BITS/2` #r8 = (h>>BN_BITS4)
$SHRI r11,r4,`$BITS/2` #r11= (l&BN_MASK2h)>>BN_BITS4
# compute here for innerloop.
$UCMP 0,r8,r9 # is (h>>BN_BITS4)==dh
bne Lppcasm_div5 # goto Lppcasm_div5 if not
li r8,-1
$CLRU r8,r8,`$BITS/2` #q = BN_MASK2l
b Lppcasm_div6
Lppcasm_div5:
$UDIV r8,r3,r9 #q = h/dh
Lppcasm_div6:
$UMULL r12,r9,r8 #th = q*dh
$CLRU r10,r5,`$BITS/2` #r10=dl
$UMULL r6,r8,r10 #tl = q*dl
Lppcasm_divinnerloop:
subf r10,r12,r3 #t = h -th
$SHRI r7,r10,`$BITS/2` #r7= (t &BN_MASK2H), sort of...
addic. r7,r7,0 #test if r7 == 0. used below.
# now want to compute
# r7 = (t<<BN_BITS4)|((l&BN_MASK2h)>>BN_BITS4)
# the following 2 instructions do that
$SHLI r7,r10,`$BITS/2` # r7 = (t<<BN_BITS4)
or r7,r7,r11 # r7|=((l&BN_MASK2h)>>BN_BITS4)
$UCMP cr1,r6,r7 # compare (tl <= r7)
bne Lppcasm_divinnerexit
ble cr1,Lppcasm_divinnerexit
addi r8,r8,-1 #q--
subf r12,r9,r12 #th -=dh
$CLRU r10,r5,`$BITS/2` #r10=dl. t is no longer needed in loop.
subf r6,r10,r6 #tl -=dl
b Lppcasm_divinnerloop
Lppcasm_divinnerexit:
$SHRI r10,r6,`$BITS/2` #t=(tl>>BN_BITS4)
$SHLI r11,r6,`$BITS/2` #tl=(tl<<BN_BITS4)&BN_MASK2h;
$UCMP cr1,r4,r11 # compare l and tl
add r12,r12,r10 # th+=t
bge cr1,Lppcasm_div7 # if (l>=tl) goto Lppcasm_div7
addi r12,r12,1 # th++
Lppcasm_div7:
subf r11,r11,r4 #r11=l-tl
$UCMP cr1,r3,r12 #compare h and th
bge cr1,Lppcasm_div8 #if (h>=th) goto Lppcasm_div8
addi r8,r8,-1 # q--
add r3,r5,r3 # h+=d
Lppcasm_div8:
subf r12,r12,r3 #r12 = h-th
$SHLI r4,r11,`$BITS/2` #l=(l&BN_MASK2l)<<BN_BITS4
# want to compute
# h = ((h<<BN_BITS4)|(l>>BN_BITS4))&BN_MASK2
# the following 2 instructions will do this.
$INSR r11,r12,`$BITS/2`,`$BITS/2` # r11 is the value we want rotated $BITS/2.
$ROTL r3,r11,`$BITS/2` # rotate by $BITS/2 and store in r3
bdz Lppcasm_div9 #if (count==0) break ;
$SHLI r0,r8,`$BITS/2` #ret =q<<BN_BITS4
b Lppcasm_divouterloop
Lppcasm_div9:
or r3,r8,r0
blr
.long 0
.byte 0,12,0x14,0,0,0,3,0
.long 0
.size .bn_div_words,.-.bn_div_words
#
# NOTE: The following label name should be changed to
# "bn_sqr_words" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_sqr_words:
#
# Optimized version of bn_sqr_words
#
# void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n)
#
# r3 = r
# r4 = a
# r5 = n
#
# r6 = a[i].
# r7,r8 = product.
#
# No unrolling done here. Not performance critical.
addic. r5,r5,0 #test r5.
beq Lppcasm_sqr_adios
addi r4,r4,-$BNSZ
addi r3,r3,-$BNSZ
mtctr r5
Lppcasm_sqr_mainloop:
#sqr(r[0],r[1],a[0]);
$LDU r6,$BNSZ(r4)
$UMULL r7,r6,r6
$UMULH r8,r6,r6
$STU r7,$BNSZ(r3)
$STU r8,$BNSZ(r3)
bdnz Lppcasm_sqr_mainloop
Lppcasm_sqr_adios:
blr
.long 0
.byte 0,12,0x14,0,0,0,3,0
.long 0
.size .bn_sqr_words,.-.bn_sqr_words
#
# NOTE: The following label name should be changed to
# "bn_mul_words" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_mul_words:
#
# BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
#
# r3 = rp
# r4 = ap
# r5 = num
# r6 = w
xor r0,r0,r0
xor r12,r12,r12 # used for carry
rlwinm. r7,r5,30,2,31 # num >> 2
beq Lppcasm_mw_REM
mtctr r7
Lppcasm_mw_LOOP:
#mul(rp[0],ap[0],w,c1);
$LD r8,`0*$BNSZ`(r4)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
addc r9,r9,r12
#addze r10,r10 #carry is NOT ignored.
#will be taken care of
#in second spin below
#using adde.
$ST r9,`0*$BNSZ`(r3)
#mul(rp[1],ap[1],w,c1);
$LD r8,`1*$BNSZ`(r4)
$UMULL r11,r6,r8
$UMULH r12,r6,r8
adde r11,r11,r10
#addze r12,r12
$ST r11,`1*$BNSZ`(r3)
#mul(rp[2],ap[2],w,c1);
$LD r8,`2*$BNSZ`(r4)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
adde r9,r9,r12
#addze r10,r10
$ST r9,`2*$BNSZ`(r3)
#mul_add(rp[3],ap[3],w,c1);
$LD r8,`3*$BNSZ`(r4)
$UMULL r11,r6,r8
$UMULH r12,r6,r8
adde r11,r11,r10
addze r12,r12 #this spin we collect carry into
#r12
$ST r11,`3*$BNSZ`(r3)
addi r3,r3,`4*$BNSZ`
addi r4,r4,`4*$BNSZ`
bdnz Lppcasm_mw_LOOP
Lppcasm_mw_REM:
andi. r5,r5,0x3
beq Lppcasm_mw_OVER
#mul(rp[0],ap[0],w,c1);
$LD r8,`0*$BNSZ`(r4)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
addc r9,r9,r12
addze r10,r10
$ST r9,`0*$BNSZ`(r3)
addi r12,r10,0
addi r5,r5,-1
cmpli 0,0,r5,0
beq Lppcasm_mw_OVER
#mul(rp[1],ap[1],w,c1);
$LD r8,`1*$BNSZ`(r4)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
addc r9,r9,r12
addze r10,r10
$ST r9,`1*$BNSZ`(r3)
addi r12,r10,0
addi r5,r5,-1
cmpli 0,0,r5,0
beq Lppcasm_mw_OVER
#mul_add(rp[2],ap[2],w,c1);
$LD r8,`2*$BNSZ`(r4)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
addc r9,r9,r12
addze r10,r10
$ST r9,`2*$BNSZ`(r3)
addi r12,r10,0
Lppcasm_mw_OVER:
addi r3,r12,0
blr
.long 0
.byte 0,12,0x14,0,0,0,4,0
.long 0
.size .bn_mul_words,.-.bn_mul_words
#
# NOTE: The following label name should be changed to
# "bn_mul_add_words" i.e. remove the first dot
# for the gcc compiler. This should be automatically
# done in the build
#
.align 4
.bn_mul_add_words:
#
# BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
#
# r3 = rp
# r4 = ap
# r5 = num
# r6 = w
#
# empirical evidence suggests that unrolled version performs best!!
#
xor r0,r0,r0 #r0 = 0
xor r12,r12,r12 #r12 = 0 . used for carry
rlwinm. r7,r5,30,2,31 # num >> 2
beq Lppcasm_maw_leftover # if (num < 4) go LPPCASM_maw_leftover
mtctr r7
Lppcasm_maw_mainloop:
#mul_add(rp[0],ap[0],w,c1);
$LD r8,`0*$BNSZ`(r4)
$LD r11,`0*$BNSZ`(r3)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
addc r9,r9,r12 #r12 is carry.
addze r10,r10
addc r9,r9,r11
#addze r10,r10
#the above instruction addze
#is NOT needed. Carry will NOT
#be ignored. It's not affected
#by multiply and will be collected
#in the next spin
$ST r9,`0*$BNSZ`(r3)
#mul_add(rp[1],ap[1],w,c1);
$LD r8,`1*$BNSZ`(r4)
$LD r9,`1*$BNSZ`(r3)
$UMULL r11,r6,r8
$UMULH r12,r6,r8
adde r11,r11,r10 #r10 is carry.
addze r12,r12
addc r11,r11,r9
#addze r12,r12
$ST r11,`1*$BNSZ`(r3)
#mul_add(rp[2],ap[2],w,c1);
$LD r8,`2*$BNSZ`(r4)
$UMULL r9,r6,r8
$LD r11,`2*$BNSZ`(r3)
$UMULH r10,r6,r8
adde r9,r9,r12
addze r10,r10
addc r9,r9,r11
#addze r10,r10
$ST r9,`2*$BNSZ`(r3)
#mul_add(rp[3],ap[3],w,c1);
$LD r8,`3*$BNSZ`(r4)
$UMULL r11,r6,r8
$LD r9,`3*$BNSZ`(r3)
$UMULH r12,r6,r8
adde r11,r11,r10
addze r12,r12
addc r11,r11,r9
addze r12,r12
$ST r11,`3*$BNSZ`(r3)
addi r3,r3,`4*$BNSZ`
addi r4,r4,`4*$BNSZ`
bdnz Lppcasm_maw_mainloop
Lppcasm_maw_leftover:
andi. r5,r5,0x3
beq Lppcasm_maw_adios
addi r3,r3,-$BNSZ
addi r4,r4,-$BNSZ
#mul_add(rp[0],ap[0],w,c1);
mtctr r5
$LDU r8,$BNSZ(r4)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
$LDU r11,$BNSZ(r3)
addc r9,r9,r11
addze r10,r10
addc r9,r9,r12
addze r12,r10
$ST r9,0(r3)
bdz Lppcasm_maw_adios
#mul_add(rp[1],ap[1],w,c1);
$LDU r8,$BNSZ(r4)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
$LDU r11,$BNSZ(r3)
addc r9,r9,r11
addze r10,r10
addc r9,r9,r12
addze r12,r10
$ST r9,0(r3)
bdz Lppcasm_maw_adios
#mul_add(rp[2],ap[2],w,c1);
$LDU r8,$BNSZ(r4)
$UMULL r9,r6,r8
$UMULH r10,r6,r8
$LDU r11,$BNSZ(r3)
addc r9,r9,r11
addze r10,r10
addc r9,r9,r12
addze r12,r10
$ST r9,0(r3)
Lppcasm_maw_adios:
addi r3,r12,0
blr
.long 0
.byte 0,12,0x14,0,0,0,4,0
.long 0
.size .bn_mul_add_words,.-.bn_mul_add_words
.align 4
EOF
$data =~ s/\`([^\`]*)\`/eval $1/gem;
print $data;
close STDOUT;
diff --git a/crypto/bn/bn_ctx.c b/crypto/bn/bn_ctx.c
index 54b799961aa4..90cecea2aa5d 100644
--- a/crypto/bn/bn_ctx.c
+++ b/crypto/bn/bn_ctx.c
@@ -1,361 +1,363 @@
/*
* Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
#include "bn_lcl.h"
/*-
* TODO list
*
* 1. Check a bunch of "(words+1)" type hacks in various bignum functions and
* check they can be safely removed.
* - Check +1 and other ugliness in BN_from_montgomery()
*
* 2. Consider allowing a BN_new_ex() that, at least, lets you specify an
* appropriate 'block' size that will be honoured by bn_expand_internal() to
* prevent piddly little reallocations. OTOH, profiling bignum expansions in
* BN_CTX doesn't show this to be a big issue.
*/
/* How many bignums are in each "pool item"; */
#define BN_CTX_POOL_SIZE 16
/* The stack frame info is resizing, set a first-time expansion size; */
#define BN_CTX_START_FRAMES 32
/***********/
/* BN_POOL */
/***********/
/* A bundle of bignums that can be linked with other bundles */
typedef struct bignum_pool_item {
/* The bignum values */
BIGNUM vals[BN_CTX_POOL_SIZE];
/* Linked-list admin */
struct bignum_pool_item *prev, *next;
} BN_POOL_ITEM;
/* A linked-list of bignums grouped in bundles */
typedef struct bignum_pool {
/* Linked-list admin */
BN_POOL_ITEM *head, *current, *tail;
/* Stack depth and allocation size */
unsigned used, size;
} BN_POOL;
static void BN_POOL_init(BN_POOL *);
static void BN_POOL_finish(BN_POOL *);
static BIGNUM *BN_POOL_get(BN_POOL *, int);
static void BN_POOL_release(BN_POOL *, unsigned int);
/************/
/* BN_STACK */
/************/
/* A wrapper to manage the "stack frames" */
typedef struct bignum_ctx_stack {
/* Array of indexes into the bignum stack */
unsigned int *indexes;
/* Number of stack frames, and the size of the allocated array */
unsigned int depth, size;
} BN_STACK;
static void BN_STACK_init(BN_STACK *);
static void BN_STACK_finish(BN_STACK *);
static int BN_STACK_push(BN_STACK *, unsigned int);
static unsigned int BN_STACK_pop(BN_STACK *);
/**********/
/* BN_CTX */
/**********/
/* The opaque BN_CTX type */
struct bignum_ctx {
/* The bignum bundles */
BN_POOL pool;
/* The "stack frames", if you will */
BN_STACK stack;
/* The number of bignums currently assigned */
unsigned int used;
/* Depth of stack overflow */
int err_stack;
/* Block "gets" until an "end" (compatibility behaviour) */
int too_many;
/* Flags. */
int flags;
};
/* Enable this to find BN_CTX bugs */
#ifdef BN_CTX_DEBUG
static const char *ctxdbg_cur = NULL;
static void ctxdbg(BN_CTX *ctx)
{
unsigned int bnidx = 0, fpidx = 0;
BN_POOL_ITEM *item = ctx->pool.head;
BN_STACK *stack = &ctx->stack;
fprintf(stderr, "(%16p): ", ctx);
while (bnidx < ctx->used) {
fprintf(stderr, "%03x ", item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax);
if (!(bnidx % BN_CTX_POOL_SIZE))
item = item->next;
}
fprintf(stderr, "\n");
bnidx = 0;
fprintf(stderr, " : ");
while (fpidx < stack->depth) {
while (bnidx++ < stack->indexes[fpidx])
fprintf(stderr, " ");
fprintf(stderr, "^^^ ");
bnidx++;
fpidx++;
}
fprintf(stderr, "\n");
}
# define CTXDBG_ENTRY(str, ctx) do { \
ctxdbg_cur = (str); \
fprintf(stderr,"Starting %s\n", ctxdbg_cur); \
ctxdbg(ctx); \
} while(0)
# define CTXDBG_EXIT(ctx) do { \
fprintf(stderr,"Ending %s\n", ctxdbg_cur); \
ctxdbg(ctx); \
} while(0)
# define CTXDBG_RET(ctx,ret)
#else
# define CTXDBG_ENTRY(str, ctx)
# define CTXDBG_EXIT(ctx)
# define CTXDBG_RET(ctx,ret)
#endif
BN_CTX *BN_CTX_new(void)
{
BN_CTX *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
/* Initialise the structure */
BN_POOL_init(&ret->pool);
BN_STACK_init(&ret->stack);
return ret;
}
BN_CTX *BN_CTX_secure_new(void)
{
BN_CTX *ret = BN_CTX_new();
if (ret != NULL)
ret->flags = BN_FLG_SECURE;
return ret;
}
void BN_CTX_free(BN_CTX *ctx)
{
if (ctx == NULL)
return;
#ifdef BN_CTX_DEBUG
{
BN_POOL_ITEM *pool = ctx->pool.head;
fprintf(stderr, "BN_CTX_free, stack-size=%d, pool-bignums=%d\n",
ctx->stack.size, ctx->pool.size);
fprintf(stderr, "dmaxs: ");
while (pool) {
unsigned loop = 0;
while (loop < BN_CTX_POOL_SIZE)
fprintf(stderr, "%02x ", pool->vals[loop++].dmax);
pool = pool->next;
}
fprintf(stderr, "\n");
}
#endif
BN_STACK_finish(&ctx->stack);
BN_POOL_finish(&ctx->pool);
OPENSSL_free(ctx);
}
void BN_CTX_start(BN_CTX *ctx)
{
CTXDBG_ENTRY("BN_CTX_start", ctx);
/* If we're already overflowing ... */
if (ctx->err_stack || ctx->too_many)
ctx->err_stack++;
/* (Try to) get a new frame pointer */
else if (!BN_STACK_push(&ctx->stack, ctx->used)) {
BNerr(BN_F_BN_CTX_START, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
ctx->err_stack++;
}
CTXDBG_EXIT(ctx);
}
void BN_CTX_end(BN_CTX *ctx)
{
+ if (ctx == NULL)
+ return;
CTXDBG_ENTRY("BN_CTX_end", ctx);
if (ctx->err_stack)
ctx->err_stack--;
else {
unsigned int fp = BN_STACK_pop(&ctx->stack);
/* Does this stack frame have anything to release? */
if (fp < ctx->used)
BN_POOL_release(&ctx->pool, ctx->used - fp);
ctx->used = fp;
/* Unjam "too_many" in case "get" had failed */
ctx->too_many = 0;
}
CTXDBG_EXIT(ctx);
}
BIGNUM *BN_CTX_get(BN_CTX *ctx)
{
BIGNUM *ret;
CTXDBG_ENTRY("BN_CTX_get", ctx);
if (ctx->err_stack || ctx->too_many)
return NULL;
if ((ret = BN_POOL_get(&ctx->pool, ctx->flags)) == NULL) {
/*
* Setting too_many prevents repeated "get" attempts from cluttering
* the error stack.
*/
ctx->too_many = 1;
BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
return NULL;
}
/* OK, make sure the returned bignum is "zero" */
BN_zero(ret);
/* clear BN_FLG_CONSTTIME if leaked from previous frames */
ret->flags &= (~BN_FLG_CONSTTIME);
ctx->used++;
CTXDBG_RET(ctx, ret);
return ret;
}
/************/
/* BN_STACK */
/************/
static void BN_STACK_init(BN_STACK *st)
{
st->indexes = NULL;
st->depth = st->size = 0;
}
static void BN_STACK_finish(BN_STACK *st)
{
OPENSSL_free(st->indexes);
st->indexes = NULL;
}
static int BN_STACK_push(BN_STACK *st, unsigned int idx)
{
if (st->depth == st->size) {
/* Need to expand */
unsigned int newsize =
st->size ? (st->size * 3 / 2) : BN_CTX_START_FRAMES;
unsigned int *newitems;
if ((newitems = OPENSSL_malloc(sizeof(*newitems) * newsize)) == NULL) {
BNerr(BN_F_BN_STACK_PUSH, ERR_R_MALLOC_FAILURE);
return 0;
}
if (st->depth)
memcpy(newitems, st->indexes, sizeof(*newitems) * st->depth);
OPENSSL_free(st->indexes);
st->indexes = newitems;
st->size = newsize;
}
st->indexes[(st->depth)++] = idx;
return 1;
}
static unsigned int BN_STACK_pop(BN_STACK *st)
{
return st->indexes[--(st->depth)];
}
/***********/
/* BN_POOL */
/***********/
static void BN_POOL_init(BN_POOL *p)
{
p->head = p->current = p->tail = NULL;
p->used = p->size = 0;
}
static void BN_POOL_finish(BN_POOL *p)
{
unsigned int loop;
BIGNUM *bn;
while (p->head) {
for (loop = 0, bn = p->head->vals; loop++ < BN_CTX_POOL_SIZE; bn++)
if (bn->d)
BN_clear_free(bn);
p->current = p->head->next;
OPENSSL_free(p->head);
p->head = p->current;
}
}
static BIGNUM *BN_POOL_get(BN_POOL *p, int flag)
{
BIGNUM *bn;
unsigned int loop;
/* Full; allocate a new pool item and link it in. */
if (p->used == p->size) {
BN_POOL_ITEM *item;
if ((item = OPENSSL_malloc(sizeof(*item))) == NULL) {
BNerr(BN_F_BN_POOL_GET, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (loop = 0, bn = item->vals; loop++ < BN_CTX_POOL_SIZE; bn++) {
bn_init(bn);
if ((flag & BN_FLG_SECURE) != 0)
BN_set_flags(bn, BN_FLG_SECURE);
}
item->prev = p->tail;
item->next = NULL;
if (p->head == NULL)
p->head = p->current = p->tail = item;
else {
p->tail->next = item;
p->tail = item;
p->current = item;
}
p->size += BN_CTX_POOL_SIZE;
p->used++;
/* Return the first bignum from the new pool */
return item->vals;
}
if (!p->used)
p->current = p->head;
else if ((p->used % BN_CTX_POOL_SIZE) == 0)
p->current = p->current->next;
return p->current->vals + ((p->used++) % BN_CTX_POOL_SIZE);
}
static void BN_POOL_release(BN_POOL *p, unsigned int num)
{
unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE;
p->used -= num;
while (num--) {
bn_check_top(p->current->vals + offset);
if (offset == 0) {
offset = BN_CTX_POOL_SIZE - 1;
p->current = p->current->prev;
} else
offset--;
}
}
diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c
index 8286b3855a2c..f93bbcfcc71f 100644
--- a/crypto/bn/bn_lib.c
+++ b/crypto/bn/bn_lib.c
@@ -1,964 +1,966 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <assert.h>
#include <limits.h>
#include "internal/cryptlib.h"
#include "bn_lcl.h"
#include <openssl/opensslconf.h>
#include "internal/constant_time_locl.h"
/* This stuff appears to be completely unused, so is deprecated */
#if OPENSSL_API_COMPAT < 0x00908000L
/*-
* For a 32 bit machine
* 2 - 4 == 128
* 3 - 8 == 256
* 4 - 16 == 512
* 5 - 32 == 1024
* 6 - 64 == 2048
* 7 - 128 == 4096
* 8 - 256 == 8192
*/
static int bn_limit_bits = 0;
static int bn_limit_num = 8; /* (1<<bn_limit_bits) */
static int bn_limit_bits_low = 0;
static int bn_limit_num_low = 8; /* (1<<bn_limit_bits_low) */
static int bn_limit_bits_high = 0;
static int bn_limit_num_high = 8; /* (1<<bn_limit_bits_high) */
static int bn_limit_bits_mont = 0;
static int bn_limit_num_mont = 8; /* (1<<bn_limit_bits_mont) */
void BN_set_params(int mult, int high, int low, int mont)
{
if (mult >= 0) {
if (mult > (int)(sizeof(int) * 8) - 1)
mult = sizeof(int) * 8 - 1;
bn_limit_bits = mult;
bn_limit_num = 1 << mult;
}
if (high >= 0) {
if (high > (int)(sizeof(int) * 8) - 1)
high = sizeof(int) * 8 - 1;
bn_limit_bits_high = high;
bn_limit_num_high = 1 << high;
}
if (low >= 0) {
if (low > (int)(sizeof(int) * 8) - 1)
low = sizeof(int) * 8 - 1;
bn_limit_bits_low = low;
bn_limit_num_low = 1 << low;
}
if (mont >= 0) {
if (mont > (int)(sizeof(int) * 8) - 1)
mont = sizeof(int) * 8 - 1;
bn_limit_bits_mont = mont;
bn_limit_num_mont = 1 << mont;
}
}
int BN_get_params(int which)
{
if (which == 0)
return bn_limit_bits;
else if (which == 1)
return bn_limit_bits_high;
else if (which == 2)
return bn_limit_bits_low;
else if (which == 3)
return bn_limit_bits_mont;
else
return 0;
}
#endif
const BIGNUM *BN_value_one(void)
{
static const BN_ULONG data_one = 1L;
static const BIGNUM const_one =
{ (BN_ULONG *)&data_one, 1, 1, 0, BN_FLG_STATIC_DATA };
return &const_one;
}
int BN_num_bits_word(BN_ULONG l)
{
BN_ULONG x, mask;
int bits = (l != 0);
#if BN_BITS2 > 32
x = l >> 32;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 32 & mask;
l ^= (x ^ l) & mask;
#endif
x = l >> 16;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 16 & mask;
l ^= (x ^ l) & mask;
x = l >> 8;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 8 & mask;
l ^= (x ^ l) & mask;
x = l >> 4;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 4 & mask;
l ^= (x ^ l) & mask;
x = l >> 2;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 2 & mask;
l ^= (x ^ l) & mask;
x = l >> 1;
mask = (0 - x) & BN_MASK2;
mask = (0 - (mask >> (BN_BITS2 - 1)));
bits += 1 & mask;
return bits;
}
int BN_num_bits(const BIGNUM *a)
{
int i = a->top - 1;
bn_check_top(a);
if (BN_is_zero(a))
return 0;
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
}
static void bn_free_d(BIGNUM *a)
{
if (BN_get_flags(a, BN_FLG_SECURE))
OPENSSL_secure_free(a->d);
else
OPENSSL_free(a->d);
}
void BN_clear_free(BIGNUM *a)
{
if (a == NULL)
return;
if (a->d != NULL && !BN_get_flags(a, BN_FLG_STATIC_DATA)) {
OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
bn_free_d(a);
}
if (BN_get_flags(a, BN_FLG_MALLOCED)) {
OPENSSL_cleanse(a, sizeof(*a));
OPENSSL_free(a);
}
}
void BN_free(BIGNUM *a)
{
if (a == NULL)
return;
if (!BN_get_flags(a, BN_FLG_STATIC_DATA))
bn_free_d(a);
if (a->flags & BN_FLG_MALLOCED)
OPENSSL_free(a);
}
void bn_init(BIGNUM *a)
{
static BIGNUM nilbn;
*a = nilbn;
bn_check_top(a);
}
BIGNUM *BN_new(void)
{
BIGNUM *ret;
if ((ret = OPENSSL_zalloc(sizeof(*ret))) == NULL) {
BNerr(BN_F_BN_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->flags = BN_FLG_MALLOCED;
bn_check_top(ret);
return ret;
}
BIGNUM *BN_secure_new(void)
{
BIGNUM *ret = BN_new();
if (ret != NULL)
ret->flags |= BN_FLG_SECURE;
return ret;
}
/* This is used by bn_expand2() */
/* The caller MUST check that words > b->dmax before calling this */
static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
{
BN_ULONG *a = NULL;
if (words > (INT_MAX / (4 * BN_BITS2))) {
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG);
return NULL;
}
if (BN_get_flags(b, BN_FLG_STATIC_DATA)) {
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
return NULL;
}
if (BN_get_flags(b, BN_FLG_SECURE))
a = OPENSSL_secure_zalloc(words * sizeof(*a));
else
a = OPENSSL_zalloc(words * sizeof(*a));
if (a == NULL) {
BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE);
return NULL;
}
assert(b->top <= words);
if (b->top > 0)
memcpy(a, b->d, sizeof(*a) * b->top);
return a;
}
/*
* This is an internal function that should not be used in applications. It
* ensures that 'b' has enough room for a 'words' word number and initialises
* any unused part of b->d with leading zeros. It is mostly used by the
* various BIGNUM routines. If there is an error, NULL is returned. If not,
* 'b' is returned.
*/
BIGNUM *bn_expand2(BIGNUM *b, int words)
{
if (words > b->dmax) {
BN_ULONG *a = bn_expand_internal(b, words);
if (!a)
return NULL;
if (b->d) {
OPENSSL_cleanse(b->d, b->dmax * sizeof(b->d[0]));
bn_free_d(b);
}
b->d = a;
b->dmax = words;
}
return b;
}
BIGNUM *BN_dup(const BIGNUM *a)
{
BIGNUM *t;
if (a == NULL)
return NULL;
bn_check_top(a);
t = BN_get_flags(a, BN_FLG_SECURE) ? BN_secure_new() : BN_new();
if (t == NULL)
return NULL;
if (!BN_copy(t, a)) {
BN_free(t);
return NULL;
}
bn_check_top(t);
return t;
}
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
{
bn_check_top(b);
if (a == b)
return a;
if (bn_wexpand(a, b->top) == NULL)
return NULL;
if (b->top > 0)
memcpy(a->d, b->d, sizeof(b->d[0]) * b->top);
a->neg = b->neg;
a->top = b->top;
a->flags |= b->flags & BN_FLG_FIXED_TOP;
bn_check_top(a);
return a;
}
#define FLAGS_DATA(flags) ((flags) & (BN_FLG_STATIC_DATA \
| BN_FLG_CONSTTIME \
| BN_FLG_SECURE \
| BN_FLG_FIXED_TOP))
#define FLAGS_STRUCT(flags) ((flags) & (BN_FLG_MALLOCED))
void BN_swap(BIGNUM *a, BIGNUM *b)
{
int flags_old_a, flags_old_b;
BN_ULONG *tmp_d;
int tmp_top, tmp_dmax, tmp_neg;
bn_check_top(a);
bn_check_top(b);
flags_old_a = a->flags;
flags_old_b = b->flags;
tmp_d = a->d;
tmp_top = a->top;
tmp_dmax = a->dmax;
tmp_neg = a->neg;
a->d = b->d;
a->top = b->top;
a->dmax = b->dmax;
a->neg = b->neg;
b->d = tmp_d;
b->top = tmp_top;
b->dmax = tmp_dmax;
b->neg = tmp_neg;
a->flags = FLAGS_STRUCT(flags_old_a) | FLAGS_DATA(flags_old_b);
b->flags = FLAGS_STRUCT(flags_old_b) | FLAGS_DATA(flags_old_a);
bn_check_top(a);
bn_check_top(b);
}
void BN_clear(BIGNUM *a)
{
+ if (a == NULL)
+ return;
bn_check_top(a);
if (a->d != NULL)
OPENSSL_cleanse(a->d, sizeof(*a->d) * a->dmax);
a->neg = 0;
a->top = 0;
a->flags &= ~BN_FLG_FIXED_TOP;
}
BN_ULONG BN_get_word(const BIGNUM *a)
{
if (a->top > 1)
return BN_MASK2;
else if (a->top == 1)
return a->d[0];
/* a->top == 0 */
return 0;
}
int BN_set_word(BIGNUM *a, BN_ULONG w)
{
bn_check_top(a);
if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL)
return 0;
a->neg = 0;
a->d[0] = w;
a->top = (w ? 1 : 0);
a->flags &= ~BN_FLG_FIXED_TOP;
bn_check_top(a);
return 1;
}
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i, m;
unsigned int n;
BN_ULONG l;
BIGNUM *bn = NULL;
if (ret == NULL)
ret = bn = BN_new();
if (ret == NULL)
return NULL;
bn_check_top(ret);
/* Skip leading zero's. */
for ( ; len > 0 && *s == 0; s++, len--)
continue;
n = len;
if (n == 0) {
ret->top = 0;
return ret;
}
i = ((n - 1) / BN_BYTES) + 1;
m = ((n - 1) % (BN_BYTES));
if (bn_wexpand(ret, (int)i) == NULL) {
BN_free(bn);
return NULL;
}
ret->top = i;
ret->neg = 0;
l = 0;
while (n--) {
l = (l << 8L) | *(s++);
if (m-- == 0) {
ret->d[--i] = l;
l = 0;
m = BN_BYTES - 1;
}
}
/*
* need to call this due to clear byte at top if avoiding having the top
* bit set (-ve number)
*/
bn_correct_top(ret);
return ret;
}
/* ignore negative */
static int bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
{
int n;
size_t i, lasti, j, atop, mask;
BN_ULONG l;
/*
* In case |a| is fixed-top, BN_num_bytes can return bogus length,
* but it's assumed that fixed-top inputs ought to be "nominated"
* even for padded output, so it works out...
*/
n = BN_num_bytes(a);
if (tolen == -1) {
tolen = n;
} else if (tolen < n) { /* uncommon/unlike case */
BIGNUM temp = *a;
bn_correct_top(&temp);
n = BN_num_bytes(&temp);
if (tolen < n)
return -1;
}
/* Swipe through whole available data and don't give away padded zero. */
atop = a->dmax * BN_BYTES;
if (atop == 0) {
OPENSSL_cleanse(to, tolen);
return tolen;
}
lasti = atop - 1;
atop = a->top * BN_BYTES;
for (i = 0, j = 0, to += tolen; j < (size_t)tolen; j++) {
l = a->d[i / BN_BYTES];
mask = 0 - ((j - atop) >> (8 * sizeof(i) - 1));
*--to = (unsigned char)(l >> (8 * (i % BN_BYTES)) & mask);
i += (i - lasti) >> (8 * sizeof(i) - 1); /* stay on last limb */
}
return tolen;
}
int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen)
{
if (tolen < 0)
return -1;
return bn2binpad(a, to, tolen);
}
int BN_bn2bin(const BIGNUM *a, unsigned char *to)
{
return bn2binpad(a, to, -1);
}
BIGNUM *BN_lebin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i, m;
unsigned int n;
BN_ULONG l;
BIGNUM *bn = NULL;
if (ret == NULL)
ret = bn = BN_new();
if (ret == NULL)
return NULL;
bn_check_top(ret);
s += len;
/* Skip trailing zeroes. */
for ( ; len > 0 && s[-1] == 0; s--, len--)
continue;
n = len;
if (n == 0) {
ret->top = 0;
return ret;
}
i = ((n - 1) / BN_BYTES) + 1;
m = ((n - 1) % (BN_BYTES));
if (bn_wexpand(ret, (int)i) == NULL) {
BN_free(bn);
return NULL;
}
ret->top = i;
ret->neg = 0;
l = 0;
while (n--) {
s--;
l = (l << 8L) | *s;
if (m-- == 0) {
ret->d[--i] = l;
l = 0;
m = BN_BYTES - 1;
}
}
/*
* need to call this due to clear byte at top if avoiding having the top
* bit set (-ve number)
*/
bn_correct_top(ret);
return ret;
}
int BN_bn2lebinpad(const BIGNUM *a, unsigned char *to, int tolen)
{
int i;
BN_ULONG l;
bn_check_top(a);
i = BN_num_bytes(a);
if (tolen < i)
return -1;
/* Add trailing zeroes if necessary */
if (tolen > i)
memset(to + i, 0, tolen - i);
to += i;
while (i--) {
l = a->d[i / BN_BYTES];
to--;
*to = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
}
return tolen;
}
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
BN_ULONG t1, t2, *ap, *bp;
bn_check_top(a);
bn_check_top(b);
i = a->top - b->top;
if (i != 0)
return i;
ap = a->d;
bp = b->d;
for (i = a->top - 1; i >= 0; i--) {
t1 = ap[i];
t2 = bp[i];
if (t1 != t2)
return ((t1 > t2) ? 1 : -1);
}
return 0;
}
int BN_cmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
int gt, lt;
BN_ULONG t1, t2;
if ((a == NULL) || (b == NULL)) {
if (a != NULL)
return -1;
else if (b != NULL)
return 1;
else
return 0;
}
bn_check_top(a);
bn_check_top(b);
if (a->neg != b->neg) {
if (a->neg)
return -1;
else
return 1;
}
if (a->neg == 0) {
gt = 1;
lt = -1;
} else {
gt = -1;
lt = 1;
}
if (a->top > b->top)
return gt;
if (a->top < b->top)
return lt;
for (i = a->top - 1; i >= 0; i--) {
t1 = a->d[i];
t2 = b->d[i];
if (t1 > t2)
return gt;
if (t1 < t2)
return lt;
}
return 0;
}
int BN_set_bit(BIGNUM *a, int n)
{
int i, j, k;
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i) {
if (bn_wexpand(a, i + 1) == NULL)
return 0;
for (k = a->top; k < i + 1; k++)
a->d[k] = 0;
a->top = i + 1;
a->flags &= ~BN_FLG_FIXED_TOP;
}
a->d[i] |= (((BN_ULONG)1) << j);
bn_check_top(a);
return 1;
}
int BN_clear_bit(BIGNUM *a, int n)
{
int i, j;
bn_check_top(a);
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i)
return 0;
a->d[i] &= (~(((BN_ULONG)1) << j));
bn_correct_top(a);
return 1;
}
int BN_is_bit_set(const BIGNUM *a, int n)
{
int i, j;
bn_check_top(a);
if (n < 0)
return 0;
i = n / BN_BITS2;
j = n % BN_BITS2;
if (a->top <= i)
return 0;
return (int)(((a->d[i]) >> j) & ((BN_ULONG)1));
}
int BN_mask_bits(BIGNUM *a, int n)
{
int b, w;
bn_check_top(a);
if (n < 0)
return 0;
w = n / BN_BITS2;
b = n % BN_BITS2;
if (w >= a->top)
return 0;
if (b == 0)
a->top = w;
else {
a->top = w + 1;
a->d[w] &= ~(BN_MASK2 << b);
}
bn_correct_top(a);
return 1;
}
void BN_set_negative(BIGNUM *a, int b)
{
if (b && !BN_is_zero(a))
a->neg = 1;
else
a->neg = 0;
}
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
{
int i;
BN_ULONG aa, bb;
if (n == 0)
return 0;
aa = a[n - 1];
bb = b[n - 1];
if (aa != bb)
return ((aa > bb) ? 1 : -1);
for (i = n - 2; i >= 0; i--) {
aa = a[i];
bb = b[i];
if (aa != bb)
return ((aa > bb) ? 1 : -1);
}
return 0;
}
/*
* Here follows a specialised variants of bn_cmp_words(). It has the
* capability of performing the operation on arrays of different sizes. The
* sizes of those arrays is expressed through cl, which is the common length
* ( basically, min(len(a),len(b)) ), and dl, which is the delta between the
* two lengths, calculated as len(a)-len(b). All lengths are the number of
* BN_ULONGs...
*/
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl)
{
int n, i;
n = cl - 1;
if (dl < 0) {
for (i = dl; i < 0; i++) {
if (b[n - i] != 0)
return -1; /* a < b */
}
}
if (dl > 0) {
for (i = dl; i > 0; i--) {
if (a[n + i] != 0)
return 1; /* a > b */
}
}
return bn_cmp_words(a, b, cl);
}
/*-
* Constant-time conditional swap of a and b.
* a and b are swapped if condition is not 0.
* nwords is the number of words to swap.
* Assumes that at least nwords are allocated in both a and b.
* Assumes that no more than nwords are used by either a or b.
*/
void BN_consttime_swap(BN_ULONG condition, BIGNUM *a, BIGNUM *b, int nwords)
{
BN_ULONG t;
int i;
if (a == b)
return;
bn_wcheck_size(a, nwords);
bn_wcheck_size(b, nwords);
condition = ((~condition & ((condition - 1))) >> (BN_BITS2 - 1)) - 1;
t = (a->top ^ b->top) & condition;
a->top ^= t;
b->top ^= t;
t = (a->neg ^ b->neg) & condition;
a->neg ^= t;
b->neg ^= t;
/*-
* BN_FLG_STATIC_DATA: indicates that data may not be written to. Intention
* is actually to treat it as it's read-only data, and some (if not most)
* of it does reside in read-only segment. In other words observation of
* BN_FLG_STATIC_DATA in BN_consttime_swap should be treated as fatal
* condition. It would either cause SEGV or effectively cause data
* corruption.
*
* BN_FLG_MALLOCED: refers to BN structure itself, and hence must be
* preserved.
*
* BN_FLG_SECURE: must be preserved, because it determines how x->d was
* allocated and hence how to free it.
*
* BN_FLG_CONSTTIME: sufficient to mask and swap
*
* BN_FLG_FIXED_TOP: indicates that we haven't called bn_correct_top() on
* the data, so the d array may be padded with additional 0 values (i.e.
* top could be greater than the minimal value that it could be). We should
* be swapping it
*/
#define BN_CONSTTIME_SWAP_FLAGS (BN_FLG_CONSTTIME | BN_FLG_FIXED_TOP)
t = ((a->flags ^ b->flags) & BN_CONSTTIME_SWAP_FLAGS) & condition;
a->flags ^= t;
b->flags ^= t;
/* conditionally swap the data */
for (i = 0; i < nwords; i++) {
t = (a->d[i] ^ b->d[i]) & condition;
a->d[i] ^= t;
b->d[i] ^= t;
}
}
#undef BN_CONSTTIME_SWAP_FLAGS
/* Bits of security, see SP800-57 */
int BN_security_bits(int L, int N)
{
int secbits, bits;
if (L >= 15360)
secbits = 256;
else if (L >= 7680)
secbits = 192;
else if (L >= 3072)
secbits = 128;
else if (L >= 2048)
secbits = 112;
else if (L >= 1024)
secbits = 80;
else
return 0;
if (N == -1)
return secbits;
bits = N / 2;
if (bits < 80)
return 0;
return bits >= secbits ? secbits : bits;
}
void BN_zero_ex(BIGNUM *a)
{
a->neg = 0;
a->top = 0;
a->flags &= ~BN_FLG_FIXED_TOP;
}
int BN_abs_is_word(const BIGNUM *a, const BN_ULONG w)
{
return ((a->top == 1) && (a->d[0] == w)) || ((w == 0) && (a->top == 0));
}
int BN_is_zero(const BIGNUM *a)
{
return a->top == 0;
}
int BN_is_one(const BIGNUM *a)
{
return BN_abs_is_word(a, 1) && !a->neg;
}
int BN_is_word(const BIGNUM *a, const BN_ULONG w)
{
return BN_abs_is_word(a, w) && (!w || !a->neg);
}
int BN_is_odd(const BIGNUM *a)
{
return (a->top > 0) && (a->d[0] & 1);
}
int BN_is_negative(const BIGNUM *a)
{
return (a->neg != 0);
}
int BN_to_montgomery(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx)
{
return BN_mod_mul_montgomery(r, a, &(mont->RR), mont, ctx);
}
void BN_with_flags(BIGNUM *dest, const BIGNUM *b, int flags)
{
dest->d = b->d;
dest->top = b->top;
dest->dmax = b->dmax;
dest->neg = b->neg;
dest->flags = ((dest->flags & BN_FLG_MALLOCED)
| (b->flags & ~BN_FLG_MALLOCED)
| BN_FLG_STATIC_DATA | flags);
}
BN_GENCB *BN_GENCB_new(void)
{
BN_GENCB *ret;
if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL) {
BNerr(BN_F_BN_GENCB_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
return ret;
}
void BN_GENCB_free(BN_GENCB *cb)
{
if (cb == NULL)
return;
OPENSSL_free(cb);
}
void BN_set_flags(BIGNUM *b, int n)
{
b->flags |= n;
}
int BN_get_flags(const BIGNUM *b, int n)
{
return b->flags & n;
}
/* Populate a BN_GENCB structure with an "old"-style callback */
void BN_GENCB_set_old(BN_GENCB *gencb, void (*callback) (int, int, void *),
void *cb_arg)
{
BN_GENCB *tmp_gencb = gencb;
tmp_gencb->ver = 1;
tmp_gencb->arg = cb_arg;
tmp_gencb->cb.cb_1 = callback;
}
/* Populate a BN_GENCB structure with a "new"-style callback */
void BN_GENCB_set(BN_GENCB *gencb, int (*callback) (int, int, BN_GENCB *),
void *cb_arg)
{
BN_GENCB *tmp_gencb = gencb;
tmp_gencb->ver = 2;
tmp_gencb->arg = cb_arg;
tmp_gencb->cb.cb_2 = callback;
}
void *BN_GENCB_get_arg(BN_GENCB *cb)
{
return cb->arg;
}
BIGNUM *bn_wexpand(BIGNUM *a, int words)
{
return (words <= a->dmax) ? a : bn_expand2(a, words);
}
void bn_correct_top(BIGNUM *a)
{
BN_ULONG *ftl;
int tmp_top = a->top;
if (tmp_top > 0) {
for (ftl = &(a->d[tmp_top]); tmp_top > 0; tmp_top--) {
ftl--;
if (*ftl != 0)
break;
}
a->top = tmp_top;
}
if (a->top == 0)
a->neg = 0;
a->flags &= ~BN_FLG_FIXED_TOP;
bn_pollute(a);
}
diff --git a/crypto/bn/bn_prime.c b/crypto/bn/bn_prime.c
index b91b31b1f304..4bbd7c881031 100644
--- a/crypto/bn/bn_prime.c
+++ b/crypto/bn/bn_prime.c
@@ -1,469 +1,468 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include "internal/cryptlib.h"
#include "bn_lcl.h"
/*
* The quick sieve algorithm approach to weeding out primes is Philip
* Zimmermann's, as implemented in PGP. I have had a read of his comments
* and implemented my own version.
*/
#include "bn_prime.h"
static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
const BIGNUM *a1_odd, int k, BN_CTX *ctx,
BN_MONT_CTX *mont);
static int probable_prime(BIGNUM *rnd, int bits, prime_t *mods);
static int probable_prime_dh_safe(BIGNUM *rnd, int bits,
const BIGNUM *add, const BIGNUM *rem,
BN_CTX *ctx);
int BN_GENCB_call(BN_GENCB *cb, int a, int b)
{
/* No callback means continue */
if (!cb)
return 1;
switch (cb->ver) {
case 1:
/* Deprecated-style callbacks */
if (!cb->cb.cb_1)
return 1;
cb->cb.cb_1(a, b, cb->arg);
return 1;
case 2:
/* New-style callbacks */
return cb->cb.cb_2(a, b, cb);
default:
break;
}
/* Unrecognised callback type */
return 0;
}
int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb)
{
BIGNUM *t;
int found = 0;
int i, j, c1 = 0;
BN_CTX *ctx = NULL;
prime_t *mods = NULL;
int checks = BN_prime_checks_for_size(bits);
if (bits < 2) {
/* There are no prime numbers this small. */
BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL);
return 0;
} else if (bits == 2 && safe) {
/* The smallest safe prime (7) is three bits. */
BNerr(BN_F_BN_GENERATE_PRIME_EX, BN_R_BITS_TOO_SMALL);
return 0;
}
mods = OPENSSL_zalloc(sizeof(*mods) * NUMPRIMES);
if (mods == NULL)
goto err;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
t = BN_CTX_get(ctx);
if (t == NULL)
goto err;
loop:
/* make a random number and set the top and bottom bits */
if (add == NULL) {
if (!probable_prime(ret, bits, mods))
goto err;
} else {
if (safe) {
if (!probable_prime_dh_safe(ret, bits, add, rem, ctx))
goto err;
} else {
if (!bn_probable_prime_dh(ret, bits, add, rem, ctx))
goto err;
}
}
if (!BN_GENCB_call(cb, 0, c1++))
/* aborted */
goto err;
if (!safe) {
i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb);
if (i == -1)
goto err;
if (i == 0)
goto loop;
} else {
/*
* for "safe prime" generation, check that (p-1)/2 is prime. Since a
* prime is odd, We just need to divide by 2
*/
if (!BN_rshift1(t, ret))
goto err;
for (i = 0; i < checks; i++) {
j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, cb);
if (j == -1)
goto err;
if (j == 0)
goto loop;
j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, cb);
if (j == -1)
goto err;
if (j == 0)
goto loop;
if (!BN_GENCB_call(cb, 2, c1 - 1))
goto err;
/* We have a safe prime test pass */
}
}
/* we have a prime :-) */
found = 1;
err:
OPENSSL_free(mods);
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
bn_check_top(ret);
return found;
}
int BN_is_prime_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
BN_GENCB *cb)
{
return BN_is_prime_fasttest_ex(a, checks, ctx_passed, 0, cb);
}
int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
int do_trial_division, BN_GENCB *cb)
{
int i, j, ret = -1;
int k;
BN_CTX *ctx = NULL;
BIGNUM *A1, *A1_odd, *A3, *check; /* taken from ctx */
BN_MONT_CTX *mont = NULL;
/* Take care of the really small primes 2 & 3 */
if (BN_is_word(a, 2) || BN_is_word(a, 3))
return 1;
/* Check odd and bigger than 1 */
if (!BN_is_odd(a) || BN_cmp(a, BN_value_one()) <= 0)
return 0;
if (checks == BN_prime_checks)
checks = BN_prime_checks_for_size(BN_num_bits(a));
/* first look for small factors */
if (do_trial_division) {
for (i = 1; i < NUMPRIMES; i++) {
BN_ULONG mod = BN_mod_word(a, primes[i]);
if (mod == (BN_ULONG)-1)
goto err;
if (mod == 0)
return BN_is_word(a, primes[i]);
}
if (!BN_GENCB_call(cb, 1, -1))
goto err;
}
if (ctx_passed != NULL)
ctx = ctx_passed;
else if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
A1 = BN_CTX_get(ctx);
A3 = BN_CTX_get(ctx);
A1_odd = BN_CTX_get(ctx);
check = BN_CTX_get(ctx);
if (check == NULL)
goto err;
/* compute A1 := a - 1 */
if (!BN_copy(A1, a) || !BN_sub_word(A1, 1))
goto err;
/* compute A3 := a - 3 */
if (!BN_copy(A3, a) || !BN_sub_word(A3, 3))
goto err;
/* write A1 as A1_odd * 2^k */
k = 1;
while (!BN_is_bit_set(A1, k))
k++;
if (!BN_rshift(A1_odd, A1, k))
goto err;
/* Montgomery setup for computations mod a */
mont = BN_MONT_CTX_new();
if (mont == NULL)
goto err;
if (!BN_MONT_CTX_set(mont, a, ctx))
goto err;
for (i = 0; i < checks; i++) {
/* 1 < check < a-1 */
if (!BN_priv_rand_range(check, A3) || !BN_add_word(check, 2))
goto err;
j = witness(check, a, A1, A1_odd, k, ctx, mont);
if (j == -1)
goto err;
if (j) {
ret = 0;
goto err;
}
if (!BN_GENCB_call(cb, 1, i))
goto err;
}
ret = 1;
err:
if (ctx != NULL) {
BN_CTX_end(ctx);
if (ctx_passed == NULL)
BN_CTX_free(ctx);
}
BN_MONT_CTX_free(mont);
return ret;
}
static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
const BIGNUM *a1_odd, int k, BN_CTX *ctx,
BN_MONT_CTX *mont)
{
if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */
return -1;
if (BN_is_one(w))
return 0; /* probably prime */
if (BN_cmp(w, a1) == 0)
return 0; /* w == -1 (mod a), 'a' is probably prime */
while (--k) {
if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */
return -1;
if (BN_is_one(w))
return 1; /* 'a' is composite, otherwise a previous 'w'
* would have been == -1 (mod 'a') */
if (BN_cmp(w, a1) == 0)
return 0; /* w == -1 (mod a), 'a' is probably prime */
}
/*
* If we get here, 'w' is the (a-1)/2-th power of the original 'w', and
* it is neither -1 nor +1 -- so 'a' cannot be prime
*/
bn_check_top(w);
return 1;
}
static int probable_prime(BIGNUM *rnd, int bits, prime_t *mods)
{
int i;
BN_ULONG delta;
BN_ULONG maxdelta = BN_MASK2 - primes[NUMPRIMES - 1];
char is_single_word = bits <= BN_BITS2;
again:
/* TODO: Not all primes are private */
if (!BN_priv_rand(rnd, bits, BN_RAND_TOP_TWO, BN_RAND_BOTTOM_ODD))
return 0;
/* we now have a random number 'rnd' to test. */
for (i = 1; i < NUMPRIMES; i++) {
BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]);
if (mod == (BN_ULONG)-1)
return 0;
mods[i] = (prime_t) mod;
}
/*
* If bits is so small that it fits into a single word then we
* additionally don't want to exceed that many bits.
*/
if (is_single_word) {
BN_ULONG size_limit;
if (bits == BN_BITS2) {
/*
* Shifting by this much has undefined behaviour so we do it a
* different way
*/
size_limit = ~((BN_ULONG)0) - BN_get_word(rnd);
} else {
size_limit = (((BN_ULONG)1) << bits) - BN_get_word(rnd) - 1;
}
if (size_limit < maxdelta)
maxdelta = size_limit;
}
delta = 0;
loop:
if (is_single_word) {
BN_ULONG rnd_word = BN_get_word(rnd);
/*-
* In the case that the candidate prime is a single word then
* we check that:
* 1) It's greater than primes[i] because we shouldn't reject
* 3 as being a prime number because it's a multiple of
* three.
* 2) That it's not a multiple of a known prime. We don't
* check that rnd-1 is also coprime to all the known
* primes because there aren't many small primes where
* that's true.
*/
for (i = 1; i < NUMPRIMES && primes[i] < rnd_word; i++) {
if ((mods[i] + delta) % primes[i] == 0) {
delta += 2;
if (delta > maxdelta)
goto again;
goto loop;
}
}
} else {
for (i = 1; i < NUMPRIMES; i++) {
/*
* check that rnd is not a prime and also that gcd(rnd-1,primes)
* == 1 (except for 2)
*/
if (((mods[i] + delta) % primes[i]) <= 1) {
delta += 2;
if (delta > maxdelta)
goto again;
goto loop;
}
}
}
if (!BN_add_word(rnd, delta))
return 0;
if (BN_num_bits(rnd) != bits)
goto again;
bn_check_top(rnd);
return 1;
}
int bn_probable_prime_dh(BIGNUM *rnd, int bits,
const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx)
{
int i, ret = 0;
BIGNUM *t1;
BN_CTX_start(ctx);
if ((t1 = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_rand(rnd, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD))
goto err;
/* we need ((rnd-rem) % add) == 0 */
if (!BN_mod(t1, rnd, add, ctx))
goto err;
if (!BN_sub(rnd, rnd, t1))
goto err;
if (rem == NULL) {
if (!BN_add_word(rnd, 1))
goto err;
} else {
if (!BN_add(rnd, rnd, rem))
goto err;
}
/* we now have a random number 'rand' to test. */
loop:
for (i = 1; i < NUMPRIMES; i++) {
/* check that rnd is a prime */
BN_ULONG mod = BN_mod_word(rnd, (BN_ULONG)primes[i]);
if (mod == (BN_ULONG)-1)
goto err;
if (mod <= 1) {
if (!BN_add(rnd, rnd, add))
goto err;
goto loop;
}
}
ret = 1;
err:
BN_CTX_end(ctx);
bn_check_top(rnd);
return ret;
}
static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd,
const BIGNUM *rem, BN_CTX *ctx)
{
int i, ret = 0;
BIGNUM *t1, *qadd, *q;
bits--;
BN_CTX_start(ctx);
t1 = BN_CTX_get(ctx);
q = BN_CTX_get(ctx);
qadd = BN_CTX_get(ctx);
if (qadd == NULL)
goto err;
if (!BN_rshift1(qadd, padd))
goto err;
if (!BN_rand(q, bits, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ODD))
goto err;
/* we need ((rnd-rem) % add) == 0 */
if (!BN_mod(t1, q, qadd, ctx))
goto err;
if (!BN_sub(q, q, t1))
goto err;
if (rem == NULL) {
if (!BN_add_word(q, 1))
goto err;
} else {
if (!BN_rshift1(t1, rem))
goto err;
if (!BN_add(q, q, t1))
goto err;
}
/* we now have a random number 'rand' to test. */
if (!BN_lshift1(p, q))
goto err;
if (!BN_add_word(p, 1))
goto err;
loop:
for (i = 1; i < NUMPRIMES; i++) {
/* check that p and q are prime */
/*
* check that for p and q gcd(p-1,primes) == 1 (except for 2)
*/
BN_ULONG pmod = BN_mod_word(p, (BN_ULONG)primes[i]);
BN_ULONG qmod = BN_mod_word(q, (BN_ULONG)primes[i]);
if (pmod == (BN_ULONG)-1 || qmod == (BN_ULONG)-1)
goto err;
if (pmod == 0 || qmod == 0) {
if (!BN_add(p, p, padd))
goto err;
if (!BN_add(q, q, qadd))
goto err;
goto loop;
}
}
ret = 1;
err:
BN_CTX_end(ctx);
bn_check_top(p);
return ret;
}
diff --git a/crypto/chacha/build.info b/crypto/chacha/build.info
index 02f8e518aeca..e75ca72b67d4 100644
--- a/crypto/chacha/build.info
+++ b/crypto/chacha/build.info
@@ -1,18 +1,20 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]={- $target{chacha_asm_src} -}
GENERATE[chacha-x86.s]=asm/chacha-x86.pl \
$(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
GENERATE[chacha-x86_64.s]=asm/chacha-x86_64.pl $(PERLASM_SCHEME)
GENERATE[chacha-ppc.s]=asm/chacha-ppc.pl $(PERLASM_SCHEME)
GENERATE[chacha-armv4.S]=asm/chacha-armv4.pl $(PERLASM_SCHEME)
INCLUDE[chacha-armv4.o]=..
GENERATE[chacha-armv8.S]=asm/chacha-armv8.pl $(PERLASM_SCHEME)
INCLUDE[chacha-armv8.o]=..
+GENERATE[chacha-s390x.S]=asm/chacha-s390x.pl $(PERLASM_SCHEME)
+INCLUDE[chacha-s390x.o]=..
BEGINRAW[Makefile(unix)]
##### CHACHA assembler implementations
{- $builddir -}/chacha-%.S: {- $sourcedir -}/asm/chacha-%.pl
CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
ENDRAW[Makefile(unix)]
diff --git a/crypto/conf/conf_sap.c b/crypto/conf/conf_sap.c
index 2ce42f0c6740..3805c426d802 100644
--- a/crypto/conf/conf_sap.c
+++ b/crypto/conf/conf_sap.c
@@ -1,77 +1,78 @@
/*
* Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include "internal/conf.h"
#include <openssl/x509.h>
#include <openssl/asn1.h>
#include <openssl/engine.h>
#ifdef _WIN32
# define strdup _strdup
#endif
/*
* This is the automatic configuration loader: it is called automatically by
* OpenSSL when any of a number of standard initialisation functions are
* called, unless this is overridden by calling OPENSSL_no_config()
*/
static int openssl_configured = 0;
#if OPENSSL_API_COMPAT < 0x10100000L
void OPENSSL_config(const char *appname)
{
OPENSSL_INIT_SETTINGS settings;
memset(&settings, 0, sizeof(settings));
if (appname != NULL)
settings.appname = strdup(appname);
+ settings.flags = DEFAULT_CONF_MFLAGS;
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, &settings);
}
#endif
int openssl_config_int(const OPENSSL_INIT_SETTINGS *settings)
{
int ret;
const char *filename;
const char *appname;
unsigned long flags;
if (openssl_configured)
return 1;
filename = settings ? settings->filename : NULL;
appname = settings ? settings->appname : NULL;
flags = settings ? settings->flags : DEFAULT_CONF_MFLAGS;
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: openssl_config_int(%s, %s, %lu)\n",
filename, appname, flags);
#endif
OPENSSL_load_builtin_modules();
#ifndef OPENSSL_NO_ENGINE
/* Need to load ENGINEs */
ENGINE_load_builtin_engines();
#endif
ERR_clear_error();
#ifndef OPENSSL_SYS_UEFI
ret = CONF_modules_load_file(filename, appname, flags);
#endif
openssl_configured = 1;
return ret;
}
void openssl_no_config_int(void)
{
openssl_configured = 1;
}
diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c
index fc45577101d0..c7e1dbf4ac0f 100644
--- a/crypto/dh/dh_check.c
+++ b/crypto/dh/dh_check.c
@@ -1,233 +1,229 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include "dh_locl.h"
+# define DH_NUMBER_ITERATIONS_FOR_PRIME 64
+
/*-
* Check that p and g are suitable enough
*
* p is odd
* 1 < g < p - 1
*/
int DH_check_params_ex(const DH *dh)
{
int errflags = 0;
(void)DH_check_params(dh, &errflags);
if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_CHECK_P_NOT_PRIME);
if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
DHerr(DH_F_DH_CHECK_PARAMS_EX, DH_R_NOT_SUITABLE_GENERATOR);
return errflags == 0;
}
int DH_check_params(const DH *dh, int *ret)
{
int ok = 0;
BIGNUM *tmp = NULL;
BN_CTX *ctx = NULL;
*ret = 0;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL)
goto err;
if (!BN_is_odd(dh->p))
*ret |= DH_CHECK_P_NOT_PRIME;
if (BN_is_negative(dh->g) || BN_is_zero(dh->g) || BN_is_one(dh->g))
*ret |= DH_NOT_SUITABLE_GENERATOR;
if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
goto err;
if (BN_cmp(dh->g, tmp) >= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR;
ok = 1;
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
/*-
* Check that p is a safe prime and
* if g is 2, 3 or 5, check that it is a suitable generator
* where
* for 2, p mod 24 == 11
* for 3, p mod 12 == 5
* for 5, p mod 10 == 3 or 7
* should hold.
*/
int DH_check_ex(const DH *dh)
{
int errflags = 0;
(void)DH_check(dh, &errflags);
if ((errflags & DH_NOT_SUITABLE_GENERATOR) != 0)
DHerr(DH_F_DH_CHECK_EX, DH_R_NOT_SUITABLE_GENERATOR);
if ((errflags & DH_CHECK_Q_NOT_PRIME) != 0)
DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_Q_NOT_PRIME);
if ((errflags & DH_CHECK_INVALID_Q_VALUE) != 0)
DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_Q_VALUE);
if ((errflags & DH_CHECK_INVALID_J_VALUE) != 0)
DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_INVALID_J_VALUE);
if ((errflags & DH_UNABLE_TO_CHECK_GENERATOR) != 0)
DHerr(DH_F_DH_CHECK_EX, DH_R_UNABLE_TO_CHECK_GENERATOR);
if ((errflags & DH_CHECK_P_NOT_PRIME) != 0)
DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_PRIME);
if ((errflags & DH_CHECK_P_NOT_SAFE_PRIME) != 0)
DHerr(DH_F_DH_CHECK_EX, DH_R_CHECK_P_NOT_SAFE_PRIME);
return errflags == 0;
}
int DH_check(const DH *dh, int *ret)
{
int ok = 0, r;
BN_CTX *ctx = NULL;
BN_ULONG l;
BIGNUM *t1 = NULL, *t2 = NULL;
*ret = 0;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
t1 = BN_CTX_get(ctx);
t2 = BN_CTX_get(ctx);
if (t2 == NULL)
goto err;
if (dh->q) {
if (BN_cmp(dh->g, BN_value_one()) <= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR;
else if (BN_cmp(dh->g, dh->p) >= 0)
*ret |= DH_NOT_SUITABLE_GENERATOR;
else {
/* Check g^q == 1 mod p */
if (!BN_mod_exp(t1, dh->g, dh->q, dh->p, ctx))
goto err;
if (!BN_is_one(t1))
*ret |= DH_NOT_SUITABLE_GENERATOR;
}
- r = BN_is_prime_ex(dh->q, BN_prime_checks, ctx, NULL);
+ r = BN_is_prime_ex(dh->q, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
*ret |= DH_CHECK_Q_NOT_PRIME;
/* Check p == 1 mod q i.e. q divides p - 1 */
if (!BN_div(t1, t2, dh->p, dh->q, ctx))
goto err;
if (!BN_is_one(t2))
*ret |= DH_CHECK_INVALID_Q_VALUE;
if (dh->j && BN_cmp(dh->j, t1))
*ret |= DH_CHECK_INVALID_J_VALUE;
} else if (BN_is_word(dh->g, DH_GENERATOR_2)) {
l = BN_mod_word(dh->p, 24);
if (l == (BN_ULONG)-1)
goto err;
if (l != 11)
*ret |= DH_NOT_SUITABLE_GENERATOR;
} else if (BN_is_word(dh->g, DH_GENERATOR_5)) {
l = BN_mod_word(dh->p, 10);
if (l == (BN_ULONG)-1)
goto err;
if ((l != 3) && (l != 7))
*ret |= DH_NOT_SUITABLE_GENERATOR;
} else
*ret |= DH_UNABLE_TO_CHECK_GENERATOR;
- r = BN_is_prime_ex(dh->p, BN_prime_checks, ctx, NULL);
+ r = BN_is_prime_ex(dh->p, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
*ret |= DH_CHECK_P_NOT_PRIME;
else if (!dh->q) {
if (!BN_rshift1(t1, dh->p))
goto err;
- r = BN_is_prime_ex(t1, BN_prime_checks, ctx, NULL);
+ r = BN_is_prime_ex(t1, DH_NUMBER_ITERATIONS_FOR_PRIME, ctx, NULL);
if (r < 0)
goto err;
if (!r)
*ret |= DH_CHECK_P_NOT_SAFE_PRIME;
}
ok = 1;
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
int DH_check_pub_key_ex(const DH *dh, const BIGNUM *pub_key)
{
int errflags = 0;
(void)DH_check(dh, &errflags);
if ((errflags & DH_CHECK_PUBKEY_TOO_SMALL) != 0)
DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_SMALL);
if ((errflags & DH_CHECK_PUBKEY_TOO_LARGE) != 0)
DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_TOO_LARGE);
if ((errflags & DH_CHECK_PUBKEY_INVALID) != 0)
DHerr(DH_F_DH_CHECK_PUB_KEY_EX, DH_R_CHECK_PUBKEY_INVALID);
return errflags == 0;
}
int DH_check_pub_key(const DH *dh, const BIGNUM *pub_key, int *ret)
{
int ok = 0;
BIGNUM *tmp = NULL;
BN_CTX *ctx = NULL;
*ret = 0;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL || !BN_set_word(tmp, 1))
goto err;
if (BN_cmp(pub_key, tmp) <= 0)
*ret |= DH_CHECK_PUBKEY_TOO_SMALL;
if (BN_copy(tmp, dh->p) == NULL || !BN_sub_word(tmp, 1))
goto err;
if (BN_cmp(pub_key, tmp) >= 0)
*ret |= DH_CHECK_PUBKEY_TOO_LARGE;
if (dh->q != NULL) {
/* Check pub_key^q == 1 mod p */
if (!BN_mod_exp(tmp, pub_key, dh->q, dh->p, ctx))
goto err;
if (!BN_is_one(tmp))
*ret |= DH_CHECK_PUBKEY_INVALID;
}
ok = 1;
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c
index 59137e0f05aa..887fc4c3aede 100644
--- a/crypto/dh/dh_gen.c
+++ b/crypto/dh/dh_gen.c
@@ -1,130 +1,128 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* NB: These functions have been upgraded - the previous prototypes are in
* dh_depr.c as wrappers to these ones. - Geoff
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include "dh_locl.h"
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
BN_GENCB *cb);
int DH_generate_parameters_ex(DH *ret, int prime_len, int generator,
BN_GENCB *cb)
{
if (ret->meth->generate_params)
return ret->meth->generate_params(ret, prime_len, generator, cb);
return dh_builtin_genparams(ret, prime_len, generator, cb);
}
/*-
* We generate DH parameters as follows
* find a prime q which is prime_len/2 bits long.
* p=(2*q)+1 or (p-1)/2 = q
* For this case, g is a generator if
* g^((p-1)/q) mod p != 1 for values of q which are the factors of p-1.
* Since the factors of p-1 are q and 2, we just need to check
* g^2 mod p != 1 and g^q mod p != 1.
*
* Having said all that,
* there is another special case method for the generators 2, 3 and 5.
* for 2, p mod 24 == 11
* for 3, p mod 12 == 5 <<<<< does not work for safe primes.
* for 5, p mod 10 == 3 or 7
*
* Thanks to Phil Karn for the pointers about the
* special generators and for answering some of my questions.
*
* I've implemented the second simple method :-).
* Since DH should be using a safe prime (both p and q are prime),
* this generator function can take a very very long time to run.
*/
/*
* Actually there is no reason to insist that 'generator' be a generator.
* It's just as OK (and in some sense better) to use a generator of the
* order-q subgroup.
*/
static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
BN_GENCB *cb)
{
BIGNUM *t1, *t2;
int g, ok = -1;
BN_CTX *ctx = NULL;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
t1 = BN_CTX_get(ctx);
t2 = BN_CTX_get(ctx);
if (t2 == NULL)
goto err;
/* Make sure 'ret' has the necessary elements */
if (!ret->p && ((ret->p = BN_new()) == NULL))
goto err;
if (!ret->g && ((ret->g = BN_new()) == NULL))
goto err;
if (generator <= 1) {
DHerr(DH_F_DH_BUILTIN_GENPARAMS, DH_R_BAD_GENERATOR);
goto err;
}
if (generator == DH_GENERATOR_2) {
if (!BN_set_word(t1, 24))
goto err;
if (!BN_set_word(t2, 11))
goto err;
g = 2;
} else if (generator == DH_GENERATOR_5) {
if (!BN_set_word(t1, 10))
goto err;
if (!BN_set_word(t2, 3))
goto err;
/*
* BN_set_word(t3,7); just have to miss out on these ones :-(
*/
g = 5;
} else {
/*
* in the general case, don't worry if 'generator' is a generator or
* not: since we are using safe primes, it will generate either an
* order-q or an order-2q group, which both is OK
*/
if (!BN_set_word(t1, 2))
goto err;
if (!BN_set_word(t2, 1))
goto err;
g = generator;
}
if (!BN_generate_prime_ex(ret->p, prime_len, 1, t1, t2, cb))
goto err;
if (!BN_GENCB_call(cb, 3, 0))
goto err;
if (!BN_set_word(ret->g, g))
goto err;
ok = 1;
err:
if (ok == -1) {
DHerr(DH_F_DH_BUILTIN_GENPARAMS, ERR_R_BN_LIB);
ok = 0;
}
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ok;
}
diff --git a/crypto/dh/dh_key.c b/crypto/dh/dh_key.c
index 4f85be7e49bd..99c00e5a05d1 100644
--- a/crypto/dh/dh_key.c
+++ b/crypto/dh/dh_key.c
@@ -1,232 +1,230 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "dh_locl.h"
#include "internal/bn_int.h"
static int generate_key(DH *dh);
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh);
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
static int dh_init(DH *dh);
static int dh_finish(DH *dh);
int DH_generate_key(DH *dh)
{
return dh->meth->generate_key(dh);
}
int DH_compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
{
return dh->meth->compute_key(key, pub_key, dh);
}
int DH_compute_key_padded(unsigned char *key, const BIGNUM *pub_key, DH *dh)
{
int rv, pad;
rv = dh->meth->compute_key(key, pub_key, dh);
if (rv <= 0)
return rv;
pad = BN_num_bytes(dh->p) - rv;
if (pad > 0) {
memmove(key + pad, key, rv);
memset(key, 0, pad);
}
return rv + pad;
}
static DH_METHOD dh_ossl = {
"OpenSSL DH Method",
generate_key,
compute_key,
dh_bn_mod_exp,
dh_init,
dh_finish,
DH_FLAG_FIPS_METHOD,
NULL,
NULL
};
static const DH_METHOD *default_DH_method = &dh_ossl;
const DH_METHOD *DH_OpenSSL(void)
{
return &dh_ossl;
}
void DH_set_default_method(const DH_METHOD *meth)
{
default_DH_method = meth;
}
const DH_METHOD *DH_get_default_method(void)
{
return default_DH_method;
}
static int generate_key(DH *dh)
{
int ok = 0;
int generate_new_key = 0;
unsigned l;
BN_CTX *ctx = NULL;
BN_MONT_CTX *mont = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
DHerr(DH_F_GENERATE_KEY, DH_R_MODULUS_TOO_LARGE);
return 0;
}
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
if (dh->priv_key == NULL) {
priv_key = BN_secure_new();
if (priv_key == NULL)
goto err;
generate_new_key = 1;
} else
priv_key = dh->priv_key;
if (dh->pub_key == NULL) {
pub_key = BN_new();
if (pub_key == NULL)
goto err;
} else
pub_key = dh->pub_key;
if (dh->flags & DH_FLAG_CACHE_MONT_P) {
mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
dh->lock, dh->p, ctx);
if (!mont)
goto err;
}
if (generate_new_key) {
if (dh->q) {
do {
if (!BN_priv_rand_range(priv_key, dh->q))
goto err;
}
while (BN_is_zero(priv_key) || BN_is_one(priv_key));
} else {
/* secret exponent length */
l = dh->length ? dh->length : BN_num_bits(dh->p) - 1;
if (!BN_priv_rand(priv_key, l, BN_RAND_TOP_ONE, BN_RAND_BOTTOM_ANY))
goto err;
}
}
{
BIGNUM *prk = BN_new();
if (prk == NULL)
goto err;
BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
if (!dh->meth->bn_mod_exp(dh, pub_key, dh->g, prk, dh->p, ctx, mont)) {
BN_free(prk);
goto err;
}
/* We MUST free prk before any further use of priv_key */
BN_free(prk);
}
dh->pub_key = pub_key;
dh->priv_key = priv_key;
ok = 1;
err:
if (ok != 1)
DHerr(DH_F_GENERATE_KEY, ERR_R_BN_LIB);
if (pub_key != dh->pub_key)
BN_free(pub_key);
if (priv_key != dh->priv_key)
BN_free(priv_key);
BN_CTX_free(ctx);
return ok;
}
static int compute_key(unsigned char *key, const BIGNUM *pub_key, DH *dh)
{
BN_CTX *ctx = NULL;
BN_MONT_CTX *mont = NULL;
BIGNUM *tmp;
int ret = -1;
int check_result;
if (BN_num_bits(dh->p) > OPENSSL_DH_MAX_MODULUS_BITS) {
DHerr(DH_F_COMPUTE_KEY, DH_R_MODULUS_TOO_LARGE);
goto err;
}
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL)
goto err;
if (dh->priv_key == NULL) {
DHerr(DH_F_COMPUTE_KEY, DH_R_NO_PRIVATE_VALUE);
goto err;
}
if (dh->flags & DH_FLAG_CACHE_MONT_P) {
mont = BN_MONT_CTX_set_locked(&dh->method_mont_p,
dh->lock, dh->p, ctx);
BN_set_flags(dh->priv_key, BN_FLG_CONSTTIME);
if (!mont)
goto err;
}
if (!DH_check_pub_key(dh, pub_key, &check_result) || check_result) {
DHerr(DH_F_COMPUTE_KEY, DH_R_INVALID_PUBKEY);
goto err;
}
if (!dh->
meth->bn_mod_exp(dh, tmp, pub_key, dh->priv_key, dh->p, ctx, mont)) {
DHerr(DH_F_COMPUTE_KEY, ERR_R_BN_LIB);
goto err;
}
ret = BN_bn2bin(tmp, key);
err:
- if (ctx != NULL) {
- BN_CTX_end(ctx);
- BN_CTX_free(ctx);
- }
+ BN_CTX_end(ctx);
+ BN_CTX_free(ctx);
return ret;
}
static int dh_bn_mod_exp(const DH *dh, BIGNUM *r,
const BIGNUM *a, const BIGNUM *p,
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
{
return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
}
static int dh_init(DH *dh)
{
dh->flags |= DH_FLAG_CACHE_MONT_P;
return 1;
}
static int dh_finish(DH *dh)
{
BN_MONT_CTX_free(dh->method_mont_p);
return 1;
}
diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
index cce2d9e26efc..568831f1c2a7 100644
--- a/crypto/dh/dh_pmeth.c
+++ b/crypto/dh/dh_pmeth.c
@@ -1,547 +1,547 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/evp.h>
#include "dh_locl.h"
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/objects.h>
#include "internal/evp_int.h"
/* DH pkey context structure */
typedef struct {
/* Parameter gen parameters */
int prime_len;
int generator;
int use_dsa;
int subprime_len;
int pad;
/* message digest used for parameter generation */
const EVP_MD *md;
int rfc5114_param;
int param_nid;
/* Keygen callback info */
int gentmp[2];
/* KDF (if any) to use for DH */
char kdf_type;
/* OID to use for KDF */
ASN1_OBJECT *kdf_oid;
/* Message digest to use for key derivation */
const EVP_MD *kdf_md;
/* User key material */
unsigned char *kdf_ukm;
size_t kdf_ukmlen;
/* KDF output length */
size_t kdf_outlen;
} DH_PKEY_CTX;
static int pkey_dh_init(EVP_PKEY_CTX *ctx)
{
DH_PKEY_CTX *dctx;
if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
DHerr(DH_F_PKEY_DH_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
- dctx->prime_len = 1024;
+ dctx->prime_len = 2048;
dctx->subprime_len = -1;
dctx->generator = 2;
dctx->kdf_type = EVP_PKEY_DH_KDF_NONE;
ctx->data = dctx;
ctx->keygen_info = dctx->gentmp;
ctx->keygen_info_count = 2;
return 1;
}
static void pkey_dh_cleanup(EVP_PKEY_CTX *ctx)
{
DH_PKEY_CTX *dctx = ctx->data;
if (dctx != NULL) {
OPENSSL_free(dctx->kdf_ukm);
ASN1_OBJECT_free(dctx->kdf_oid);
OPENSSL_free(dctx);
}
}
static int pkey_dh_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
DH_PKEY_CTX *dctx, *sctx;
if (!pkey_dh_init(dst))
return 0;
sctx = src->data;
dctx = dst->data;
dctx->prime_len = sctx->prime_len;
dctx->subprime_len = sctx->subprime_len;
dctx->generator = sctx->generator;
dctx->use_dsa = sctx->use_dsa;
dctx->pad = sctx->pad;
dctx->md = sctx->md;
dctx->rfc5114_param = sctx->rfc5114_param;
dctx->param_nid = sctx->param_nid;
dctx->kdf_type = sctx->kdf_type;
dctx->kdf_oid = OBJ_dup(sctx->kdf_oid);
if (dctx->kdf_oid == NULL)
return 0;
dctx->kdf_md = sctx->kdf_md;
if (sctx->kdf_ukm != NULL) {
dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
if (dctx->kdf_ukm == NULL)
return 0;
dctx->kdf_ukmlen = sctx->kdf_ukmlen;
}
dctx->kdf_outlen = sctx->kdf_outlen;
return 1;
}
static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
DH_PKEY_CTX *dctx = ctx->data;
switch (type) {
case EVP_PKEY_CTRL_DH_PARAMGEN_PRIME_LEN:
if (p1 < 256)
return -2;
dctx->prime_len = p1;
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_SUBPRIME_LEN:
if (dctx->use_dsa == 0)
return -2;
dctx->subprime_len = p1;
return 1;
case EVP_PKEY_CTRL_DH_PAD:
dctx->pad = p1;
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_GENERATOR:
if (dctx->use_dsa)
return -2;
dctx->generator = p1;
return 1;
case EVP_PKEY_CTRL_DH_PARAMGEN_TYPE:
#ifdef OPENSSL_NO_DSA
if (p1 != 0)
return -2;
#else
if (p1 < 0 || p1 > 2)
return -2;
#endif
dctx->use_dsa = p1;
return 1;
case EVP_PKEY_CTRL_DH_RFC5114:
if (p1 < 1 || p1 > 3 || dctx->param_nid != NID_undef)
return -2;
dctx->rfc5114_param = p1;
return 1;
case EVP_PKEY_CTRL_DH_NID:
if (p1 <= 0 || dctx->rfc5114_param != 0)
return -2;
dctx->param_nid = p1;
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
/* Default behaviour is OK */
return 1;
case EVP_PKEY_CTRL_DH_KDF_TYPE:
if (p1 == -2)
return dctx->kdf_type;
#ifdef OPENSSL_NO_CMS
if (p1 != EVP_PKEY_DH_KDF_NONE)
#else
if (p1 != EVP_PKEY_DH_KDF_NONE && p1 != EVP_PKEY_DH_KDF_X9_42)
#endif
return -2;
dctx->kdf_type = p1;
return 1;
case EVP_PKEY_CTRL_DH_KDF_MD:
dctx->kdf_md = p2;
return 1;
case EVP_PKEY_CTRL_GET_DH_KDF_MD:
*(const EVP_MD **)p2 = dctx->kdf_md;
return 1;
case EVP_PKEY_CTRL_DH_KDF_OUTLEN:
if (p1 <= 0)
return -2;
dctx->kdf_outlen = (size_t)p1;
return 1;
case EVP_PKEY_CTRL_GET_DH_KDF_OUTLEN:
*(int *)p2 = dctx->kdf_outlen;
return 1;
case EVP_PKEY_CTRL_DH_KDF_UKM:
OPENSSL_free(dctx->kdf_ukm);
dctx->kdf_ukm = p2;
if (p2)
dctx->kdf_ukmlen = p1;
else
dctx->kdf_ukmlen = 0;
return 1;
case EVP_PKEY_CTRL_GET_DH_KDF_UKM:
*(unsigned char **)p2 = dctx->kdf_ukm;
return dctx->kdf_ukmlen;
case EVP_PKEY_CTRL_DH_KDF_OID:
ASN1_OBJECT_free(dctx->kdf_oid);
dctx->kdf_oid = p2;
return 1;
case EVP_PKEY_CTRL_GET_DH_KDF_OID:
*(ASN1_OBJECT **)p2 = dctx->kdf_oid;
return 1;
default:
return -2;
}
}
static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if (strcmp(type, "dh_paramgen_prime_len") == 0) {
int len;
len = atoi(value);
return EVP_PKEY_CTX_set_dh_paramgen_prime_len(ctx, len);
}
if (strcmp(type, "dh_rfc5114") == 0) {
DH_PKEY_CTX *dctx = ctx->data;
int len;
len = atoi(value);
if (len < 0 || len > 3)
return -2;
dctx->rfc5114_param = len;
return 1;
}
if (strcmp(type, "dh_param") == 0) {
DH_PKEY_CTX *dctx = ctx->data;
int nid = OBJ_sn2nid(value);
if (nid == NID_undef) {
DHerr(DH_F_PKEY_DH_CTRL_STR, DH_R_INVALID_PARAMETER_NAME);
return -2;
}
dctx->param_nid = nid;
return 1;
}
if (strcmp(type, "dh_paramgen_generator") == 0) {
int len;
len = atoi(value);
return EVP_PKEY_CTX_set_dh_paramgen_generator(ctx, len);
}
if (strcmp(type, "dh_paramgen_subprime_len") == 0) {
int len;
len = atoi(value);
return EVP_PKEY_CTX_set_dh_paramgen_subprime_len(ctx, len);
}
if (strcmp(type, "dh_paramgen_type") == 0) {
int typ;
typ = atoi(value);
return EVP_PKEY_CTX_set_dh_paramgen_type(ctx, typ);
}
if (strcmp(type, "dh_pad") == 0) {
int pad;
pad = atoi(value);
return EVP_PKEY_CTX_set_dh_pad(ctx, pad);
}
return -2;
}
#ifndef OPENSSL_NO_DSA
extern int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
const EVP_MD *evpmd,
const unsigned char *seed_in, size_t seed_len,
unsigned char *seed_out, int *counter_ret,
unsigned long *h_ret, BN_GENCB *cb);
extern int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
const EVP_MD *evpmd,
const unsigned char *seed_in,
size_t seed_len, int idx,
unsigned char *seed_out, int *counter_ret,
unsigned long *h_ret, BN_GENCB *cb);
static DSA *dsa_dh_generate(DH_PKEY_CTX *dctx, BN_GENCB *pcb)
{
DSA *ret;
int rv = 0;
int prime_len = dctx->prime_len;
int subprime_len = dctx->subprime_len;
const EVP_MD *md = dctx->md;
if (dctx->use_dsa > 2)
return NULL;
ret = DSA_new();
if (ret == NULL)
return NULL;
if (subprime_len == -1) {
if (prime_len >= 2048)
subprime_len = 256;
else
subprime_len = 160;
}
if (md == NULL) {
if (prime_len >= 2048)
md = EVP_sha256();
else
md = EVP_sha1();
}
if (dctx->use_dsa == 1)
rv = dsa_builtin_paramgen(ret, prime_len, subprime_len, md,
NULL, 0, NULL, NULL, NULL, pcb);
else if (dctx->use_dsa == 2)
rv = dsa_builtin_paramgen2(ret, prime_len, subprime_len, md,
NULL, 0, -1, NULL, NULL, NULL, pcb);
if (rv <= 0) {
DSA_free(ret);
return NULL;
}
return ret;
}
#endif
static int pkey_dh_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
DH *dh = NULL;
DH_PKEY_CTX *dctx = ctx->data;
BN_GENCB *pcb;
int ret;
if (dctx->rfc5114_param) {
switch (dctx->rfc5114_param) {
case 1:
dh = DH_get_1024_160();
break;
case 2:
dh = DH_get_2048_224();
break;
case 3:
dh = DH_get_2048_256();
break;
default:
return -2;
}
EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
return 1;
}
if (dctx->param_nid != 0) {
if ((dh = DH_new_by_nid(dctx->param_nid)) == NULL)
return 0;
EVP_PKEY_assign(pkey, EVP_PKEY_DH, dh);
return 1;
}
if (ctx->pkey_gencb) {
pcb = BN_GENCB_new();
if (pcb == NULL)
return 0;
evp_pkey_set_cb_translate(pcb, ctx);
} else
pcb = NULL;
#ifndef OPENSSL_NO_DSA
if (dctx->use_dsa) {
DSA *dsa_dh;
dsa_dh = dsa_dh_generate(dctx, pcb);
BN_GENCB_free(pcb);
if (dsa_dh == NULL)
return 0;
dh = DSA_dup_DH(dsa_dh);
DSA_free(dsa_dh);
if (!dh)
return 0;
EVP_PKEY_assign(pkey, EVP_PKEY_DHX, dh);
return 1;
}
#endif
dh = DH_new();
if (dh == NULL) {
BN_GENCB_free(pcb);
return 0;
}
ret = DH_generate_parameters_ex(dh,
dctx->prime_len, dctx->generator, pcb);
BN_GENCB_free(pcb);
if (ret)
EVP_PKEY_assign_DH(pkey, dh);
else
DH_free(dh);
return ret;
}
static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
DH_PKEY_CTX *dctx = ctx->data;
DH *dh = NULL;
if (ctx->pkey == NULL && dctx->param_nid == 0) {
DHerr(DH_F_PKEY_DH_KEYGEN, DH_R_NO_PARAMETERS_SET);
return 0;
}
if (dctx->param_nid != 0)
dh = DH_new_by_nid(dctx->param_nid);
else
dh = DH_new();
if (dh == NULL)
return 0;
EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, dh);
/* Note: if error return, pkey is freed by parent routine */
if (ctx->pkey != NULL && !EVP_PKEY_copy_parameters(pkey, ctx->pkey))
return 0;
return DH_generate_key(pkey->pkey.dh);
}
static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
size_t *keylen)
{
int ret;
DH *dh;
DH_PKEY_CTX *dctx = ctx->data;
BIGNUM *dhpub;
if (!ctx->pkey || !ctx->peerkey) {
DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET);
return 0;
}
dh = ctx->pkey->pkey.dh;
dhpub = ctx->peerkey->pkey.dh->pub_key;
if (dctx->kdf_type == EVP_PKEY_DH_KDF_NONE) {
if (key == NULL) {
*keylen = DH_size(dh);
return 1;
}
if (dctx->pad)
ret = DH_compute_key_padded(key, dhpub, dh);
else
ret = DH_compute_key(key, dhpub, dh);
if (ret < 0)
return ret;
*keylen = ret;
return 1;
}
#ifndef OPENSSL_NO_CMS
else if (dctx->kdf_type == EVP_PKEY_DH_KDF_X9_42) {
unsigned char *Z = NULL;
size_t Zlen = 0;
if (!dctx->kdf_outlen || !dctx->kdf_oid)
return 0;
if (key == NULL) {
*keylen = dctx->kdf_outlen;
return 1;
}
if (*keylen != dctx->kdf_outlen)
return 0;
ret = 0;
Zlen = DH_size(dh);
Z = OPENSSL_malloc(Zlen);
if (Z == NULL) {
goto err;
}
if (DH_compute_key_padded(Z, dhpub, dh) <= 0)
goto err;
if (!DH_KDF_X9_42(key, *keylen, Z, Zlen, dctx->kdf_oid,
dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
goto err;
*keylen = dctx->kdf_outlen;
ret = 1;
err:
OPENSSL_clear_free(Z, Zlen);
return ret;
}
#endif
return 0;
}
const EVP_PKEY_METHOD dh_pkey_meth = {
EVP_PKEY_DH,
0,
pkey_dh_init,
pkey_dh_copy,
pkey_dh_cleanup,
0,
pkey_dh_paramgen,
0,
pkey_dh_keygen,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
0,
pkey_dh_derive,
pkey_dh_ctrl,
pkey_dh_ctrl_str
};
const EVP_PKEY_METHOD dhx_pkey_meth = {
EVP_PKEY_DHX,
0,
pkey_dh_init,
pkey_dh_copy,
pkey_dh_cleanup,
0,
pkey_dh_paramgen,
0,
pkey_dh_keygen,
0,
0,
0,
0,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
0,
pkey_dh_derive,
pkey_dh_ctrl,
pkey_dh_ctrl_str
};
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
index 383d853b6d37..af59a582b53e 100644
--- a/crypto/dsa/dsa_gen.c
+++ b/crypto/dsa/dsa_gen.c
@@ -1,616 +1,614 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Parameter generation follows the updated Appendix 2.2 for FIPS PUB 186,
* also Appendix 2.2 of FIPS PUB 186-1 (i.e. use SHA as defined in FIPS PUB
* 180-1)
*/
#define xxxHASH EVP_sha1()
#include <openssl/opensslconf.h>
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include "dsa_locl.h"
int DSA_generate_parameters_ex(DSA *ret, int bits,
const unsigned char *seed_in, int seed_len,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb)
{
if (ret->meth->dsa_paramgen)
return ret->meth->dsa_paramgen(ret, bits, seed_in, seed_len,
counter_ret, h_ret, cb);
else {
const EVP_MD *evpmd = bits >= 2048 ? EVP_sha256() : EVP_sha1();
size_t qbits = EVP_MD_size(evpmd) * 8;
return dsa_builtin_paramgen(ret, bits, qbits, evpmd,
seed_in, seed_len, NULL, counter_ret,
h_ret, cb);
}
}
int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
const EVP_MD *evpmd, const unsigned char *seed_in,
size_t seed_len, unsigned char *seed_out,
int *counter_ret, unsigned long *h_ret, BN_GENCB *cb)
{
int ok = 0;
unsigned char seed[SHA256_DIGEST_LENGTH];
unsigned char md[SHA256_DIGEST_LENGTH];
unsigned char buf[SHA256_DIGEST_LENGTH], buf2[SHA256_DIGEST_LENGTH];
BIGNUM *r0, *W, *X, *c, *test;
BIGNUM *g = NULL, *q = NULL, *p = NULL;
BN_MONT_CTX *mont = NULL;
int i, k, n = 0, m = 0, qsize = qbits >> 3;
int counter = 0;
int r = 0;
BN_CTX *ctx = NULL;
unsigned int h = 2;
if (qsize != SHA_DIGEST_LENGTH && qsize != SHA224_DIGEST_LENGTH &&
qsize != SHA256_DIGEST_LENGTH)
/* invalid q size */
return 0;
if (evpmd == NULL) {
if (qsize == SHA_DIGEST_LENGTH)
evpmd = EVP_sha1();
else if (qsize == SHA224_DIGEST_LENGTH)
evpmd = EVP_sha224();
else
evpmd = EVP_sha256();
} else {
qsize = EVP_MD_size(evpmd);
}
if (bits < 512)
bits = 512;
bits = (bits + 63) / 64 * 64;
if (seed_in != NULL) {
if (seed_len < (size_t)qsize) {
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_SEED_LEN_SMALL);
return 0;
}
if (seed_len > (size_t)qsize) {
/* Only consume as much seed as is expected. */
seed_len = qsize;
}
memcpy(seed, seed_in, seed_len);
}
if ((mont = BN_MONT_CTX_new()) == NULL)
goto err;
if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
r0 = BN_CTX_get(ctx);
g = BN_CTX_get(ctx);
W = BN_CTX_get(ctx);
q = BN_CTX_get(ctx);
X = BN_CTX_get(ctx);
c = BN_CTX_get(ctx);
p = BN_CTX_get(ctx);
test = BN_CTX_get(ctx);
if (test == NULL)
goto err;
if (!BN_lshift(test, BN_value_one(), bits - 1))
goto err;
for (;;) {
for (;;) { /* find q */
int use_random_seed = (seed_in == NULL);
/* step 1 */
if (!BN_GENCB_call(cb, 0, m++))
goto err;
if (use_random_seed) {
if (RAND_bytes(seed, qsize) <= 0)
goto err;
} else {
/* If we come back through, use random seed next time. */
seed_in = NULL;
}
memcpy(buf, seed, qsize);
memcpy(buf2, seed, qsize);
/* precompute "SEED + 1" for step 7: */
for (i = qsize - 1; i >= 0; i--) {
buf[i]++;
if (buf[i] != 0)
break;
}
/* step 2 */
if (!EVP_Digest(seed, qsize, md, NULL, evpmd, NULL))
goto err;
if (!EVP_Digest(buf, qsize, buf2, NULL, evpmd, NULL))
goto err;
for (i = 0; i < qsize; i++)
md[i] ^= buf2[i];
/* step 3 */
md[0] |= 0x80;
md[qsize - 1] |= 0x01;
if (!BN_bin2bn(md, qsize, q))
goto err;
/* step 4 */
r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
use_random_seed, cb);
if (r > 0)
break;
if (r != 0)
goto err;
/* do a callback call */
/* step 5 */
}
if (!BN_GENCB_call(cb, 2, 0))
goto err;
if (!BN_GENCB_call(cb, 3, 0))
goto err;
/* step 6 */
counter = 0;
/* "offset = 2" */
n = (bits - 1) / 160;
for (;;) {
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
goto err;
/* step 7 */
BN_zero(W);
/* now 'buf' contains "SEED + offset - 1" */
for (k = 0; k <= n; k++) {
/*
* obtain "SEED + offset + k" by incrementing:
*/
for (i = qsize - 1; i >= 0; i--) {
buf[i]++;
if (buf[i] != 0)
break;
}
if (!EVP_Digest(buf, qsize, md, NULL, evpmd, NULL))
goto err;
/* step 8 */
if (!BN_bin2bn(md, qsize, r0))
goto err;
if (!BN_lshift(r0, r0, (qsize << 3) * k))
goto err;
if (!BN_add(W, W, r0))
goto err;
}
/* more of step 8 */
if (!BN_mask_bits(W, bits - 1))
goto err;
if (!BN_copy(X, W))
goto err;
if (!BN_add(X, X, test))
goto err;
/* step 9 */
if (!BN_lshift1(r0, q))
goto err;
if (!BN_mod(c, X, r0, ctx))
goto err;
if (!BN_sub(r0, c, BN_value_one()))
goto err;
if (!BN_sub(p, X, r0))
goto err;
/* step 10 */
if (BN_cmp(p, test) >= 0) {
/* step 11 */
r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
if (r > 0)
goto end; /* found it */
if (r != 0)
goto err;
}
/* step 13 */
counter++;
/* "offset = offset + n + 1" */
/* step 14 */
if (counter >= 4096)
break;
}
}
end:
if (!BN_GENCB_call(cb, 2, 1))
goto err;
/* We now need to generate g */
/* Set r0=(p-1)/q */
if (!BN_sub(test, p, BN_value_one()))
goto err;
if (!BN_div(r0, NULL, test, q, ctx))
goto err;
if (!BN_set_word(test, h))
goto err;
if (!BN_MONT_CTX_set(mont, p, ctx))
goto err;
for (;;) {
/* g=test^r0%p */
if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
goto err;
if (!BN_is_one(g))
break;
if (!BN_add(test, test, BN_value_one()))
goto err;
h++;
}
if (!BN_GENCB_call(cb, 3, 1))
goto err;
ok = 1;
err:
if (ok) {
BN_free(ret->p);
BN_free(ret->q);
BN_free(ret->g);
ret->p = BN_dup(p);
ret->q = BN_dup(q);
ret->g = BN_dup(g);
if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
ok = 0;
goto err;
}
if (counter_ret != NULL)
*counter_ret = counter;
if (h_ret != NULL)
*h_ret = h;
if (seed_out)
memcpy(seed_out, seed, qsize);
}
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
return ok;
}
/*
* This is a parameter generation algorithm for the DSA2 algorithm as
* described in FIPS 186-3.
*/
int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
const EVP_MD *evpmd, const unsigned char *seed_in,
size_t seed_len, int idx, unsigned char *seed_out,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb)
{
int ok = -1;
unsigned char *seed = NULL, *seed_tmp = NULL;
unsigned char md[EVP_MAX_MD_SIZE];
int mdsize;
BIGNUM *r0, *W, *X, *c, *test;
BIGNUM *g = NULL, *q = NULL, *p = NULL;
BN_MONT_CTX *mont = NULL;
int i, k, n = 0, m = 0, qsize = N >> 3;
int counter = 0;
int r = 0;
BN_CTX *ctx = NULL;
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
unsigned int h = 2;
if (mctx == NULL)
goto err;
/* make sure L > N, otherwise we'll get trapped in an infinite loop */
if (L <= N) {
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS);
goto err;
}
if (evpmd == NULL) {
if (N == 160)
evpmd = EVP_sha1();
else if (N == 224)
evpmd = EVP_sha224();
else
evpmd = EVP_sha256();
}
mdsize = EVP_MD_size(evpmd);
/* If unverifiable g generation only don't need seed */
if (!ret->p || !ret->q || idx >= 0) {
if (seed_len == 0)
seed_len = mdsize;
seed = OPENSSL_malloc(seed_len);
if (seed_out)
seed_tmp = seed_out;
else
seed_tmp = OPENSSL_malloc(seed_len);
if (seed == NULL || seed_tmp == NULL)
goto err;
if (seed_in)
memcpy(seed, seed_in, seed_len);
}
if ((ctx = BN_CTX_new()) == NULL)
goto err;
if ((mont = BN_MONT_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
r0 = BN_CTX_get(ctx);
g = BN_CTX_get(ctx);
W = BN_CTX_get(ctx);
X = BN_CTX_get(ctx);
c = BN_CTX_get(ctx);
test = BN_CTX_get(ctx);
if (test == NULL)
goto err;
/* if p, q already supplied generate g only */
if (ret->p && ret->q) {
p = ret->p;
q = ret->q;
if (idx >= 0)
memcpy(seed_tmp, seed, seed_len);
goto g_only;
} else {
p = BN_CTX_get(ctx);
q = BN_CTX_get(ctx);
if (q == NULL)
goto err;
}
if (!BN_lshift(test, BN_value_one(), L - 1))
goto err;
for (;;) {
for (;;) { /* find q */
unsigned char *pmd;
/* step 1 */
if (!BN_GENCB_call(cb, 0, m++))
goto err;
if (!seed_in) {
if (RAND_bytes(seed, seed_len) <= 0)
goto err;
}
/* step 2 */
if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL))
goto err;
/* Take least significant bits of md */
if (mdsize > qsize)
pmd = md + mdsize - qsize;
else
pmd = md;
if (mdsize < qsize)
memset(md + mdsize, 0, qsize - mdsize);
/* step 3 */
pmd[0] |= 0x80;
pmd[qsize - 1] |= 0x01;
if (!BN_bin2bn(pmd, qsize, q))
goto err;
/* step 4 */
r = BN_is_prime_fasttest_ex(q, DSS_prime_checks, ctx,
seed_in ? 1 : 0, cb);
if (r > 0)
break;
if (r != 0)
goto err;
/* Provided seed didn't produce a prime: error */
if (seed_in) {
ok = 0;
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_Q_NOT_PRIME);
goto err;
}
/* do a callback call */
/* step 5 */
}
/* Copy seed to seed_out before we mess with it */
if (seed_out)
memcpy(seed_out, seed, seed_len);
if (!BN_GENCB_call(cb, 2, 0))
goto err;
if (!BN_GENCB_call(cb, 3, 0))
goto err;
/* step 6 */
counter = 0;
/* "offset = 1" */
n = (L - 1) / (mdsize << 3);
for (;;) {
if ((counter != 0) && !BN_GENCB_call(cb, 0, counter))
goto err;
/* step 7 */
BN_zero(W);
/* now 'buf' contains "SEED + offset - 1" */
for (k = 0; k <= n; k++) {
/*
* obtain "SEED + offset + k" by incrementing:
*/
for (i = seed_len - 1; i >= 0; i--) {
seed[i]++;
if (seed[i] != 0)
break;
}
if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL))
goto err;
/* step 8 */
if (!BN_bin2bn(md, mdsize, r0))
goto err;
if (!BN_lshift(r0, r0, (mdsize << 3) * k))
goto err;
if (!BN_add(W, W, r0))
goto err;
}
/* more of step 8 */
if (!BN_mask_bits(W, L - 1))
goto err;
if (!BN_copy(X, W))
goto err;
if (!BN_add(X, X, test))
goto err;
/* step 9 */
if (!BN_lshift1(r0, q))
goto err;
if (!BN_mod(c, X, r0, ctx))
goto err;
if (!BN_sub(r0, c, BN_value_one()))
goto err;
if (!BN_sub(p, X, r0))
goto err;
/* step 10 */
if (BN_cmp(p, test) >= 0) {
/* step 11 */
r = BN_is_prime_fasttest_ex(p, DSS_prime_checks, ctx, 1, cb);
if (r > 0)
goto end; /* found it */
if (r != 0)
goto err;
}
/* step 13 */
counter++;
/* "offset = offset + n + 1" */
/* step 14 */
if (counter >= (int)(4 * L))
break;
}
if (seed_in) {
ok = 0;
DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS);
goto err;
}
}
end:
if (!BN_GENCB_call(cb, 2, 1))
goto err;
g_only:
/* We now need to generate g */
/* Set r0=(p-1)/q */
if (!BN_sub(test, p, BN_value_one()))
goto err;
if (!BN_div(r0, NULL, test, q, ctx))
goto err;
if (idx < 0) {
if (!BN_set_word(test, h))
goto err;
} else
h = 1;
if (!BN_MONT_CTX_set(mont, p, ctx))
goto err;
for (;;) {
static const unsigned char ggen[4] = { 0x67, 0x67, 0x65, 0x6e };
if (idx >= 0) {
md[0] = idx & 0xff;
md[1] = (h >> 8) & 0xff;
md[2] = h & 0xff;
if (!EVP_DigestInit_ex(mctx, evpmd, NULL))
goto err;
if (!EVP_DigestUpdate(mctx, seed_tmp, seed_len))
goto err;
if (!EVP_DigestUpdate(mctx, ggen, sizeof(ggen)))
goto err;
if (!EVP_DigestUpdate(mctx, md, 3))
goto err;
if (!EVP_DigestFinal_ex(mctx, md, NULL))
goto err;
if (!BN_bin2bn(md, mdsize, test))
goto err;
}
/* g=test^r0%p */
if (!BN_mod_exp_mont(g, test, r0, p, ctx, mont))
goto err;
if (!BN_is_one(g))
break;
if (idx < 0 && !BN_add(test, test, BN_value_one()))
goto err;
h++;
if (idx >= 0 && h > 0xffff)
goto err;
}
if (!BN_GENCB_call(cb, 3, 1))
goto err;
ok = 1;
err:
if (ok == 1) {
if (p != ret->p) {
BN_free(ret->p);
ret->p = BN_dup(p);
}
if (q != ret->q) {
BN_free(ret->q);
ret->q = BN_dup(q);
}
BN_free(ret->g);
ret->g = BN_dup(g);
if (ret->p == NULL || ret->q == NULL || ret->g == NULL) {
ok = -1;
goto err;
}
if (counter_ret != NULL)
*counter_ret = counter;
if (h_ret != NULL)
*h_ret = h;
}
OPENSSL_free(seed);
if (seed_out != seed_tmp)
OPENSSL_free(seed_tmp);
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
EVP_MD_CTX_free(mctx);
return ok;
}
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index 7a0b0874c54e..cefda5a450fa 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -1,428 +1,434 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/bn_int.h"
#include <openssl/bn.h>
#include <openssl/sha.h>
#include "dsa_locl.h"
#include <openssl/asn1.h>
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa);
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp);
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
BIGNUM **rp, const unsigned char *dgst, int dlen);
static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa);
static int dsa_init(DSA *dsa);
static int dsa_finish(DSA *dsa);
static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q,
BN_CTX *ctx);
static DSA_METHOD openssl_dsa_meth = {
"OpenSSL DSA method",
dsa_do_sign,
dsa_sign_setup_no_digest,
dsa_do_verify,
NULL, /* dsa_mod_exp, */
NULL, /* dsa_bn_mod_exp, */
dsa_init,
dsa_finish,
DSA_FLAG_FIPS_METHOD,
NULL,
NULL,
NULL
};
static const DSA_METHOD *default_DSA_method = &openssl_dsa_meth;
void DSA_set_default_method(const DSA_METHOD *meth)
{
default_DSA_method = meth;
}
const DSA_METHOD *DSA_get_default_method(void)
{
return default_DSA_method;
}
const DSA_METHOD *DSA_OpenSSL(void)
{
return &openssl_dsa_meth;
}
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
BIGNUM *kinv = NULL;
BIGNUM *m, *blind, *blindm, *tmp;
BN_CTX *ctx = NULL;
int reason = ERR_R_BN_LIB;
DSA_SIG *ret = NULL;
int rv = 0;
if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
reason = DSA_R_MISSING_PARAMETERS;
goto err;
}
ret = DSA_SIG_new();
if (ret == NULL)
goto err;
ret->r = BN_new();
ret->s = BN_new();
if (ret->r == NULL || ret->s == NULL)
goto err;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
m = BN_CTX_get(ctx);
blind = BN_CTX_get(ctx);
blindm = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
if (tmp == NULL)
goto err;
redo:
if (!dsa_sign_setup(dsa, ctx, &kinv, &ret->r, dgst, dlen))
goto err;
if (dlen > BN_num_bytes(dsa->q))
/*
* if the digest length is greater than the size of q use the
* BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3,
* 4.2
*/
dlen = BN_num_bytes(dsa->q);
if (BN_bin2bn(dgst, dlen, m) == NULL)
goto err;
/*
* The normal signature calculation is:
*
* s := k^-1 * (m + r * priv_key) mod q
*
* We will blind this to protect against side channel attacks
*
* s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod q
*/
/* Generate a blinding value */
do {
if (!BN_priv_rand(blind, BN_num_bits(dsa->q) - 1,
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY))
goto err;
} while (BN_is_zero(blind));
BN_set_flags(blind, BN_FLG_CONSTTIME);
BN_set_flags(blindm, BN_FLG_CONSTTIME);
BN_set_flags(tmp, BN_FLG_CONSTTIME);
/* tmp := blind * priv_key * r mod q */
if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->q, ctx))
goto err;
if (!BN_mod_mul(tmp, tmp, ret->r, dsa->q, ctx))
goto err;
/* blindm := blind * m mod q */
if (!BN_mod_mul(blindm, blind, m, dsa->q, ctx))
goto err;
/* s : = (blind * priv_key * r) + (blind * m) mod q */
if (!BN_mod_add_quick(ret->s, tmp, blindm, dsa->q))
goto err;
/* s := s * k^-1 mod q */
if (!BN_mod_mul(ret->s, ret->s, kinv, dsa->q, ctx))
goto err;
/* s:= s * blind^-1 mod q */
if (BN_mod_inverse(blind, blind, dsa->q, ctx) == NULL)
goto err;
if (!BN_mod_mul(ret->s, ret->s, blind, dsa->q, ctx))
goto err;
/*
* Redo if r or s is zero as required by FIPS 186-3: this is very
* unlikely.
*/
if (BN_is_zero(ret->r) || BN_is_zero(ret->s))
goto redo;
rv = 1;
err:
if (rv == 0) {
DSAerr(DSA_F_DSA_DO_SIGN, reason);
DSA_SIG_free(ret);
ret = NULL;
}
BN_CTX_free(ctx);
BN_clear_free(kinv);
return ret;
}
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp)
{
return dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0);
}
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in,
BIGNUM **kinvp, BIGNUM **rp,
const unsigned char *dgst, int dlen)
{
BN_CTX *ctx = NULL;
BIGNUM *k, *kinv = NULL, *r = *rp;
BIGNUM *l;
int ret = 0;
int q_bits, q_words;
if (!dsa->p || !dsa->q || !dsa->g) {
DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_MISSING_PARAMETERS);
return 0;
}
+ /* Reject obviously invalid parameters */
+ if (BN_is_zero(dsa->p) || BN_is_zero(dsa->q) || BN_is_zero(dsa->g)) {
+ DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_PARAMETERS);
+ return 0;
+ }
+
k = BN_new();
l = BN_new();
if (k == NULL || l == NULL)
goto err;
if (ctx_in == NULL) {
if ((ctx = BN_CTX_new()) == NULL)
goto err;
} else
ctx = ctx_in;
/* Preallocate space */
q_bits = BN_num_bits(dsa->q);
q_words = bn_get_top(dsa->q);
if (!bn_wexpand(k, q_words + 2)
|| !bn_wexpand(l, q_words + 2))
goto err;
/* Get random k */
do {
if (dgst != NULL) {
/*
* We calculate k from SHA512(private_key + H(message) + random).
* This protects the private key from a weak PRNG.
*/
if (!BN_generate_dsa_nonce(k, dsa->q, dsa->priv_key, dgst,
dlen, ctx))
goto err;
} else if (!BN_priv_rand_range(k, dsa->q))
goto err;
} while (BN_is_zero(k));
BN_set_flags(k, BN_FLG_CONSTTIME);
BN_set_flags(l, BN_FLG_CONSTTIME);
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
dsa->lock, dsa->p, ctx))
goto err;
}
/* Compute r = (g^k mod p) mod q */
/*
* We do not want timing information to leak the length of k, so we
* compute G^k using an equivalent scalar of fixed bit-length.
*
* We unconditionally perform both of these additions to prevent a
* small timing information leakage. We then choose the sum that is
* one bit longer than the modulus.
*
* There are some concerns about the efficacy of doing this. More
* specificly refer to the discussion starting with:
* https://github.com/openssl/openssl/pull/7486#discussion_r228323705
* The fix is to rework BN so these gymnastics aren't required.
*/
if (!BN_add(l, k, dsa->q)
|| !BN_add(k, l, dsa->q))
goto err;
BN_consttime_swap(BN_is_bit_set(l, q_bits), k, l, q_words + 2);
if ((dsa)->meth->bn_mod_exp != NULL) {
if (!dsa->meth->bn_mod_exp(dsa, r, dsa->g, k, dsa->p, ctx,
dsa->method_mont_p))
goto err;
} else {
if (!BN_mod_exp_mont(r, dsa->g, k, dsa->p, ctx, dsa->method_mont_p))
goto err;
}
if (!BN_mod(r, r, dsa->q, ctx))
goto err;
/* Compute part of 's = inv(k) (m + xr) mod q' */
if ((kinv = dsa_mod_inverse_fermat(k, dsa->q, ctx)) == NULL)
goto err;
BN_clear_free(*kinvp);
*kinvp = kinv;
kinv = NULL;
ret = 1;
err:
if (!ret)
DSAerr(DSA_F_DSA_SIGN_SETUP, ERR_R_BN_LIB);
if (ctx != ctx_in)
BN_CTX_free(ctx);
BN_clear_free(k);
BN_clear_free(l);
return ret;
}
static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa)
{
BN_CTX *ctx;
BIGNUM *u1, *u2, *t1;
BN_MONT_CTX *mont = NULL;
const BIGNUM *r, *s;
int ret = -1, i;
if (!dsa->p || !dsa->q || !dsa->g) {
DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MISSING_PARAMETERS);
return -1;
}
i = BN_num_bits(dsa->q);
/* fips 186-3 allows only different sizes for q */
if (i != 160 && i != 224 && i != 256) {
DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_BAD_Q_VALUE);
return -1;
}
if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) {
DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_MODULUS_TOO_LARGE);
return -1;
}
u1 = BN_new();
u2 = BN_new();
t1 = BN_new();
ctx = BN_CTX_new();
if (u1 == NULL || u2 == NULL || t1 == NULL || ctx == NULL)
goto err;
DSA_SIG_get0(sig, &r, &s);
if (BN_is_zero(r) || BN_is_negative(r) ||
BN_ucmp(r, dsa->q) >= 0) {
ret = 0;
goto err;
}
if (BN_is_zero(s) || BN_is_negative(s) ||
BN_ucmp(s, dsa->q) >= 0) {
ret = 0;
goto err;
}
/*
* Calculate W = inv(S) mod Q save W in u2
*/
if ((BN_mod_inverse(u2, s, dsa->q, ctx)) == NULL)
goto err;
/* save M in u1 */
if (dgst_len > (i >> 3))
/*
* if the digest length is greater than the size of q use the
* BN_num_bits(dsa->q) leftmost bits of the digest, see fips 186-3,
* 4.2
*/
dgst_len = (i >> 3);
if (BN_bin2bn(dgst, dgst_len, u1) == NULL)
goto err;
/* u1 = M * w mod q */
if (!BN_mod_mul(u1, u1, u2, dsa->q, ctx))
goto err;
/* u2 = r * w mod q */
if (!BN_mod_mul(u2, r, u2, dsa->q, ctx))
goto err;
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
mont = BN_MONT_CTX_set_locked(&dsa->method_mont_p,
dsa->lock, dsa->p, ctx);
if (!mont)
goto err;
}
if (dsa->meth->dsa_mod_exp != NULL) {
if (!dsa->meth->dsa_mod_exp(dsa, t1, dsa->g, u1, dsa->pub_key, u2,
dsa->p, ctx, mont))
goto err;
} else {
if (!BN_mod_exp2_mont(t1, dsa->g, u1, dsa->pub_key, u2, dsa->p, ctx,
mont))
goto err;
}
/* let u1 = u1 mod q */
if (!BN_mod(u1, t1, dsa->q, ctx))
goto err;
/*
* V is now in u1. If the signature is correct, it will be equal to R.
*/
ret = (BN_ucmp(u1, r) == 0);
err:
if (ret < 0)
DSAerr(DSA_F_DSA_DO_VERIFY, ERR_R_BN_LIB);
BN_CTX_free(ctx);
BN_free(u1);
BN_free(u2);
BN_free(t1);
return ret;
}
static int dsa_init(DSA *dsa)
{
dsa->flags |= DSA_FLAG_CACHE_MONT_P;
return 1;
}
static int dsa_finish(DSA *dsa)
{
BN_MONT_CTX_free(dsa->method_mont_p);
return 1;
}
/*
* Compute the inverse of k modulo q.
* Since q is prime, Fermat's Little Theorem applies, which reduces this to
* mod-exp operation. Both the exponent and modulus are public information
* so a mod-exp that doesn't leak the base is sufficient. A newly allocated
* BIGNUM is returned which the caller must free.
*/
static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q,
BN_CTX *ctx)
{
BIGNUM *res = NULL;
BIGNUM *r, *e;
if ((r = BN_new()) == NULL)
return NULL;
BN_CTX_start(ctx);
if ((e = BN_CTX_get(ctx)) != NULL
&& BN_set_word(r, 2)
&& BN_sub(e, q, r)
&& BN_mod_exp_mont(r, k, e, q, ctx, NULL))
res = r;
else
BN_free(r);
BN_CTX_end(ctx);
return res;
}
diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c
index b4ee5a75715e..1dd2fef9beb9 100644
--- a/crypto/dsa/dsa_pmeth.c
+++ b/crypto/dsa/dsa_pmeth.c
@@ -1,273 +1,277 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/evp.h>
#include <openssl/bn.h>
#include "internal/evp_int.h"
#include "dsa_locl.h"
/* DSA pkey context structure */
typedef struct {
/* Parameter gen parameters */
- int nbits; /* size of p in bits (default: 1024) */
- int qbits; /* size of q in bits (default: 160) */
+ int nbits; /* size of p in bits (default: 2048) */
+ int qbits; /* size of q in bits (default: 224) */
const EVP_MD *pmd; /* MD for parameter generation */
/* Keygen callback info */
int gentmp[2];
/* message digest */
const EVP_MD *md; /* MD for the signature */
} DSA_PKEY_CTX;
static int pkey_dsa_init(EVP_PKEY_CTX *ctx)
{
DSA_PKEY_CTX *dctx = OPENSSL_malloc(sizeof(*dctx));
if (dctx == NULL)
return 0;
- dctx->nbits = 1024;
- dctx->qbits = 160;
+ dctx->nbits = 2048;
+ dctx->qbits = 224;
dctx->pmd = NULL;
dctx->md = NULL;
ctx->data = dctx;
ctx->keygen_info = dctx->gentmp;
ctx->keygen_info_count = 2;
return 1;
}
static int pkey_dsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
DSA_PKEY_CTX *dctx, *sctx;
if (!pkey_dsa_init(dst))
return 0;
sctx = src->data;
dctx = dst->data;
dctx->nbits = sctx->nbits;
dctx->qbits = sctx->qbits;
dctx->pmd = sctx->pmd;
dctx->md = sctx->md;
return 1;
}
static void pkey_dsa_cleanup(EVP_PKEY_CTX *ctx)
{
DSA_PKEY_CTX *dctx = ctx->data;
OPENSSL_free(dctx);
}
static int pkey_dsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen)
{
int ret;
unsigned int sltmp;
DSA_PKEY_CTX *dctx = ctx->data;
DSA *dsa = ctx->pkey->pkey.dsa;
if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md))
return 0;
ret = DSA_sign(0, tbs, tbslen, sig, &sltmp, dsa);
if (ret <= 0)
return ret;
*siglen = sltmp;
return 1;
}
static int pkey_dsa_verify(EVP_PKEY_CTX *ctx,
const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen)
{
int ret;
DSA_PKEY_CTX *dctx = ctx->data;
DSA *dsa = ctx->pkey->pkey.dsa;
if (dctx->md != NULL && tbslen != (size_t)EVP_MD_size(dctx->md))
return 0;
ret = DSA_verify(0, tbs, tbslen, sig, siglen, dsa);
return ret;
}
static int pkey_dsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
DSA_PKEY_CTX *dctx = ctx->data;
switch (type) {
case EVP_PKEY_CTRL_DSA_PARAMGEN_BITS:
if (p1 < 256)
return -2;
dctx->nbits = p1;
return 1;
case EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS:
if (p1 != 160 && p1 != 224 && p1 && p1 != 256)
return -2;
dctx->qbits = p1;
return 1;
case EVP_PKEY_CTRL_DSA_PARAMGEN_MD:
if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha256) {
DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
return 0;
}
dctx->pmd = p2;
return 1;
case EVP_PKEY_CTRL_MD:
if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
EVP_MD_type((const EVP_MD *)p2) != NID_dsa &&
EVP_MD_type((const EVP_MD *)p2) != NID_dsaWithSHA &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
DSAerr(DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE);
return 0;
}
dctx->md = p2;
return 1;
case EVP_PKEY_CTRL_GET_MD:
*(const EVP_MD **)p2 = dctx->md;
return 1;
case EVP_PKEY_CTRL_DIGESTINIT:
case EVP_PKEY_CTRL_PKCS7_SIGN:
case EVP_PKEY_CTRL_CMS_SIGN:
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
DSAerr(DSA_F_PKEY_DSA_CTRL,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
default:
return -2;
}
}
static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if (strcmp(type, "dsa_paramgen_bits") == 0) {
int nbits;
nbits = atoi(value);
return EVP_PKEY_CTX_set_dsa_paramgen_bits(ctx, nbits);
}
if (strcmp(type, "dsa_paramgen_q_bits") == 0) {
int qbits = atoi(value);
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits,
NULL);
}
if (strcmp(type, "dsa_paramgen_md") == 0) {
const EVP_MD *md = EVP_get_digestbyname(value);
if (md == NULL) {
DSAerr(DSA_F_PKEY_DSA_CTRL_STR, DSA_R_INVALID_DIGEST_TYPE);
return 0;
}
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0,
(void *)md);
}
return -2;
}
static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
DSA *dsa = NULL;
DSA_PKEY_CTX *dctx = ctx->data;
BN_GENCB *pcb;
int ret;
if (ctx->pkey_gencb) {
pcb = BN_GENCB_new();
if (pcb == NULL)
return 0;
evp_pkey_set_cb_translate(pcb, ctx);
} else
pcb = NULL;
dsa = DSA_new();
if (dsa == NULL) {
BN_GENCB_free(pcb);
return 0;
}
ret = dsa_builtin_paramgen(dsa, dctx->nbits, dctx->qbits, dctx->pmd,
NULL, 0, NULL, NULL, NULL, pcb);
BN_GENCB_free(pcb);
if (ret)
EVP_PKEY_assign_DSA(pkey, dsa);
else
DSA_free(dsa);
return ret;
}
static int pkey_dsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
DSA *dsa = NULL;
if (ctx->pkey == NULL) {
DSAerr(DSA_F_PKEY_DSA_KEYGEN, DSA_R_NO_PARAMETERS_SET);
return 0;
}
dsa = DSA_new();
if (dsa == NULL)
return 0;
EVP_PKEY_assign_DSA(pkey, dsa);
/* Note: if error return, pkey is freed by parent routine */
if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
return 0;
return DSA_generate_key(pkey->pkey.dsa);
}
const EVP_PKEY_METHOD dsa_pkey_meth = {
EVP_PKEY_DSA,
EVP_PKEY_FLAG_AUTOARGLEN,
pkey_dsa_init,
pkey_dsa_copy,
pkey_dsa_cleanup,
0,
pkey_dsa_paramgen,
0,
pkey_dsa_keygen,
0,
pkey_dsa_sign,
0,
pkey_dsa_verify,
0, 0,
0, 0, 0, 0,
0, 0,
0, 0,
0, 0,
pkey_dsa_ctrl,
pkey_dsa_ctrl_str
};
diff --git a/crypto/dso/dso_openssl.c b/crypto/dso/dso_openssl.c
index 6626331e9256..f0dd38ace259 100644
--- a/crypto/dso/dso_openssl.c
+++ b/crypto/dso/dso_openssl.c
@@ -1,22 +1,22 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "dso_locl.h"
-#if !defined(DSO_VMS) && !defined(DSO_DLCFN) && !defined(DSO_DL) && !defined(DSO_WIN32) && !defined(DSO_DLFCN)
+#ifdef DSO_NONE
static DSO_METHOD dso_meth_null = {
"NULL shared library method"
};
DSO_METHOD *DSO_METHOD_openssl(void)
{
return &dso_meth_null;
}
#endif
diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c
index aa999cc5914e..c5d887ec4cd4 100644
--- a/crypto/ec/curve25519.c
+++ b/crypto/ec/curve25519.c
@@ -1,5596 +1,5597 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include "ec_lcl.h"
#include <openssl/sha.h>
#if defined(X25519_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64))
# define BASE_2_64_IMPLEMENTED
typedef uint64_t fe64[4];
int x25519_fe64_eligible(void);
/*
* Following subroutines perform corresponding operations modulo
* 2^256-38, i.e. double the curve modulus. However, inputs and
* outputs are permitted to be partially reduced, i.e. to remain
* in [0..2^256) range. It's all tied up in final fe64_tobytes
* that performs full reduction modulo 2^255-19.
*
* There are no reference C implementations for these.
*/
void x25519_fe64_mul(fe64 h, const fe64 f, const fe64 g);
void x25519_fe64_sqr(fe64 h, const fe64 f);
void x25519_fe64_mul121666(fe64 h, fe64 f);
void x25519_fe64_add(fe64 h, const fe64 f, const fe64 g);
void x25519_fe64_sub(fe64 h, const fe64 f, const fe64 g);
void x25519_fe64_tobytes(uint8_t *s, const fe64 f);
# define fe64_mul x25519_fe64_mul
# define fe64_sqr x25519_fe64_sqr
# define fe64_mul121666 x25519_fe64_mul121666
# define fe64_add x25519_fe64_add
# define fe64_sub x25519_fe64_sub
# define fe64_tobytes x25519_fe64_tobytes
static uint64_t load_8(const uint8_t *in)
{
uint64_t result;
result = in[0];
result |= ((uint64_t)in[1]) << 8;
result |= ((uint64_t)in[2]) << 16;
result |= ((uint64_t)in[3]) << 24;
result |= ((uint64_t)in[4]) << 32;
result |= ((uint64_t)in[5]) << 40;
result |= ((uint64_t)in[6]) << 48;
result |= ((uint64_t)in[7]) << 56;
return result;
}
static void fe64_frombytes(fe64 h, const uint8_t *s)
{
h[0] = load_8(s);
h[1] = load_8(s + 8);
h[2] = load_8(s + 16);
h[3] = load_8(s + 24) & 0x7fffffffffffffff;
}
static void fe64_0(fe64 h)
{
h[0] = 0;
h[1] = 0;
h[2] = 0;
h[3] = 0;
}
static void fe64_1(fe64 h)
{
h[0] = 1;
h[1] = 0;
h[2] = 0;
h[3] = 0;
}
static void fe64_copy(fe64 h, const fe64 f)
{
h[0] = f[0];
h[1] = f[1];
h[2] = f[2];
h[3] = f[3];
}
static void fe64_cswap(fe64 f, fe64 g, unsigned int b)
{
int i;
uint64_t mask = 0 - (uint64_t)b;
for (i = 0; i < 4; i++) {
uint64_t x = f[i] ^ g[i];
x &= mask;
f[i] ^= x;
g[i] ^= x;
}
}
static void fe64_invert(fe64 out, const fe64 z)
{
fe64 t0;
fe64 t1;
fe64 t2;
fe64 t3;
int i;
/*
* Compute z ** -1 = z ** (2 ** 255 - 19 - 2) with the exponent as
* 2 ** 255 - 21 = (2 ** 5) * (2 ** 250 - 1) + 11.
*/
/* t0 = z ** 2 */
fe64_sqr(t0, z);
/* t1 = t0 ** (2 ** 2) = z ** 8 */
fe64_sqr(t1, t0);
fe64_sqr(t1, t1);
/* t1 = z * t1 = z ** 9 */
fe64_mul(t1, z, t1);
/* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */
fe64_mul(t0, t0, t1);
/* t2 = t0 ** 2 = z ** 22 */
fe64_sqr(t2, t0);
/* t1 = t1 * t2 = z ** (2 ** 5 - 1) */
fe64_mul(t1, t1, t2);
/* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */
fe64_sqr(t2, t1);
for (i = 1; i < 5; ++i)
fe64_sqr(t2, t2);
/* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */
fe64_mul(t1, t2, t1);
/* Continuing similarly... */
/* t2 = z ** (2 ** 20 - 1) */
fe64_sqr(t2, t1);
for (i = 1; i < 10; ++i)
fe64_sqr(t2, t2);
fe64_mul(t2, t2, t1);
/* t2 = z ** (2 ** 40 - 1) */
fe64_sqr(t3, t2);
for (i = 1; i < 20; ++i)
fe64_sqr(t3, t3);
fe64_mul(t2, t3, t2);
/* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */
for (i = 0; i < 10; ++i)
fe64_sqr(t2, t2);
/* t1 = z ** (2 ** 50 - 1) */
fe64_mul(t1, t2, t1);
/* t2 = z ** (2 ** 100 - 1) */
fe64_sqr(t2, t1);
for (i = 1; i < 50; ++i)
fe64_sqr(t2, t2);
fe64_mul(t2, t2, t1);
/* t2 = z ** (2 ** 200 - 1) */
fe64_sqr(t3, t2);
for (i = 1; i < 100; ++i)
fe64_sqr(t3, t3);
fe64_mul(t2, t3, t2);
/* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */
for (i = 0; i < 50; ++i)
fe64_sqr(t2, t2);
/* t1 = z ** (2 ** 250 - 1) */
fe64_mul(t1, t2, t1);
/* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */
for (i = 0; i < 5; ++i)
fe64_sqr(t1, t1);
/* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */
fe64_mul(out, t1, t0);
}
/*
* Duplicate of original x25519_scalar_mult_generic, but using
* fe64_* subroutines.
*/
static void x25519_scalar_mulx(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32])
{
fe64 x1, x2, z2, x3, z3, tmp0, tmp1;
uint8_t e[32];
unsigned swap = 0;
int pos;
memcpy(e, scalar, 32);
e[0] &= 0xf8;
e[31] &= 0x7f;
e[31] |= 0x40;
fe64_frombytes(x1, point);
fe64_1(x2);
fe64_0(z2);
fe64_copy(x3, x1);
fe64_1(z3);
for (pos = 254; pos >= 0; --pos) {
unsigned int b = 1 & (e[pos / 8] >> (pos & 7));
swap ^= b;
fe64_cswap(x2, x3, swap);
fe64_cswap(z2, z3, swap);
swap = b;
fe64_sub(tmp0, x3, z3);
fe64_sub(tmp1, x2, z2);
fe64_add(x2, x2, z2);
fe64_add(z2, x3, z3);
fe64_mul(z3, x2, tmp0);
fe64_mul(z2, z2, tmp1);
fe64_sqr(tmp0, tmp1);
fe64_sqr(tmp1, x2);
fe64_add(x3, z3, z2);
fe64_sub(z2, z3, z2);
fe64_mul(x2, tmp1, tmp0);
fe64_sub(tmp1, tmp1, tmp0);
fe64_sqr(z2, z2);
fe64_mul121666(z3, tmp1);
fe64_sqr(x3, x3);
fe64_add(tmp0, tmp0, z3);
fe64_mul(z3, x1, z2);
fe64_mul(z2, tmp1, tmp0);
}
fe64_invert(z2, z2);
fe64_mul(x2, x2, z2);
fe64_tobytes(out, x2);
OPENSSL_cleanse(e, sizeof(e));
}
#endif
#if defined(X25519_ASM) \
|| ( (defined(__SIZEOF_INT128__) && __SIZEOF_INT128__ == 16) \
&& !defined(__sparc__) \
+ && (!defined(__SIZEOF_LONG__) || (__SIZEOF_LONG__ == 8)) \
&& !(defined(__ANDROID__) && !defined(__clang__)) )
/*
* Base 2^51 implementation. It's virtually no different from reference
* base 2^25.5 implementation in respect to lax boundary conditions for
* intermediate values and even individual limbs. So that whatever you
* know about the reference, applies even here...
*/
# define BASE_2_51_IMPLEMENTED
typedef uint64_t fe51[5];
static const uint64_t MASK51 = 0x7ffffffffffff;
static uint64_t load_7(const uint8_t *in)
{
uint64_t result;
result = in[0];
result |= ((uint64_t)in[1]) << 8;
result |= ((uint64_t)in[2]) << 16;
result |= ((uint64_t)in[3]) << 24;
result |= ((uint64_t)in[4]) << 32;
result |= ((uint64_t)in[5]) << 40;
result |= ((uint64_t)in[6]) << 48;
return result;
}
static uint64_t load_6(const uint8_t *in)
{
uint64_t result;
result = in[0];
result |= ((uint64_t)in[1]) << 8;
result |= ((uint64_t)in[2]) << 16;
result |= ((uint64_t)in[3]) << 24;
result |= ((uint64_t)in[4]) << 32;
result |= ((uint64_t)in[5]) << 40;
return result;
}
static void fe51_frombytes(fe51 h, const uint8_t *s)
{
uint64_t h0 = load_7(s); /* 56 bits */
uint64_t h1 = load_6(s + 7) << 5; /* 53 bits */
uint64_t h2 = load_7(s + 13) << 2; /* 58 bits */
uint64_t h3 = load_6(s + 20) << 7; /* 55 bits */
uint64_t h4 = (load_6(s + 26) & 0x7fffffffffff) << 4; /* 51 bits */
h1 |= h0 >> 51; h0 &= MASK51;
h2 |= h1 >> 51; h1 &= MASK51;
h3 |= h2 >> 51; h2 &= MASK51;
h4 |= h3 >> 51; h3 &= MASK51;
h[0] = h0;
h[1] = h1;
h[2] = h2;
h[3] = h3;
h[4] = h4;
}
static void fe51_tobytes(uint8_t *s, const fe51 h)
{
uint64_t h0 = h[0];
uint64_t h1 = h[1];
uint64_t h2 = h[2];
uint64_t h3 = h[3];
uint64_t h4 = h[4];
uint64_t q;
/* compare to modulus */
q = (h0 + 19) >> 51;
q = (h1 + q) >> 51;
q = (h2 + q) >> 51;
q = (h3 + q) >> 51;
q = (h4 + q) >> 51;
/* full reduce */
h0 += 19 * q;
h1 += h0 >> 51; h0 &= MASK51;
h2 += h1 >> 51; h1 &= MASK51;
h3 += h2 >> 51; h2 &= MASK51;
h4 += h3 >> 51; h3 &= MASK51;
h4 &= MASK51;
/* smash */
s[0] = (uint8_t)(h0 >> 0);
s[1] = (uint8_t)(h0 >> 8);
s[2] = (uint8_t)(h0 >> 16);
s[3] = (uint8_t)(h0 >> 24);
s[4] = (uint8_t)(h0 >> 32);
s[5] = (uint8_t)(h0 >> 40);
s[6] = (uint8_t)((h0 >> 48) | ((uint32_t)h1 << 3));
s[7] = (uint8_t)(h1 >> 5);
s[8] = (uint8_t)(h1 >> 13);
s[9] = (uint8_t)(h1 >> 21);
s[10] = (uint8_t)(h1 >> 29);
s[11] = (uint8_t)(h1 >> 37);
s[12] = (uint8_t)((h1 >> 45) | ((uint32_t)h2 << 6));
s[13] = (uint8_t)(h2 >> 2);
s[14] = (uint8_t)(h2 >> 10);
s[15] = (uint8_t)(h2 >> 18);
s[16] = (uint8_t)(h2 >> 26);
s[17] = (uint8_t)(h2 >> 34);
s[18] = (uint8_t)(h2 >> 42);
s[19] = (uint8_t)((h2 >> 50) | ((uint32_t)h3 << 1));
s[20] = (uint8_t)(h3 >> 7);
s[21] = (uint8_t)(h3 >> 15);
s[22] = (uint8_t)(h3 >> 23);
s[23] = (uint8_t)(h3 >> 31);
s[24] = (uint8_t)(h3 >> 39);
s[25] = (uint8_t)((h3 >> 47) | ((uint32_t)h4 << 4));
s[26] = (uint8_t)(h4 >> 4);
s[27] = (uint8_t)(h4 >> 12);
s[28] = (uint8_t)(h4 >> 20);
s[29] = (uint8_t)(h4 >> 28);
s[30] = (uint8_t)(h4 >> 36);
s[31] = (uint8_t)(h4 >> 44);
}
# if defined(X25519_ASM)
void x25519_fe51_mul(fe51 h, const fe51 f, const fe51 g);
void x25519_fe51_sqr(fe51 h, const fe51 f);
void x25519_fe51_mul121666(fe51 h, fe51 f);
# define fe51_mul x25519_fe51_mul
# define fe51_sq x25519_fe51_sqr
# define fe51_mul121666 x25519_fe51_mul121666
# else
typedef __uint128_t u128;
static void fe51_mul(fe51 h, const fe51 f, const fe51 g)
{
u128 h0, h1, h2, h3, h4;
uint64_t f_i, g0, g1, g2, g3, g4;
f_i = f[0];
h0 = (u128)f_i * (g0 = g[0]);
h1 = (u128)f_i * (g1 = g[1]);
h2 = (u128)f_i * (g2 = g[2]);
h3 = (u128)f_i * (g3 = g[3]);
h4 = (u128)f_i * (g4 = g[4]);
f_i = f[1];
h0 += (u128)f_i * (g4 *= 19);
h1 += (u128)f_i * g0;
h2 += (u128)f_i * g1;
h3 += (u128)f_i * g2;
h4 += (u128)f_i * g3;
f_i = f[2];
h0 += (u128)f_i * (g3 *= 19);
h1 += (u128)f_i * g4;
h2 += (u128)f_i * g0;
h3 += (u128)f_i * g1;
h4 += (u128)f_i * g2;
f_i = f[3];
h0 += (u128)f_i * (g2 *= 19);
h1 += (u128)f_i * g3;
h2 += (u128)f_i * g4;
h3 += (u128)f_i * g0;
h4 += (u128)f_i * g1;
f_i = f[4];
h0 += (u128)f_i * (g1 *= 19);
h1 += (u128)f_i * g2;
h2 += (u128)f_i * g3;
h3 += (u128)f_i * g4;
h4 += (u128)f_i * g0;
/* partial [lazy] reduction */
h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51;
h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51;
h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51;
g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51;
g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51;
g3 += g2 >> 51; g2 &= MASK51;
g1 += g0 >> 51; g0 &= MASK51;
h[0] = g0;
h[1] = g1;
h[2] = g2;
h[3] = g3;
h[4] = g4;
}
static void fe51_sq(fe51 h, const fe51 f)
{
# if defined(OPENSSL_SMALL_FOOTPRINT)
fe51_mul(h, f, f);
# else
/* dedicated squaring gives 16-25% overall improvement */
uint64_t g0 = f[0];
uint64_t g1 = f[1];
uint64_t g2 = f[2];
uint64_t g3 = f[3];
uint64_t g4 = f[4];
u128 h0, h1, h2, h3, h4;
h0 = (u128)g0 * g0; g0 *= 2;
h1 = (u128)g0 * g1;
h2 = (u128)g0 * g2;
h3 = (u128)g0 * g3;
h4 = (u128)g0 * g4;
g0 = g4; /* borrow g0 */
h3 += (u128)g0 * (g4 *= 19);
h2 += (u128)g1 * g1; g1 *= 2;
h3 += (u128)g1 * g2;
h4 += (u128)g1 * g3;
h0 += (u128)g1 * g4;
g0 = g3; /* borrow g0 */
h1 += (u128)g0 * (g3 *= 19);
h2 += (u128)(g0 * 2) * g4;
h4 += (u128)g2 * g2; g2 *= 2;
h0 += (u128)g2 * g3;
h1 += (u128)g2 * g4;
/* partial [lazy] reduction */
h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51;
h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51;
h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51;
g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51;
g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51;
g3 += g2 >> 51; g2 &= MASK51;
g1 += g0 >> 51; g0 &= MASK51;
h[0] = g0;
h[1] = g1;
h[2] = g2;
h[3] = g3;
h[4] = g4;
# endif
}
static void fe51_mul121666(fe51 h, fe51 f)
{
u128 h0 = f[0] * (u128)121666;
u128 h1 = f[1] * (u128)121666;
u128 h2 = f[2] * (u128)121666;
u128 h3 = f[3] * (u128)121666;
u128 h4 = f[4] * (u128)121666;
uint64_t g0, g1, g2, g3, g4;
h3 += (uint64_t)(h2 >> 51); g2 = (uint64_t)h2 & MASK51;
h1 += (uint64_t)(h0 >> 51); g0 = (uint64_t)h0 & MASK51;
h4 += (uint64_t)(h3 >> 51); g3 = (uint64_t)h3 & MASK51;
g2 += (uint64_t)(h1 >> 51); g1 = (uint64_t)h1 & MASK51;
g0 += (uint64_t)(h4 >> 51) * 19; g4 = (uint64_t)h4 & MASK51;
g3 += g2 >> 51; g2 &= MASK51;
g1 += g0 >> 51; g0 &= MASK51;
h[0] = g0;
h[1] = g1;
h[2] = g2;
h[3] = g3;
h[4] = g4;
}
# endif
static void fe51_add(fe51 h, const fe51 f, const fe51 g)
{
h[0] = f[0] + g[0];
h[1] = f[1] + g[1];
h[2] = f[2] + g[2];
h[3] = f[3] + g[3];
h[4] = f[4] + g[4];
}
static void fe51_sub(fe51 h, const fe51 f, const fe51 g)
{
/*
* Add 2*modulus to ensure that result remains positive
* even if subtrahend is partially reduced.
*/
h[0] = (f[0] + 0xfffffffffffda) - g[0];
h[1] = (f[1] + 0xffffffffffffe) - g[1];
h[2] = (f[2] + 0xffffffffffffe) - g[2];
h[3] = (f[3] + 0xffffffffffffe) - g[3];
h[4] = (f[4] + 0xffffffffffffe) - g[4];
}
static void fe51_0(fe51 h)
{
h[0] = 0;
h[1] = 0;
h[2] = 0;
h[3] = 0;
h[4] = 0;
}
static void fe51_1(fe51 h)
{
h[0] = 1;
h[1] = 0;
h[2] = 0;
h[3] = 0;
h[4] = 0;
}
static void fe51_copy(fe51 h, const fe51 f)
{
h[0] = f[0];
h[1] = f[1];
h[2] = f[2];
h[3] = f[3];
h[4] = f[4];
}
static void fe51_cswap(fe51 f, fe51 g, unsigned int b)
{
int i;
uint64_t mask = 0 - (uint64_t)b;
for (i = 0; i < 5; i++) {
int64_t x = f[i] ^ g[i];
x &= mask;
f[i] ^= x;
g[i] ^= x;
}
}
static void fe51_invert(fe51 out, const fe51 z)
{
fe51 t0;
fe51 t1;
fe51 t2;
fe51 t3;
int i;
/*
* Compute z ** -1 = z ** (2 ** 255 - 19 - 2) with the exponent as
* 2 ** 255 - 21 = (2 ** 5) * (2 ** 250 - 1) + 11.
*/
/* t0 = z ** 2 */
fe51_sq(t0, z);
/* t1 = t0 ** (2 ** 2) = z ** 8 */
fe51_sq(t1, t0);
fe51_sq(t1, t1);
/* t1 = z * t1 = z ** 9 */
fe51_mul(t1, z, t1);
/* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */
fe51_mul(t0, t0, t1);
/* t2 = t0 ** 2 = z ** 22 */
fe51_sq(t2, t0);
/* t1 = t1 * t2 = z ** (2 ** 5 - 1) */
fe51_mul(t1, t1, t2);
/* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */
fe51_sq(t2, t1);
for (i = 1; i < 5; ++i)
fe51_sq(t2, t2);
/* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */
fe51_mul(t1, t2, t1);
/* Continuing similarly... */
/* t2 = z ** (2 ** 20 - 1) */
fe51_sq(t2, t1);
for (i = 1; i < 10; ++i)
fe51_sq(t2, t2);
fe51_mul(t2, t2, t1);
/* t2 = z ** (2 ** 40 - 1) */
fe51_sq(t3, t2);
for (i = 1; i < 20; ++i)
fe51_sq(t3, t3);
fe51_mul(t2, t3, t2);
/* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */
for (i = 0; i < 10; ++i)
fe51_sq(t2, t2);
/* t1 = z ** (2 ** 50 - 1) */
fe51_mul(t1, t2, t1);
/* t2 = z ** (2 ** 100 - 1) */
fe51_sq(t2, t1);
for (i = 1; i < 50; ++i)
fe51_sq(t2, t2);
fe51_mul(t2, t2, t1);
/* t2 = z ** (2 ** 200 - 1) */
fe51_sq(t3, t2);
for (i = 1; i < 100; ++i)
fe51_sq(t3, t3);
fe51_mul(t2, t3, t2);
/* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */
for (i = 0; i < 50; ++i)
fe51_sq(t2, t2);
/* t1 = z ** (2 ** 250 - 1) */
fe51_mul(t1, t2, t1);
/* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */
for (i = 0; i < 5; ++i)
fe51_sq(t1, t1);
/* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */
fe51_mul(out, t1, t0);
}
/*
* Duplicate of original x25519_scalar_mult_generic, but using
* fe51_* subroutines.
*/
static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32])
{
fe51 x1, x2, z2, x3, z3, tmp0, tmp1;
uint8_t e[32];
unsigned swap = 0;
int pos;
# ifdef BASE_2_64_IMPLEMENTED
if (x25519_fe64_eligible()) {
x25519_scalar_mulx(out, scalar, point);
return;
}
# endif
memcpy(e, scalar, 32);
e[0] &= 0xf8;
e[31] &= 0x7f;
e[31] |= 0x40;
fe51_frombytes(x1, point);
fe51_1(x2);
fe51_0(z2);
fe51_copy(x3, x1);
fe51_1(z3);
for (pos = 254; pos >= 0; --pos) {
unsigned int b = 1 & (e[pos / 8] >> (pos & 7));
swap ^= b;
fe51_cswap(x2, x3, swap);
fe51_cswap(z2, z3, swap);
swap = b;
fe51_sub(tmp0, x3, z3);
fe51_sub(tmp1, x2, z2);
fe51_add(x2, x2, z2);
fe51_add(z2, x3, z3);
fe51_mul(z3, tmp0, x2);
fe51_mul(z2, z2, tmp1);
fe51_sq(tmp0, tmp1);
fe51_sq(tmp1, x2);
fe51_add(x3, z3, z2);
fe51_sub(z2, z3, z2);
fe51_mul(x2, tmp1, tmp0);
fe51_sub(tmp1, tmp1, tmp0);
fe51_sq(z2, z2);
fe51_mul121666(z3, tmp1);
fe51_sq(x3, x3);
fe51_add(tmp0, tmp0, z3);
fe51_mul(z3, x1, z2);
fe51_mul(z2, tmp1, tmp0);
}
fe51_invert(z2, z2);
fe51_mul(x2, x2, z2);
fe51_tobytes(out, x2);
OPENSSL_cleanse(e, sizeof(e));
}
#endif
/*
* Reference base 2^25.5 implementation.
*
* This code is mostly taken from the ref10 version of Ed25519 in SUPERCOP
* 20141124 (http://bench.cr.yp.to/supercop.html).
*
* The field functions are shared by Ed25519 and X25519 where possible.
*/
/*
* fe means field element. Here the field is \Z/(2^255-19). An element t,
* entries t[0]...t[9], represents the integer t[0]+2^26 t[1]+2^51 t[2]+2^77
* t[3]+2^102 t[4]+...+2^230 t[9]. Bounds on each t[i] vary depending on
* context.
*/
typedef int32_t fe[10];
static const int64_t kBottom21Bits = 0x1fffffLL;
static const int64_t kBottom25Bits = 0x1ffffffLL;
static const int64_t kBottom26Bits = 0x3ffffffLL;
static const int64_t kTop39Bits = 0xfffffffffe000000LL;
static const int64_t kTop38Bits = 0xfffffffffc000000LL;
static uint64_t load_3(const uint8_t *in)
{
uint64_t result;
result = ((uint64_t)in[0]);
result |= ((uint64_t)in[1]) << 8;
result |= ((uint64_t)in[2]) << 16;
return result;
}
static uint64_t load_4(const uint8_t *in)
{
uint64_t result;
result = ((uint64_t)in[0]);
result |= ((uint64_t)in[1]) << 8;
result |= ((uint64_t)in[2]) << 16;
result |= ((uint64_t)in[3]) << 24;
return result;
}
static void fe_frombytes(fe h, const uint8_t *s)
{
/* Ignores top bit of h. */
int64_t h0 = load_4(s);
int64_t h1 = load_3(s + 4) << 6;
int64_t h2 = load_3(s + 7) << 5;
int64_t h3 = load_3(s + 10) << 3;
int64_t h4 = load_3(s + 13) << 2;
int64_t h5 = load_4(s + 16);
int64_t h6 = load_3(s + 20) << 7;
int64_t h7 = load_3(s + 23) << 5;
int64_t h8 = load_3(s + 26) << 4;
int64_t h9 = (load_3(s + 29) & 0x7fffff) << 2;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
h[0] = (int32_t)h0;
h[1] = (int32_t)h1;
h[2] = (int32_t)h2;
h[3] = (int32_t)h3;
h[4] = (int32_t)h4;
h[5] = (int32_t)h5;
h[6] = (int32_t)h6;
h[7] = (int32_t)h7;
h[8] = (int32_t)h8;
h[9] = (int32_t)h9;
}
/*
* Preconditions:
* |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*
* Write p=2^255-19; q=floor(h/p).
* Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))).
*
* Proof:
* Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4.
* Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4.
*
* Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9).
* Then 0<y<1.
*
* Write r=h-pq.
* Have 0<=r<=p-1=2^255-20.
* Thus 0<=r+19(2^-255)r<r+19(2^-255)2^255<=2^255-1.
*
* Write x=r+19(2^-255)r+y.
* Then 0<x<2^255 so floor(2^(-255)x) = 0 so floor(q+2^(-255)x) = q.
*
* Have q+2^(-255)x = 2^(-255)(h + 19 2^(-25) h9 + 2^(-1))
* so floor(2^(-255)(h + 19 2^(-25) h9 + 2^(-1))) = q.
*/
static void fe_tobytes(uint8_t *s, const fe h)
{
int32_t h0 = h[0];
int32_t h1 = h[1];
int32_t h2 = h[2];
int32_t h3 = h[3];
int32_t h4 = h[4];
int32_t h5 = h[5];
int32_t h6 = h[6];
int32_t h7 = h[7];
int32_t h8 = h[8];
int32_t h9 = h[9];
int32_t q;
q = (19 * h9 + (((int32_t) 1) << 24)) >> 25;
q = (h0 + q) >> 26;
q = (h1 + q) >> 25;
q = (h2 + q) >> 26;
q = (h3 + q) >> 25;
q = (h4 + q) >> 26;
q = (h5 + q) >> 25;
q = (h6 + q) >> 26;
q = (h7 + q) >> 25;
q = (h8 + q) >> 26;
q = (h9 + q) >> 25;
/* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */
h0 += 19 * q;
/* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */
h1 += h0 >> 26; h0 &= kBottom26Bits;
h2 += h1 >> 25; h1 &= kBottom25Bits;
h3 += h2 >> 26; h2 &= kBottom26Bits;
h4 += h3 >> 25; h3 &= kBottom25Bits;
h5 += h4 >> 26; h4 &= kBottom26Bits;
h6 += h5 >> 25; h5 &= kBottom25Bits;
h7 += h6 >> 26; h6 &= kBottom26Bits;
h8 += h7 >> 25; h7 &= kBottom25Bits;
h9 += h8 >> 26; h8 &= kBottom26Bits;
h9 &= kBottom25Bits;
/* h10 = carry9 */
/*
* Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20.
* Have h0+...+2^230 h9 between 0 and 2^255-1;
* evidently 2^255 h10-2^255 q = 0.
* Goal: Output h0+...+2^230 h9.
*/
s[ 0] = (uint8_t) (h0 >> 0);
s[ 1] = (uint8_t) (h0 >> 8);
s[ 2] = (uint8_t) (h0 >> 16);
s[ 3] = (uint8_t)((h0 >> 24) | ((uint32_t)(h1) << 2));
s[ 4] = (uint8_t) (h1 >> 6);
s[ 5] = (uint8_t) (h1 >> 14);
s[ 6] = (uint8_t)((h1 >> 22) | ((uint32_t)(h2) << 3));
s[ 7] = (uint8_t) (h2 >> 5);
s[ 8] = (uint8_t) (h2 >> 13);
s[ 9] = (uint8_t)((h2 >> 21) | ((uint32_t)(h3) << 5));
s[10] = (uint8_t) (h3 >> 3);
s[11] = (uint8_t) (h3 >> 11);
s[12] = (uint8_t)((h3 >> 19) | ((uint32_t)(h4) << 6));
s[13] = (uint8_t) (h4 >> 2);
s[14] = (uint8_t) (h4 >> 10);
s[15] = (uint8_t) (h4 >> 18);
s[16] = (uint8_t) (h5 >> 0);
s[17] = (uint8_t) (h5 >> 8);
s[18] = (uint8_t) (h5 >> 16);
s[19] = (uint8_t)((h5 >> 24) | ((uint32_t)(h6) << 1));
s[20] = (uint8_t) (h6 >> 7);
s[21] = (uint8_t) (h6 >> 15);
s[22] = (uint8_t)((h6 >> 23) | ((uint32_t)(h7) << 3));
s[23] = (uint8_t) (h7 >> 5);
s[24] = (uint8_t) (h7 >> 13);
s[25] = (uint8_t)((h7 >> 21) | ((uint32_t)(h8) << 4));
s[26] = (uint8_t) (h8 >> 4);
s[27] = (uint8_t) (h8 >> 12);
s[28] = (uint8_t)((h8 >> 20) | ((uint32_t)(h9) << 6));
s[29] = (uint8_t) (h9 >> 2);
s[30] = (uint8_t) (h9 >> 10);
s[31] = (uint8_t) (h9 >> 18);
}
/* h = f */
static void fe_copy(fe h, const fe f)
{
memmove(h, f, sizeof(int32_t) * 10);
}
/* h = 0 */
static void fe_0(fe h)
{
memset(h, 0, sizeof(int32_t) * 10);
}
/* h = 1 */
static void fe_1(fe h)
{
memset(h, 0, sizeof(int32_t) * 10);
h[0] = 1;
}
/*
* h = f + g
*
* Can overlap h with f or g.
*
* Preconditions:
* |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
*
* Postconditions:
* |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
static void fe_add(fe h, const fe f, const fe g)
{
unsigned i;
for (i = 0; i < 10; i++) {
h[i] = f[i] + g[i];
}
}
/*
* h = f - g
*
* Can overlap h with f or g.
*
* Preconditions:
* |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
* |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
*
* Postconditions:
* |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
static void fe_sub(fe h, const fe f, const fe g)
{
unsigned i;
for (i = 0; i < 10; i++) {
h[i] = f[i] - g[i];
}
}
/*
* h = f * g
*
* Can overlap h with f or g.
*
* Preconditions:
* |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
* |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
*
* Postconditions:
* |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
*
* Notes on implementation strategy:
*
* Using schoolbook multiplication.
* Karatsuba would save a little in some cost models.
*
* Most multiplications by 2 and 19 are 32-bit precomputations;
* cheaper than 64-bit postcomputations.
*
* There is one remaining multiplication by 19 in the carry chain;
* one *19 precomputation can be merged into this,
* but the resulting data flow is considerably less clean.
*
* There are 12 carries below.
* 10 of them are 2-way parallelizable and vectorizable.
* Can get away with 11 carries, but then data flow is much deeper.
*
* With tighter constraints on inputs can squeeze carries into int32.
*/
static void fe_mul(fe h, const fe f, const fe g)
{
int32_t f0 = f[0];
int32_t f1 = f[1];
int32_t f2 = f[2];
int32_t f3 = f[3];
int32_t f4 = f[4];
int32_t f5 = f[5];
int32_t f6 = f[6];
int32_t f7 = f[7];
int32_t f8 = f[8];
int32_t f9 = f[9];
int32_t g0 = g[0];
int32_t g1 = g[1];
int32_t g2 = g[2];
int32_t g3 = g[3];
int32_t g4 = g[4];
int32_t g5 = g[5];
int32_t g6 = g[6];
int32_t g7 = g[7];
int32_t g8 = g[8];
int32_t g9 = g[9];
int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */
int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */
int32_t g3_19 = 19 * g3;
int32_t g4_19 = 19 * g4;
int32_t g5_19 = 19 * g5;
int32_t g6_19 = 19 * g6;
int32_t g7_19 = 19 * g7;
int32_t g8_19 = 19 * g8;
int32_t g9_19 = 19 * g9;
int32_t f1_2 = 2 * f1;
int32_t f3_2 = 2 * f3;
int32_t f5_2 = 2 * f5;
int32_t f7_2 = 2 * f7;
int32_t f9_2 = 2 * f9;
int64_t f0g0 = f0 * (int64_t) g0;
int64_t f0g1 = f0 * (int64_t) g1;
int64_t f0g2 = f0 * (int64_t) g2;
int64_t f0g3 = f0 * (int64_t) g3;
int64_t f0g4 = f0 * (int64_t) g4;
int64_t f0g5 = f0 * (int64_t) g5;
int64_t f0g6 = f0 * (int64_t) g6;
int64_t f0g7 = f0 * (int64_t) g7;
int64_t f0g8 = f0 * (int64_t) g8;
int64_t f0g9 = f0 * (int64_t) g9;
int64_t f1g0 = f1 * (int64_t) g0;
int64_t f1g1_2 = f1_2 * (int64_t) g1;
int64_t f1g2 = f1 * (int64_t) g2;
int64_t f1g3_2 = f1_2 * (int64_t) g3;
int64_t f1g4 = f1 * (int64_t) g4;
int64_t f1g5_2 = f1_2 * (int64_t) g5;
int64_t f1g6 = f1 * (int64_t) g6;
int64_t f1g7_2 = f1_2 * (int64_t) g7;
int64_t f1g8 = f1 * (int64_t) g8;
int64_t f1g9_38 = f1_2 * (int64_t) g9_19;
int64_t f2g0 = f2 * (int64_t) g0;
int64_t f2g1 = f2 * (int64_t) g1;
int64_t f2g2 = f2 * (int64_t) g2;
int64_t f2g3 = f2 * (int64_t) g3;
int64_t f2g4 = f2 * (int64_t) g4;
int64_t f2g5 = f2 * (int64_t) g5;
int64_t f2g6 = f2 * (int64_t) g6;
int64_t f2g7 = f2 * (int64_t) g7;
int64_t f2g8_19 = f2 * (int64_t) g8_19;
int64_t f2g9_19 = f2 * (int64_t) g9_19;
int64_t f3g0 = f3 * (int64_t) g0;
int64_t f3g1_2 = f3_2 * (int64_t) g1;
int64_t f3g2 = f3 * (int64_t) g2;
int64_t f3g3_2 = f3_2 * (int64_t) g3;
int64_t f3g4 = f3 * (int64_t) g4;
int64_t f3g5_2 = f3_2 * (int64_t) g5;
int64_t f3g6 = f3 * (int64_t) g6;
int64_t f3g7_38 = f3_2 * (int64_t) g7_19;
int64_t f3g8_19 = f3 * (int64_t) g8_19;
int64_t f3g9_38 = f3_2 * (int64_t) g9_19;
int64_t f4g0 = f4 * (int64_t) g0;
int64_t f4g1 = f4 * (int64_t) g1;
int64_t f4g2 = f4 * (int64_t) g2;
int64_t f4g3 = f4 * (int64_t) g3;
int64_t f4g4 = f4 * (int64_t) g4;
int64_t f4g5 = f4 * (int64_t) g5;
int64_t f4g6_19 = f4 * (int64_t) g6_19;
int64_t f4g7_19 = f4 * (int64_t) g7_19;
int64_t f4g8_19 = f4 * (int64_t) g8_19;
int64_t f4g9_19 = f4 * (int64_t) g9_19;
int64_t f5g0 = f5 * (int64_t) g0;
int64_t f5g1_2 = f5_2 * (int64_t) g1;
int64_t f5g2 = f5 * (int64_t) g2;
int64_t f5g3_2 = f5_2 * (int64_t) g3;
int64_t f5g4 = f5 * (int64_t) g4;
int64_t f5g5_38 = f5_2 * (int64_t) g5_19;
int64_t f5g6_19 = f5 * (int64_t) g6_19;
int64_t f5g7_38 = f5_2 * (int64_t) g7_19;
int64_t f5g8_19 = f5 * (int64_t) g8_19;
int64_t f5g9_38 = f5_2 * (int64_t) g9_19;
int64_t f6g0 = f6 * (int64_t) g0;
int64_t f6g1 = f6 * (int64_t) g1;
int64_t f6g2 = f6 * (int64_t) g2;
int64_t f6g3 = f6 * (int64_t) g3;
int64_t f6g4_19 = f6 * (int64_t) g4_19;
int64_t f6g5_19 = f6 * (int64_t) g5_19;
int64_t f6g6_19 = f6 * (int64_t) g6_19;
int64_t f6g7_19 = f6 * (int64_t) g7_19;
int64_t f6g8_19 = f6 * (int64_t) g8_19;
int64_t f6g9_19 = f6 * (int64_t) g9_19;
int64_t f7g0 = f7 * (int64_t) g0;
int64_t f7g1_2 = f7_2 * (int64_t) g1;
int64_t f7g2 = f7 * (int64_t) g2;
int64_t f7g3_38 = f7_2 * (int64_t) g3_19;
int64_t f7g4_19 = f7 * (int64_t) g4_19;
int64_t f7g5_38 = f7_2 * (int64_t) g5_19;
int64_t f7g6_19 = f7 * (int64_t) g6_19;
int64_t f7g7_38 = f7_2 * (int64_t) g7_19;
int64_t f7g8_19 = f7 * (int64_t) g8_19;
int64_t f7g9_38 = f7_2 * (int64_t) g9_19;
int64_t f8g0 = f8 * (int64_t) g0;
int64_t f8g1 = f8 * (int64_t) g1;
int64_t f8g2_19 = f8 * (int64_t) g2_19;
int64_t f8g3_19 = f8 * (int64_t) g3_19;
int64_t f8g4_19 = f8 * (int64_t) g4_19;
int64_t f8g5_19 = f8 * (int64_t) g5_19;
int64_t f8g6_19 = f8 * (int64_t) g6_19;
int64_t f8g7_19 = f8 * (int64_t) g7_19;
int64_t f8g8_19 = f8 * (int64_t) g8_19;
int64_t f8g9_19 = f8 * (int64_t) g9_19;
int64_t f9g0 = f9 * (int64_t) g0;
int64_t f9g1_38 = f9_2 * (int64_t) g1_19;
int64_t f9g2_19 = f9 * (int64_t) g2_19;
int64_t f9g3_38 = f9_2 * (int64_t) g3_19;
int64_t f9g4_19 = f9 * (int64_t) g4_19;
int64_t f9g5_38 = f9_2 * (int64_t) g5_19;
int64_t f9g6_19 = f9 * (int64_t) g6_19;
int64_t f9g7_38 = f9_2 * (int64_t) g7_19;
int64_t f9g8_19 = f9 * (int64_t) g8_19;
int64_t f9g9_38 = f9_2 * (int64_t) g9_19;
int64_t h0 = f0g0 + f1g9_38 + f2g8_19 + f3g7_38 + f4g6_19 + f5g5_38 + f6g4_19 + f7g3_38 + f8g2_19 + f9g1_38;
int64_t h1 = f0g1 + f1g0 + f2g9_19 + f3g8_19 + f4g7_19 + f5g6_19 + f6g5_19 + f7g4_19 + f8g3_19 + f9g2_19;
int64_t h2 = f0g2 + f1g1_2 + f2g0 + f3g9_38 + f4g8_19 + f5g7_38 + f6g6_19 + f7g5_38 + f8g4_19 + f9g3_38;
int64_t h3 = f0g3 + f1g2 + f2g1 + f3g0 + f4g9_19 + f5g8_19 + f6g7_19 + f7g6_19 + f8g5_19 + f9g4_19;
int64_t h4 = f0g4 + f1g3_2 + f2g2 + f3g1_2 + f4g0 + f5g9_38 + f6g8_19 + f7g7_38 + f8g6_19 + f9g5_38;
int64_t h5 = f0g5 + f1g4 + f2g3 + f3g2 + f4g1 + f5g0 + f6g9_19 + f7g8_19 + f8g7_19 + f9g6_19;
int64_t h6 = f0g6 + f1g5_2 + f2g4 + f3g3_2 + f4g2 + f5g1_2 + f6g0 + f7g9_38 + f8g8_19 + f9g7_38;
int64_t h7 = f0g7 + f1g6 + f2g5 + f3g4 + f4g3 + f5g2 + f6g1 + f7g0 + f8g9_19 + f9g8_19;
int64_t h8 = f0g8 + f1g7_2 + f2g6 + f3g5_2 + f4g4 + f5g3_2 + f6g2 + f7g1_2 + f8g0 + f9g9_38;
int64_t h9 = f0g9 + f1g8 + f2g7 + f3g6 + f4g5 + f5g4 + f6g3 + f7g2 + f8g1 + f9g0 ;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
/* |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38))
* i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8
* |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19))
* i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 */
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
/* |h0| <= 2^25 */
/* |h4| <= 2^25 */
/* |h1| <= 1.71*2^59 */
/* |h5| <= 1.71*2^59 */
carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
/* |h1| <= 2^24; from now on fits into int32 */
/* |h5| <= 2^24; from now on fits into int32 */
/* |h2| <= 1.41*2^60 */
/* |h6| <= 1.41*2^60 */
carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
/* |h2| <= 2^25; from now on fits into int32 unchanged */
/* |h6| <= 2^25; from now on fits into int32 unchanged */
/* |h3| <= 1.71*2^59 */
/* |h7| <= 1.71*2^59 */
carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
/* |h3| <= 2^24; from now on fits into int32 unchanged */
/* |h7| <= 2^24; from now on fits into int32 unchanged */
/* |h4| <= 1.72*2^34 */
/* |h8| <= 1.41*2^60 */
carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
/* |h4| <= 2^25; from now on fits into int32 unchanged */
/* |h8| <= 2^25; from now on fits into int32 unchanged */
/* |h5| <= 1.01*2^24 */
/* |h9| <= 1.71*2^59 */
carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
/* |h9| <= 2^24; from now on fits into int32 unchanged */
/* |h0| <= 1.1*2^39 */
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
/* |h0| <= 2^25; from now on fits into int32 unchanged */
/* |h1| <= 1.01*2^24 */
h[0] = (int32_t)h0;
h[1] = (int32_t)h1;
h[2] = (int32_t)h2;
h[3] = (int32_t)h3;
h[4] = (int32_t)h4;
h[5] = (int32_t)h5;
h[6] = (int32_t)h6;
h[7] = (int32_t)h7;
h[8] = (int32_t)h8;
h[9] = (int32_t)h9;
}
/*
* h = f * f
*
* Can overlap h with f.
*
* Preconditions:
* |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
*
* Postconditions:
* |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
*
* See fe_mul.c for discussion of implementation strategy.
*/
static void fe_sq(fe h, const fe f)
{
int32_t f0 = f[0];
int32_t f1 = f[1];
int32_t f2 = f[2];
int32_t f3 = f[3];
int32_t f4 = f[4];
int32_t f5 = f[5];
int32_t f6 = f[6];
int32_t f7 = f[7];
int32_t f8 = f[8];
int32_t f9 = f[9];
int32_t f0_2 = 2 * f0;
int32_t f1_2 = 2 * f1;
int32_t f2_2 = 2 * f2;
int32_t f3_2 = 2 * f3;
int32_t f4_2 = 2 * f4;
int32_t f5_2 = 2 * f5;
int32_t f6_2 = 2 * f6;
int32_t f7_2 = 2 * f7;
int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
int64_t f0f0 = f0 * (int64_t) f0;
int64_t f0f1_2 = f0_2 * (int64_t) f1;
int64_t f0f2_2 = f0_2 * (int64_t) f2;
int64_t f0f3_2 = f0_2 * (int64_t) f3;
int64_t f0f4_2 = f0_2 * (int64_t) f4;
int64_t f0f5_2 = f0_2 * (int64_t) f5;
int64_t f0f6_2 = f0_2 * (int64_t) f6;
int64_t f0f7_2 = f0_2 * (int64_t) f7;
int64_t f0f8_2 = f0_2 * (int64_t) f8;
int64_t f0f9_2 = f0_2 * (int64_t) f9;
int64_t f1f1_2 = f1_2 * (int64_t) f1;
int64_t f1f2_2 = f1_2 * (int64_t) f2;
int64_t f1f3_4 = f1_2 * (int64_t) f3_2;
int64_t f1f4_2 = f1_2 * (int64_t) f4;
int64_t f1f5_4 = f1_2 * (int64_t) f5_2;
int64_t f1f6_2 = f1_2 * (int64_t) f6;
int64_t f1f7_4 = f1_2 * (int64_t) f7_2;
int64_t f1f8_2 = f1_2 * (int64_t) f8;
int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
int64_t f2f2 = f2 * (int64_t) f2;
int64_t f2f3_2 = f2_2 * (int64_t) f3;
int64_t f2f4_2 = f2_2 * (int64_t) f4;
int64_t f2f5_2 = f2_2 * (int64_t) f5;
int64_t f2f6_2 = f2_2 * (int64_t) f6;
int64_t f2f7_2 = f2_2 * (int64_t) f7;
int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
int64_t f2f9_38 = f2 * (int64_t) f9_38;
int64_t f3f3_2 = f3_2 * (int64_t) f3;
int64_t f3f4_2 = f3_2 * (int64_t) f4;
int64_t f3f5_4 = f3_2 * (int64_t) f5_2;
int64_t f3f6_2 = f3_2 * (int64_t) f6;
int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
int64_t f4f4 = f4 * (int64_t) f4;
int64_t f4f5_2 = f4_2 * (int64_t) f5;
int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
int64_t f4f7_38 = f4 * (int64_t) f7_38;
int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
int64_t f4f9_38 = f4 * (int64_t) f9_38;
int64_t f5f5_38 = f5 * (int64_t) f5_38;
int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
int64_t f6f6_19 = f6 * (int64_t) f6_19;
int64_t f6f7_38 = f6 * (int64_t) f7_38;
int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
int64_t f6f9_38 = f6 * (int64_t) f9_38;
int64_t f7f7_38 = f7 * (int64_t) f7_38;
int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
int64_t f8f8_19 = f8 * (int64_t) f8_19;
int64_t f8f9_38 = f8 * (int64_t) f9_38;
int64_t f9f9_38 = f9 * (int64_t) f9_38;
int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
h[0] = (int32_t)h0;
h[1] = (int32_t)h1;
h[2] = (int32_t)h2;
h[3] = (int32_t)h3;
h[4] = (int32_t)h4;
h[5] = (int32_t)h5;
h[6] = (int32_t)h6;
h[7] = (int32_t)h7;
h[8] = (int32_t)h8;
h[9] = (int32_t)h9;
}
static void fe_invert(fe out, const fe z)
{
fe t0;
fe t1;
fe t2;
fe t3;
int i;
/*
* Compute z ** -1 = z ** (2 ** 255 - 19 - 2) with the exponent as
* 2 ** 255 - 21 = (2 ** 5) * (2 ** 250 - 1) + 11.
*/
/* t0 = z ** 2 */
fe_sq(t0, z);
/* t1 = t0 ** (2 ** 2) = z ** 8 */
fe_sq(t1, t0);
fe_sq(t1, t1);
/* t1 = z * t1 = z ** 9 */
fe_mul(t1, z, t1);
/* t0 = t0 * t1 = z ** 11 -- stash t0 away for the end. */
fe_mul(t0, t0, t1);
/* t2 = t0 ** 2 = z ** 22 */
fe_sq(t2, t0);
/* t1 = t1 * t2 = z ** (2 ** 5 - 1) */
fe_mul(t1, t1, t2);
/* t2 = t1 ** (2 ** 5) = z ** ((2 ** 5) * (2 ** 5 - 1)) */
fe_sq(t2, t1);
for (i = 1; i < 5; ++i) {
fe_sq(t2, t2);
}
/* t1 = t1 * t2 = z ** ((2 ** 5 + 1) * (2 ** 5 - 1)) = z ** (2 ** 10 - 1) */
fe_mul(t1, t2, t1);
/* Continuing similarly... */
/* t2 = z ** (2 ** 20 - 1) */
fe_sq(t2, t1);
for (i = 1; i < 10; ++i) {
fe_sq(t2, t2);
}
fe_mul(t2, t2, t1);
/* t2 = z ** (2 ** 40 - 1) */
fe_sq(t3, t2);
for (i = 1; i < 20; ++i) {
fe_sq(t3, t3);
}
fe_mul(t2, t3, t2);
/* t2 = z ** (2 ** 10) * (2 ** 40 - 1) */
for (i = 0; i < 10; ++i) {
fe_sq(t2, t2);
}
/* t1 = z ** (2 ** 50 - 1) */
fe_mul(t1, t2, t1);
/* t2 = z ** (2 ** 100 - 1) */
fe_sq(t2, t1);
for (i = 1; i < 50; ++i) {
fe_sq(t2, t2);
}
fe_mul(t2, t2, t1);
/* t2 = z ** (2 ** 200 - 1) */
fe_sq(t3, t2);
for (i = 1; i < 100; ++i) {
fe_sq(t3, t3);
}
fe_mul(t2, t3, t2);
/* t2 = z ** ((2 ** 50) * (2 ** 200 - 1) */
fe_sq(t2, t2);
for (i = 1; i < 50; ++i) {
fe_sq(t2, t2);
}
/* t1 = z ** (2 ** 250 - 1) */
fe_mul(t1, t2, t1);
/* t1 = z ** ((2 ** 5) * (2 ** 250 - 1)) */
fe_sq(t1, t1);
for (i = 1; i < 5; ++i) {
fe_sq(t1, t1);
}
/* Recall t0 = z ** 11; out = z ** (2 ** 255 - 21) */
fe_mul(out, t1, t0);
}
/*
* h = -f
*
* Preconditions:
* |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
*
* Postconditions:
* |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
*/
static void fe_neg(fe h, const fe f)
{
unsigned i;
for (i = 0; i < 10; i++) {
h[i] = -f[i];
}
}
/*
* Replace (f,g) with (g,g) if b == 1;
* replace (f,g) with (f,g) if b == 0.
*
* Preconditions: b in {0,1}.
*/
static void fe_cmov(fe f, const fe g, unsigned b)
{
size_t i;
b = 0-b;
for (i = 0; i < 10; i++) {
int32_t x = f[i] ^ g[i];
x &= b;
f[i] ^= x;
}
}
/*
* return 0 if f == 0
* return 1 if f != 0
*
* Preconditions:
* |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
static int fe_isnonzero(const fe f)
{
uint8_t s[32];
static const uint8_t zero[32] = {0};
fe_tobytes(s, f);
return CRYPTO_memcmp(s, zero, sizeof(zero)) != 0;
}
/*
* return 1 if f is in {1,3,5,...,q-2}
* return 0 if f is in {0,2,4,...,q-1}
*
* Preconditions:
* |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*/
static int fe_isnegative(const fe f)
{
uint8_t s[32];
fe_tobytes(s, f);
return s[0] & 1;
}
/*
* h = 2 * f * f
*
* Can overlap h with f.
*
* Preconditions:
* |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc.
*
* Postconditions:
* |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc.
*
* See fe_mul.c for discussion of implementation strategy.
*/
static void fe_sq2(fe h, const fe f)
{
int32_t f0 = f[0];
int32_t f1 = f[1];
int32_t f2 = f[2];
int32_t f3 = f[3];
int32_t f4 = f[4];
int32_t f5 = f[5];
int32_t f6 = f[6];
int32_t f7 = f[7];
int32_t f8 = f[8];
int32_t f9 = f[9];
int32_t f0_2 = 2 * f0;
int32_t f1_2 = 2 * f1;
int32_t f2_2 = 2 * f2;
int32_t f3_2 = 2 * f3;
int32_t f4_2 = 2 * f4;
int32_t f5_2 = 2 * f5;
int32_t f6_2 = 2 * f6;
int32_t f7_2 = 2 * f7;
int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */
int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */
int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */
int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */
int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */
int64_t f0f0 = f0 * (int64_t) f0;
int64_t f0f1_2 = f0_2 * (int64_t) f1;
int64_t f0f2_2 = f0_2 * (int64_t) f2;
int64_t f0f3_2 = f0_2 * (int64_t) f3;
int64_t f0f4_2 = f0_2 * (int64_t) f4;
int64_t f0f5_2 = f0_2 * (int64_t) f5;
int64_t f0f6_2 = f0_2 * (int64_t) f6;
int64_t f0f7_2 = f0_2 * (int64_t) f7;
int64_t f0f8_2 = f0_2 * (int64_t) f8;
int64_t f0f9_2 = f0_2 * (int64_t) f9;
int64_t f1f1_2 = f1_2 * (int64_t) f1;
int64_t f1f2_2 = f1_2 * (int64_t) f2;
int64_t f1f3_4 = f1_2 * (int64_t) f3_2;
int64_t f1f4_2 = f1_2 * (int64_t) f4;
int64_t f1f5_4 = f1_2 * (int64_t) f5_2;
int64_t f1f6_2 = f1_2 * (int64_t) f6;
int64_t f1f7_4 = f1_2 * (int64_t) f7_2;
int64_t f1f8_2 = f1_2 * (int64_t) f8;
int64_t f1f9_76 = f1_2 * (int64_t) f9_38;
int64_t f2f2 = f2 * (int64_t) f2;
int64_t f2f3_2 = f2_2 * (int64_t) f3;
int64_t f2f4_2 = f2_2 * (int64_t) f4;
int64_t f2f5_2 = f2_2 * (int64_t) f5;
int64_t f2f6_2 = f2_2 * (int64_t) f6;
int64_t f2f7_2 = f2_2 * (int64_t) f7;
int64_t f2f8_38 = f2_2 * (int64_t) f8_19;
int64_t f2f9_38 = f2 * (int64_t) f9_38;
int64_t f3f3_2 = f3_2 * (int64_t) f3;
int64_t f3f4_2 = f3_2 * (int64_t) f4;
int64_t f3f5_4 = f3_2 * (int64_t) f5_2;
int64_t f3f6_2 = f3_2 * (int64_t) f6;
int64_t f3f7_76 = f3_2 * (int64_t) f7_38;
int64_t f3f8_38 = f3_2 * (int64_t) f8_19;
int64_t f3f9_76 = f3_2 * (int64_t) f9_38;
int64_t f4f4 = f4 * (int64_t) f4;
int64_t f4f5_2 = f4_2 * (int64_t) f5;
int64_t f4f6_38 = f4_2 * (int64_t) f6_19;
int64_t f4f7_38 = f4 * (int64_t) f7_38;
int64_t f4f8_38 = f4_2 * (int64_t) f8_19;
int64_t f4f9_38 = f4 * (int64_t) f9_38;
int64_t f5f5_38 = f5 * (int64_t) f5_38;
int64_t f5f6_38 = f5_2 * (int64_t) f6_19;
int64_t f5f7_76 = f5_2 * (int64_t) f7_38;
int64_t f5f8_38 = f5_2 * (int64_t) f8_19;
int64_t f5f9_76 = f5_2 * (int64_t) f9_38;
int64_t f6f6_19 = f6 * (int64_t) f6_19;
int64_t f6f7_38 = f6 * (int64_t) f7_38;
int64_t f6f8_38 = f6_2 * (int64_t) f8_19;
int64_t f6f9_38 = f6 * (int64_t) f9_38;
int64_t f7f7_38 = f7 * (int64_t) f7_38;
int64_t f7f8_38 = f7_2 * (int64_t) f8_19;
int64_t f7f9_76 = f7_2 * (int64_t) f9_38;
int64_t f8f8_19 = f8 * (int64_t) f8_19;
int64_t f8f9_38 = f8 * (int64_t) f9_38;
int64_t f9f9_38 = f9 * (int64_t) f9_38;
int64_t h0 = f0f0 + f1f9_76 + f2f8_38 + f3f7_76 + f4f6_38 + f5f5_38;
int64_t h1 = f0f1_2 + f2f9_38 + f3f8_38 + f4f7_38 + f5f6_38;
int64_t h2 = f0f2_2 + f1f1_2 + f3f9_76 + f4f8_38 + f5f7_76 + f6f6_19;
int64_t h3 = f0f3_2 + f1f2_2 + f4f9_38 + f5f8_38 + f6f7_38;
int64_t h4 = f0f4_2 + f1f3_4 + f2f2 + f5f9_76 + f6f8_38 + f7f7_38;
int64_t h5 = f0f5_2 + f1f4_2 + f2f3_2 + f6f9_38 + f7f8_38;
int64_t h6 = f0f6_2 + f1f5_4 + f2f4_2 + f3f3_2 + f7f9_76 + f8f8_19;
int64_t h7 = f0f7_2 + f1f6_2 + f2f5_2 + f3f4_2 + f8f9_38;
int64_t h8 = f0f8_2 + f1f7_4 + f2f6_2 + f3f5_4 + f4f4 + f9f9_38;
int64_t h9 = f0f9_2 + f1f8_2 + f2f7_2 + f3f6_2 + f4f5_2;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
h0 += h0;
h1 += h1;
h2 += h2;
h3 += h3;
h4 += h4;
h5 += h5;
h6 += h6;
h7 += h7;
h8 += h8;
h9 += h9;
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
h[0] = (int32_t)h0;
h[1] = (int32_t)h1;
h[2] = (int32_t)h2;
h[3] = (int32_t)h3;
h[4] = (int32_t)h4;
h[5] = (int32_t)h5;
h[6] = (int32_t)h6;
h[7] = (int32_t)h7;
h[8] = (int32_t)h8;
h[9] = (int32_t)h9;
}
static void fe_pow22523(fe out, const fe z)
{
fe t0;
fe t1;
fe t2;
int i;
fe_sq(t0, z);
fe_sq(t1, t0);
for (i = 1; i < 2; ++i) {
fe_sq(t1, t1);
}
fe_mul(t1, z, t1);
fe_mul(t0, t0, t1);
fe_sq(t0, t0);
fe_mul(t0, t1, t0);
fe_sq(t1, t0);
for (i = 1; i < 5; ++i) {
fe_sq(t1, t1);
}
fe_mul(t0, t1, t0);
fe_sq(t1, t0);
for (i = 1; i < 10; ++i) {
fe_sq(t1, t1);
}
fe_mul(t1, t1, t0);
fe_sq(t2, t1);
for (i = 1; i < 20; ++i) {
fe_sq(t2, t2);
}
fe_mul(t1, t2, t1);
fe_sq(t1, t1);
for (i = 1; i < 10; ++i) {
fe_sq(t1, t1);
}
fe_mul(t0, t1, t0);
fe_sq(t1, t0);
for (i = 1; i < 50; ++i) {
fe_sq(t1, t1);
}
fe_mul(t1, t1, t0);
fe_sq(t2, t1);
for (i = 1; i < 100; ++i) {
fe_sq(t2, t2);
}
fe_mul(t1, t2, t1);
fe_sq(t1, t1);
for (i = 1; i < 50; ++i) {
fe_sq(t1, t1);
}
fe_mul(t0, t1, t0);
fe_sq(t0, t0);
for (i = 1; i < 2; ++i) {
fe_sq(t0, t0);
}
fe_mul(out, t0, z);
}
/*
* ge means group element.
*
* Here the group is the set of pairs (x,y) of field elements (see fe.h)
* satisfying -x^2 + y^2 = 1 + d x^2y^2
* where d = -121665/121666.
*
* Representations:
* ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z
* ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT
* ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T
* ge_precomp (Duif): (y+x,y-x,2dxy)
*/
typedef struct {
fe X;
fe Y;
fe Z;
} ge_p2;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p3;
typedef struct {
fe X;
fe Y;
fe Z;
fe T;
} ge_p1p1;
typedef struct {
fe yplusx;
fe yminusx;
fe xy2d;
} ge_precomp;
typedef struct {
fe YplusX;
fe YminusX;
fe Z;
fe T2d;
} ge_cached;
static void ge_tobytes(uint8_t *s, const ge_p2 *h)
{
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}
static void ge_p3_tobytes(uint8_t *s, const ge_p3 *h)
{
fe recip;
fe x;
fe y;
fe_invert(recip, h->Z);
fe_mul(x, h->X, recip);
fe_mul(y, h->Y, recip);
fe_tobytes(s, y);
s[31] ^= fe_isnegative(x) << 7;
}
static const fe d = {
-10913610, 13857413, -15372611, 6949391, 114729,
-8787816, -6275908, -3247719, -18696448, -12055116
};
static const fe sqrtm1 = {
-32595792, -7943725, 9377950, 3500415, 12389472,
-272473, -25146209, -2005654, 326686, 11406482
};
static int ge_frombytes_vartime(ge_p3 *h, const uint8_t *s)
{
fe u;
fe v;
fe v3;
fe vxx;
fe check;
fe_frombytes(h->Y, s);
fe_1(h->Z);
fe_sq(u, h->Y);
fe_mul(v, u, d);
fe_sub(u, u, h->Z); /* u = y^2-1 */
fe_add(v, v, h->Z); /* v = dy^2+1 */
fe_sq(v3, v);
fe_mul(v3, v3, v); /* v3 = v^3 */
fe_sq(h->X, v3);
fe_mul(h->X, h->X, v);
fe_mul(h->X, h->X, u); /* x = uv^7 */
fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
fe_mul(h->X, h->X, v3);
fe_mul(h->X, h->X, u); /* x = uv^3(uv^7)^((q-5)/8) */
fe_sq(vxx, h->X);
fe_mul(vxx, vxx, v);
fe_sub(check, vxx, u); /* vx^2-u */
if (fe_isnonzero(check)) {
fe_add(check, vxx, u); /* vx^2+u */
if (fe_isnonzero(check)) {
return -1;
}
fe_mul(h->X, h->X, sqrtm1);
}
if (fe_isnegative(h->X) != (s[31] >> 7)) {
fe_neg(h->X, h->X);
}
fe_mul(h->T, h->X, h->Y);
return 0;
}
static void ge_p2_0(ge_p2 *h)
{
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
}
static void ge_p3_0(ge_p3 *h)
{
fe_0(h->X);
fe_1(h->Y);
fe_1(h->Z);
fe_0(h->T);
}
static void ge_precomp_0(ge_precomp *h)
{
fe_1(h->yplusx);
fe_1(h->yminusx);
fe_0(h->xy2d);
}
/* r = p */
static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p)
{
fe_copy(r->X, p->X);
fe_copy(r->Y, p->Y);
fe_copy(r->Z, p->Z);
}
static const fe d2 = {
-21827239, -5839606, -30745221, 13898782, 229458,
15978800, -12551817, -6495438, 29715968, 9444199
};
/* r = p */
static void ge_p3_to_cached(ge_cached *r, const ge_p3 *p)
{
fe_add(r->YplusX, p->Y, p->X);
fe_sub(r->YminusX, p->Y, p->X);
fe_copy(r->Z, p->Z);
fe_mul(r->T2d, p->T, d2);
}
/* r = p */
static void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p)
{
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
}
/* r = p */
static void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p)
{
fe_mul(r->X, p->X, p->T);
fe_mul(r->Y, p->Y, p->Z);
fe_mul(r->Z, p->Z, p->T);
fe_mul(r->T, p->X, p->Y);
}
/* r = 2 * p */
static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p)
{
fe t0;
fe_sq(r->X, p->X);
fe_sq(r->Z, p->Y);
fe_sq2(r->T, p->Z);
fe_add(r->Y, p->X, p->Y);
fe_sq(t0, r->Y);
fe_add(r->Y, r->Z, r->X);
fe_sub(r->Z, r->Z, r->X);
fe_sub(r->X, t0, r->Y);
fe_sub(r->T, r->T, r->Z);
}
/* r = 2 * p */
static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p)
{
ge_p2 q;
ge_p3_to_p2(&q, p);
ge_p2_dbl(r, &q);
}
/* r = p + q */
static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q)
{
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yplusx);
fe_mul(r->Y, r->Y, q->yminusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
/* r = p - q */
static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q)
{
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->yminusx);
fe_mul(r->Y, r->Y, q->yplusx);
fe_mul(r->T, q->xy2d, p->T);
fe_add(t0, p->Z, p->Z);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
/* r = p + q */
static void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q)
{
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YplusX);
fe_mul(r->Y, r->Y, q->YminusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_add(r->Z, t0, r->T);
fe_sub(r->T, t0, r->T);
}
/* r = p - q */
static void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q)
{
fe t0;
fe_add(r->X, p->Y, p->X);
fe_sub(r->Y, p->Y, p->X);
fe_mul(r->Z, r->X, q->YminusX);
fe_mul(r->Y, r->Y, q->YplusX);
fe_mul(r->T, q->T2d, p->T);
fe_mul(r->X, p->Z, q->Z);
fe_add(t0, r->X, r->X);
fe_sub(r->X, r->Z, r->Y);
fe_add(r->Y, r->Z, r->Y);
fe_sub(r->Z, t0, r->T);
fe_add(r->T, t0, r->T);
}
static uint8_t equal(signed char b, signed char c)
{
uint8_t ub = b;
uint8_t uc = c;
uint8_t x = ub ^ uc; /* 0: yes; 1..255: no */
uint32_t y = x; /* 0: yes; 1..255: no */
y -= 1; /* 4294967295: yes; 0..254: no */
y >>= 31; /* 1: yes; 0: no */
return y;
}
static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b)
{
fe_cmov(t->yplusx, u->yplusx, b);
fe_cmov(t->yminusx, u->yminusx, b);
fe_cmov(t->xy2d, u->xy2d, b);
}
/* k25519Precomp[i][j] = (j+1)*256^i*B */
static const ge_precomp k25519Precomp[32][8] = {
{
{
{25967493, -14356035, 29566456, 3660896, -12694345, 4014787,
27544626, -11754271, -6079156, 2047605},
{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692,
5043384, 19500929, -15469378},
{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380,
29287919, 11864899, -24514362, -4438546},
},
{
{-12815894, -12976347, -21581243, 11784320, -25355658, -2750717,
-11717903, -3814571, -358445, -10211303},
{-21703237, 6903825, 27185491, 6451973, -29577724, -9554005,
-15616551, 11189268, -26829678, -5319081},
{26966642, 11152617, 32442495, 15396054, 14353839, -12752335,
-3128826, -9541118, -15472047, -4166697},
},
{
{15636291, -9688557, 24204773, -7912398, 616977, -16685262,
27787600, -14772189, 28944400, -1550024},
{16568933, 4717097, -11556148, -1102322, 15682896, -11807043,
16354577, -11775962, 7689662, 11199574},
{30464156, -5976125, -11779434, -15670865, 23220365, 15915852,
7512774, 10017326, -17749093, -9920357},
},
{
{-17036878, 13921892, 10945806, -6033431, 27105052, -16084379,
-28926210, 15006023, 3284568, -6276540},
{23599295, -8306047, -11193664, -7687416, 13236774, 10506355,
7464579, 9656445, 13059162, 10374397},
{7798556, 16710257, 3033922, 2874086, 28997861, 2835604, 32406664,
-3839045, -641708, -101325},
},
{
{10861363, 11473154, 27284546, 1981175, -30064349, 12577861,
32867885, 14515107, -15438304, 10819380},
{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668,
12483688, -12668491, 5581306},
{19563160, 16186464, -29386857, 4097519, 10237984, -4348115,
28542350, 13850243, -23678021, -15815942},
},
{
{-15371964, -12862754, 32573250, 4720197, -26436522, 5875511,
-19188627, -15224819, -9818940, -12085777},
{-8549212, 109983, 15149363, 2178705, 22900618, 4543417, 3044240,
-15689887, 1762328, 14866737},
{-18199695, -15951423, -10473290, 1707278, -17185920, 3916101,
-28236412, 3959421, 27914454, 4383652},
},
{
{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852,
5230134, -23952439, -15175766},
{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722,
20654025, 16520125, 30598449, 7715701},
{28881845, 14381568, 9657904, 3680757, -20181635, 7843316,
-31400660, 1370708, 29794553, -1409300},
},
{
{14499471, -2729599, -33191113, -4254652, 28494862, 14271267,
30290735, 10876454, -33154098, 2381726},
{-7195431, -2655363, -14730155, 462251, -27724326, 3941372,
-6236617, 3696005, -32300832, 15351955},
{27431194, 8222322, 16448760, -3907995, -18707002, 11938355,
-32961401, -2970515, 29551813, 10109425},
},
},
{
{
{-13657040, -13155431, -31283750, 11777098, 21447386, 6519384,
-2378284, -1627556, 10092783, -4764171},
{27939166, 14210322, 4677035, 16277044, -22964462, -12398139,
-32508754, 12005538, -17810127, 12803510},
{17228999, -15661624, -1233527, 300140, -1224870, -11714777,
30364213, -9038194, 18016357, 4397660},
},
{
{-10958843, -7690207, 4776341, -14954238, 27850028, -15602212,
-26619106, 14544525, -17477504, 982639},
{29253598, 15796703, -2863982, -9908884, 10057023, 3163536, 7332899,
-4120128, -21047696, 9934963},
{5793303, 16271923, -24131614, -10116404, 29188560, 1206517,
-14747930, 4559895, -30123922, -10897950},
},
{
{-27643952, -11493006, 16282657, -11036493, 28414021, -15012264,
24191034, 4541697, -13338309, 5500568},
{12650548, -1497113, 9052871, 11355358, -17680037, -8400164,
-17430592, 12264343, 10874051, 13524335},
{25556948, -3045990, 714651, 2510400, 23394682, -10415330, 33119038,
5080568, -22528059, 5376628},
},
{
{-26088264, -4011052, -17013699, -3537628, -6726793, 1920897,
-22321305, -9447443, 4535768, 1569007},
{-2255422, 14606630, -21692440, -8039818, 28430649, 8775819,
-30494562, 3044290, 31848280, 12543772},
{-22028579, 2943893, -31857513, 6777306, 13784462, -4292203,
-27377195, -2062731, 7718482, 14474653},
},
{
{2385315, 2454213, -22631320, 46603, -4437935, -15680415, 656965,
-7236665, 24316168, -5253567},
{13741529, 10911568, -33233417, -8603737, -20177830, -1033297,
33040651, -13424532, -20729456, 8321686},
{21060490, -2212744, 15712757, -4336099, 1639040, 10656336,
23845965, -11874838, -9984458, 608372},
},
{
{-13672732, -15087586, -10889693, -7557059, -6036909, 11305547,
1123968, -6780577, 27229399, 23887},
{-23244140, -294205, -11744728, 14712571, -29465699, -2029617,
12797024, -6440308, -1633405, 16678954},
{-29500620, 4770662, -16054387, 14001338, 7830047, 9564805,
-1508144, -4795045, -17169265, 4904953},
},
{
{24059557, 14617003, 19037157, -15039908, 19766093, -14906429,
5169211, 16191880, 2128236, -4326833},
{-16981152, 4124966, -8540610, -10653797, 30336522, -14105247,
-29806336, 916033, -6882542, -2986532},
{-22630907, 12419372, -7134229, -7473371, -16478904, 16739175,
285431, 2763829, 15736322, 4143876},
},
{
{2379352, 11839345, -4110402, -5988665, 11274298, 794957, 212801,
-14594663, 23527084, -16458268},
{33431127, -11130478, -17838966, -15626900, 8909499, 8376530,
-32625340, 4087881, -15188911, -14416214},
{1767683, 7197987, -13205226, -2022635, -13091350, 448826, 5799055,
4357868, -4774191, -16323038},
},
},
{
{
{6721966, 13833823, -23523388, -1551314, 26354293, -11863321,
23365147, -3949732, 7390890, 2759800},
{4409041, 2052381, 23373853, 10530217, 7676779, -12885954, 21302353,
-4264057, 1244380, -12919645},
{-4421239, 7169619, 4982368, -2957590, 30256825, -2777540, 14086413,
9208236, 15886429, 16489664},
},
{
{1996075, 10375649, 14346367, 13311202, -6874135, -16438411,
-13693198, 398369, -30606455, -712933},
{-25307465, 9795880, -2777414, 14878809, -33531835, 14780363,
13348553, 12076947, -30836462, 5113182},
{-17770784, 11797796, 31950843, 13929123, -25888302, 12288344,
-30341101, -7336386, 13847711, 5387222},
},
{
{-18582163, -3416217, 17824843, -2340966, 22744343, -10442611,
8763061, 3617786, -19600662, 10370991},
{20246567, -14369378, 22358229, -543712, 18507283, -10413996,
14554437, -8746092, 32232924, 16763880},
{9648505, 10094563, 26416693, 14745928, -30374318, -6472621,
11094161, 15689506, 3140038, -16510092},
},
{
{-16160072, 5472695, 31895588, 4744994, 8823515, 10365685,
-27224800, 9448613, -28774454, 366295},
{19153450, 11523972, -11096490, -6503142, -24647631, 5420647,
28344573, 8041113, 719605, 11671788},
{8678025, 2694440, -6808014, 2517372, 4964326, 11152271, -15432916,
-15266516, 27000813, -10195553},
},
{
{-15157904, 7134312, 8639287, -2814877, -7235688, 10421742, 564065,
5336097, 6750977, -14521026},
{11836410, -3979488, 26297894, 16080799, 23455045, 15735944,
1695823, -8819122, 8169720, 16220347},
{-18115838, 8653647, 17578566, -6092619, -8025777, -16012763,
-11144307, -2627664, -5990708, -14166033},
},
{
{-23308498, -10968312, 15213228, -10081214, -30853605, -11050004,
27884329, 2847284, 2655861, 1738395},
{-27537433, -14253021, -25336301, -8002780, -9370762, 8129821,
21651608, -3239336, -19087449, -11005278},
{1533110, 3437855, 23735889, 459276, 29970501, 11335377, 26030092,
5821408, 10478196, 8544890},
},
{
{32173121, -16129311, 24896207, 3921497, 22579056, -3410854,
19270449, 12217473, 17789017, -3395995},
{-30552961, -2228401, -15578829, -10147201, 13243889, 517024,
15479401, -3853233, 30460520, 1052596},
{-11614875, 13323618, 32618793, 8175907, -15230173, 12596687,
27491595, -4612359, 3179268, -9478891},
},
{
{31947069, -14366651, -4640583, -15339921, -15125977, -6039709,
-14756777, -16411740, 19072640, -9511060},
{11685058, 11822410, 3158003, -13952594, 33402194, -4165066,
5977896, -5215017, 473099, 5040608},
{-20290863, 8198642, -27410132, 11602123, 1290375, -2799760,
28326862, 1721092, -19558642, -3131606},
},
},
{
{
{7881532, 10687937, 7578723, 7738378, -18951012, -2553952, 21820786,
8076149, -27868496, 11538389},
{-19935666, 3899861, 18283497, -6801568, -15728660, -11249211,
8754525, 7446702, -5676054, 5797016},
{-11295600, -3793569, -15782110, -7964573, 12708869, -8456199,
2014099, -9050574, -2369172, -5877341},
},
{
{-22472376, -11568741, -27682020, 1146375, 18956691, 16640559,
1192730, -3714199, 15123619, 10811505},
{14352098, -3419715, -18942044, 10822655, 32750596, 4699007, -70363,
15776356, -28886779, -11974553},
{-28241164, -8072475, -4978962, -5315317, 29416931, 1847569,
-20654173, -16484855, 4714547, -9600655},
},
{
{15200332, 8368572, 19679101, 15970074, -31872674, 1959451,
24611599, -4543832, -11745876, 12340220},
{12876937, -10480056, 33134381, 6590940, -6307776, 14872440,
9613953, 8241152, 15370987, 9608631},
{-4143277, -12014408, 8446281, -391603, 4407738, 13629032, -7724868,
15866074, -28210621, -8814099},
},
{
{26660628, -15677655, 8393734, 358047, -7401291, 992988, -23904233,
858697, 20571223, 8420556},
{14620715, 13067227, -15447274, 8264467, 14106269, 15080814,
33531827, 12516406, -21574435, -12476749},
{236881, 10476226, 57258, -14677024, 6472998, 2466984, 17258519,
7256740, 8791136, 15069930},
},
{
{1276410, -9371918, 22949635, -16322807, -23493039, -5702186,
14711875, 4874229, -30663140, -2331391},
{5855666, 4990204, -13711848, 7294284, -7804282, 1924647, -1423175,
-7912378, -33069337, 9234253},
{20590503, -9018988, 31529744, -7352666, -2706834, 10650548,
31559055, -11609587, 18979186, 13396066},
},
{
{24474287, 4968103, 22267082, 4407354, 24063882, -8325180,
-18816887, 13594782, 33514650, 7021958},
{-11566906, -6565505, -21365085, 15928892, -26158305, 4315421,
-25948728, -3916677, -21480480, 12868082},
{-28635013, 13504661, 19988037, -2132761, 21078225, 6443208,
-21446107, 2244500, -12455797, -8089383},
},
{
{-30595528, 13793479, -5852820, 319136, -25723172, -6263899,
33086546, 8957937, -15233648, 5540521},
{-11630176, -11503902, -8119500, -7643073, 2620056, 1022908,
-23710744, -1568984, -16128528, -14962807},
{23152971, 775386, 27395463, 14006635, -9701118, 4649512, 1689819,
892185, -11513277, -15205948},
},
{
{9770129, 9586738, 26496094, 4324120, 1556511, -3550024, 27453819,
4763127, -19179614, 5867134},
{-32765025, 1927590, 31726409, -4753295, 23962434, -16019500,
27846559, 5931263, -29749703, -16108455},
{27461885, -2977536, 22380810, 1815854, -23033753, -3031938,
7283490, -15148073, -19526700, 7734629},
},
},
{
{
{-8010264, -9590817, -11120403, 6196038, 29344158, -13430885,
7585295, -3176626, 18549497, 15302069},
{-32658337, -6171222, -7672793, -11051681, 6258878, 13504381,
10458790, -6418461, -8872242, 8424746},
{24687205, 8613276, -30667046, -3233545, 1863892, -1830544,
19206234, 7134917, -11284482, -828919},
},
{
{11334899, -9218022, 8025293, 12707519, 17523892, -10476071,
10243738, -14685461, -5066034, 16498837},
{8911542, 6887158, -9584260, -6958590, 11145641, -9543680, 17303925,
-14124238, 6536641, 10543906},
{-28946384, 15479763, -17466835, 568876, -1497683, 11223454,
-2669190, -16625574, -27235709, 8876771},
},
{
{-25742899, -12566864, -15649966, -846607, -33026686, -796288,
-33481822, 15824474, -604426, -9039817},
{10330056, 70051, 7957388, -9002667, 9764902, 15609756, 27698697,
-4890037, 1657394, 3084098},
{10477963, -7470260, 12119566, -13250805, 29016247, -5365589,
31280319, 14396151, -30233575, 15272409},
},
{
{-12288309, 3169463, 28813183, 16658753, 25116432, -5630466,
-25173957, -12636138, -25014757, 1950504},
{-26180358, 9489187, 11053416, -14746161, -31053720, 5825630,
-8384306, -8767532, 15341279, 8373727},
{28685821, 7759505, -14378516, -12002860, -31971820, 4079242,
298136, -10232602, -2878207, 15190420},
},
{
{-32932876, 13806336, -14337485, -15794431, -24004620, 10940928,
8669718, 2742393, -26033313, -6875003},
{-1580388, -11729417, -25979658, -11445023, -17411874, -10912854,
9291594, -16247779, -12154742, 6048605},
{-30305315, 14843444, 1539301, 11864366, 20201677, 1900163,
13934231, 5128323, 11213262, 9168384},
},
{
{-26280513, 11007847, 19408960, -940758, -18592965, -4328580,
-5088060, -11105150, 20470157, -16398701},
{-23136053, 9282192, 14855179, -15390078, -7362815, -14408560,
-22783952, 14461608, 14042978, 5230683},
{29969567, -2741594, -16711867, -8552442, 9175486, -2468974,
21556951, 3506042, -5933891, -12449708},
},
{
{-3144746, 8744661, 19704003, 4581278, -20430686, 6830683,
-21284170, 8971513, -28539189, 15326563},
{-19464629, 10110288, -17262528, -3503892, -23500387, 1355669,
-15523050, 15300988, -20514118, 9168260},
{-5353335, 4488613, -23803248, 16314347, 7780487, -15638939,
-28948358, 9601605, 33087103, -9011387},
},
{
{-19443170, -15512900, -20797467, -12445323, -29824447, 10229461,
-27444329, -15000531, -5996870, 15664672},
{23294591, -16632613, -22650781, -8470978, 27844204, 11461195,
13099750, -2460356, 18151676, 13417686},
{-24722913, -4176517, -31150679, 5988919, -26858785, 6685065,
1661597, -12551441, 15271676, -15452665},
},
},
{
{
{11433042, -13228665, 8239631, -5279517, -1985436, -725718,
-18698764, 2167544, -6921301, -13440182},
{-31436171, 15575146, 30436815, 12192228, -22463353, 9395379,
-9917708, -8638997, 12215110, 12028277},
{14098400, 6555944, 23007258, 5757252, -15427832, -12950502,
30123440, 4617780, -16900089, -655628},
},
{
{-4026201, -15240835, 11893168, 13718664, -14809462, 1847385,
-15819999, 10154009, 23973261, -12684474},
{-26531820, -3695990, -1908898, 2534301, -31870557, -16550355,
18341390, -11419951, 32013174, -10103539},
{-25479301, 10876443, -11771086, -14625140, -12369567, 1838104,
21911214, 6354752, 4425632, -837822},
},
{
{-10433389, -14612966, 22229858, -3091047, -13191166, 776729,
-17415375, -12020462, 4725005, 14044970},
{19268650, -7304421, 1555349, 8692754, -21474059, -9910664, 6347390,
-1411784, -19522291, -16109756},
{-24864089, 12986008, -10898878, -5558584, -11312371, -148526,
19541418, 8180106, 9282262, 10282508},
},
{
{-26205082, 4428547, -8661196, -13194263, 4098402, -14165257,
15522535, 8372215, 5542595, -10702683},
{-10562541, 14895633, 26814552, -16673850, -17480754, -2489360,
-2781891, 6993761, -18093885, 10114655},
{-20107055, -929418, 31422704, 10427861, -7110749, 6150669,
-29091755, -11529146, 25953725, -106158},
},
{
{-4234397, -8039292, -9119125, 3046000, 2101609, -12607294,
19390020, 6094296, -3315279, 12831125},
{-15998678, 7578152, 5310217, 14408357, -33548620, -224739,
31575954, 6326196, 7381791, -2421839},
{-20902779, 3296811, 24736065, -16328389, 18374254, 7318640,
6295303, 8082724, -15362489, 12339664},
},
{
{27724736, 2291157, 6088201, -14184798, 1792727, 5857634, 13848414,
15768922, 25091167, 14856294},
{-18866652, 8331043, 24373479, 8541013, -701998, -9269457, 12927300,
-12695493, -22182473, -9012899},
{-11423429, -5421590, 11632845, 3405020, 30536730, -11674039,
-27260765, 13866390, 30146206, 9142070},
},
{
{3924129, -15307516, -13817122, -10054960, 12291820, -668366,
-27702774, 9326384, -8237858, 4171294},
{-15921940, 16037937, 6713787, 16606682, -21612135, 2790944,
26396185, 3731949, 345228, -5462949},
{-21327538, 13448259, 25284571, 1143661, 20614966, -8849387,
2031539, -12391231, -16253183, -13582083},
},
{
{31016211, -16722429, 26371392, -14451233, -5027349, 14854137,
17477601, 3842657, 28012650, -16405420},
{-5075835, 9368966, -8562079, -4600902, -15249953, 6970560,
-9189873, 16292057, -8867157, 3507940},
{29439664, 3537914, 23333589, 6997794, -17555561, -11018068,
-15209202, -15051267, -9164929, 6580396},
},
},
{
{
{-12185861, -7679788, 16438269, 10826160, -8696817, -6235611,
17860444, -9273846, -2095802, 9304567},
{20714564, -4336911, 29088195, 7406487, 11426967, -5095705,
14792667, -14608617, 5289421, -477127},
{-16665533, -10650790, -6160345, -13305760, 9192020, -1802462,
17271490, 12349094, 26939669, -3752294},
},
{
{-12889898, 9373458, 31595848, 16374215, 21471720, 13221525,
-27283495, -12348559, -3698806, 117887},
{22263325, -6560050, 3984570, -11174646, -15114008, -566785,
28311253, 5358056, -23319780, 541964},
{16259219, 3261970, 2309254, -15534474, -16885711, -4581916,
24134070, -16705829, -13337066, -13552195},
},
{
{9378160, -13140186, -22845982, -12745264, 28198281, -7244098,
-2399684, -717351, 690426, 14876244},
{24977353, -314384, -8223969, -13465086, 28432343, -1176353,
-13068804, -12297348, -22380984, 6618999},
{-1538174, 11685646, 12944378, 13682314, -24389511, -14413193,
8044829, -13817328, 32239829, -5652762},
},
{
{-18603066, 4762990, -926250, 8885304, -28412480, -3187315, 9781647,
-10350059, 32779359, 5095274},
{-33008130, -5214506, -32264887, -3685216, 9460461, -9327423,
-24601656, 14506724, 21639561, -2630236},
{-16400943, -13112215, 25239338, 15531969, 3987758, -4499318,
-1289502, -6863535, 17874574, 558605},
},
{
{-13600129, 10240081, 9171883, 16131053, -20869254, 9599700,
33499487, 5080151, 2085892, 5119761},
{-22205145, -2519528, -16381601, 414691, -25019550, 2170430,
30634760, -8363614, -31999993, -5759884},
{-6845704, 15791202, 8550074, -1312654, 29928809, -12092256,
27534430, -7192145, -22351378, 12961482},
},
{
{-24492060, -9570771, 10368194, 11582341, -23397293, -2245287,
16533930, 8206996, -30194652, -5159638},
{-11121496, -3382234, 2307366, 6362031, -135455, 8868177, -16835630,
7031275, 7589640, 8945490},
{-32152748, 8917967, 6661220, -11677616, -1192060, -15793393,
7251489, -11182180, 24099109, -14456170},
},
{
{5019558, -7907470, 4244127, -14714356, -26933272, 6453165,
-19118182, -13289025, -6231896, -10280736},
{10853594, 10721687, 26480089, 5861829, -22995819, 1972175,
-1866647, -10557898, -3363451, -6441124},
{-17002408, 5906790, 221599, -6563147, 7828208, -13248918, 24362661,
-2008168, -13866408, 7421392},
},
{
{8139927, -6546497, 32257646, -5890546, 30375719, 1886181,
-21175108, 15441252, 28826358, -4123029},
{6267086, 9695052, 7709135, -16603597, -32869068, -1886135,
14795160, -7840124, 13746021, -1742048},
{28584902, 7787108, -6732942, -15050729, 22846041, -7571236,
-3181936, -363524, 4771362, -8419958},
},
},
{
{
{24949256, 6376279, -27466481, -8174608, -18646154, -9930606,
33543569, -12141695, 3569627, 11342593},
{26514989, 4740088, 27912651, 3697550, 19331575, -11472339, 6809886,
4608608, 7325975, -14801071},
{-11618399, -14554430, -24321212, 7655128, -1369274, 5214312,
-27400540, 10258390, -17646694, -8186692},
},
{
{11431204, 15823007, 26570245, 14329124, 18029990, 4796082,
-31446179, 15580664, 9280358, -3973687},
{-160783, -10326257, -22855316, -4304997, -20861367, -13621002,
-32810901, -11181622, -15545091, 4387441},
{-20799378, 12194512, 3937617, -5805892, -27154820, 9340370,
-24513992, 8548137, 20617071, -7482001},
},
{
{-938825, -3930586, -8714311, 16124718, 24603125, -6225393,
-13775352, -11875822, 24345683, 10325460},
{-19855277, -1568885, -22202708, 8714034, 14007766, 6928528,
16318175, -1010689, 4766743, 3552007},
{-21751364, -16730916, 1351763, -803421, -4009670, 3950935, 3217514,
14481909, 10988822, -3994762},
},
{
{15564307, -14311570, 3101243, 5684148, 30446780, -8051356,
12677127, -6505343, -8295852, 13296005},
{-9442290, 6624296, -30298964, -11913677, -4670981, -2057379,
31521204, 9614054, -30000824, 12074674},
{4771191, -135239, 14290749, -13089852, 27992298, 14998318,
-1413936, -1556716, 29832613, -16391035},
},
{
{7064884, -7541174, -19161962, -5067537, -18891269, -2912736,
25825242, 5293297, -27122660, 13101590},
{-2298563, 2439670, -7466610, 1719965, -27267541, -16328445,
32512469, -5317593, -30356070, -4190957},
{-30006540, 10162316, -33180176, 3981723, -16482138, -13070044,
14413974, 9515896, 19568978, 9628812},
},
{
{33053803, 199357, 15894591, 1583059, 27380243, -4580435, -17838894,
-6106839, -6291786, 3437740},
{-18978877, 3884493, 19469877, 12726490, 15913552, 13614290,
-22961733, 70104, 7463304, 4176122},
{-27124001, 10659917, 11482427, -16070381, 12771467, -6635117,
-32719404, -5322751, 24216882, 5944158},
},
{
{8894125, 7450974, -2664149, -9765752, -28080517, -12389115,
19345746, 14680796, 11632993, 5847885},
{26942781, -2315317, 9129564, -4906607, 26024105, 11769399,
-11518837, 6367194, -9727230, 4782140},
{19916461, -4828410, -22910704, -11414391, 25606324, -5972441,
33253853, 8220911, 6358847, -1873857},
},
{
{801428, -2081702, 16569428, 11065167, 29875704, 96627, 7908388,
-4480480, -13538503, 1387155},
{19646058, 5720633, -11416706, 12814209, 11607948, 12749789,
14147075, 15156355, -21866831, 11835260},
{19299512, 1155910, 28703737, 14890794, 2925026, 7269399, 26121523,
15467869, -26560550, 5052483},
},
},
{
{
{-3017432, 10058206, 1980837, 3964243, 22160966, 12322533, -6431123,
-12618185, 12228557, -7003677},
{32944382, 14922211, -22844894, 5188528, 21913450, -8719943,
4001465, 13238564, -6114803, 8653815},
{22865569, -4652735, 27603668, -12545395, 14348958, 8234005,
24808405, 5719875, 28483275, 2841751},
},
{
{-16420968, -1113305, -327719, -12107856, 21886282, -15552774,
-1887966, -315658, 19932058, -12739203},
{-11656086, 10087521, -8864888, -5536143, -19278573, -3055912,
3999228, 13239134, -4777469, -13910208},
{1382174, -11694719, 17266790, 9194690, -13324356, 9720081,
20403944, 11284705, -14013818, 3093230},
},
{
{16650921, -11037932, -1064178, 1570629, -8329746, 7352753, -302424,
16271225, -24049421, -6691850},
{-21911077, -5927941, -4611316, -5560156, -31744103, -10785293,
24123614, 15193618, -21652117, -16739389},
{-9935934, -4289447, -25279823, 4372842, 2087473, 10399484,
31870908, 14690798, 17361620, 11864968},
},
{
{-11307610, 6210372, 13206574, 5806320, -29017692, -13967200,
-12331205, -7486601, -25578460, -16240689},
{14668462, -12270235, 26039039, 15305210, 25515617, 4542480,
10453892, 6577524, 9145645, -6443880},
{5974874, 3053895, -9433049, -10385191, -31865124, 3225009,
-7972642, 3936128, -5652273, -3050304},
},
{
{30625386, -4729400, -25555961, -12792866, -20484575, 7695099,
17097188, -16303496, -27999779, 1803632},
{-3553091, 9865099, -5228566, 4272701, -5673832, -16689700,
14911344, 12196514, -21405489, 7047412},
{20093277, 9920966, -11138194, -5343857, 13161587, 12044805,
-32856851, 4124601, -32343828, -10257566},
},
{
{-20788824, 14084654, -13531713, 7842147, 19119038, -13822605,
4752377, -8714640, -21679658, 2288038},
{-26819236, -3283715, 29965059, 3039786, -14473765, 2540457,
29457502, 14625692, -24819617, 12570232},
{-1063558, -11551823, 16920318, 12494842, 1278292, -5869109,
-21159943, -3498680, -11974704, 4724943},
},
{
{17960970, -11775534, -4140968, -9702530, -8876562, -1410617,
-12907383, -8659932, -29576300, 1903856},
{23134274, -14279132, -10681997, -1611936, 20684485, 15770816,
-12989750, 3190296, 26955097, 14109738},
{15308788, 5320727, -30113809, -14318877, 22902008, 7767164,
29425325, -11277562, 31960942, 11934971},
},
{
{-27395711, 8435796, 4109644, 12222639, -24627868, 14818669,
20638173, 4875028, 10491392, 1379718},
{-13159415, 9197841, 3875503, -8936108, -1383712, -5879801,
33518459, 16176658, 21432314, 12180697},
{-11787308, 11500838, 13787581, -13832590, -22430679, 10140205,
1465425, 12689540, -10301319, -13872883},
},
},
{
{
{5414091, -15386041, -21007664, 9643570, 12834970, 1186149,
-2622916, -1342231, 26128231, 6032912},
{-26337395, -13766162, 32496025, -13653919, 17847801, -12669156,
3604025, 8316894, -25875034, -10437358},
{3296484, 6223048, 24680646, -12246460, -23052020, 5903205,
-8862297, -4639164, 12376617, 3188849},
},
{
{29190488, -14659046, 27549113, -1183516, 3520066, -10697301,
32049515, -7309113, -16109234, -9852307},
{-14744486, -9309156, 735818, -598978, -20407687, -5057904,
25246078, -15795669, 18640741, -960977},
{-6928835, -16430795, 10361374, 5642961, 4910474, 12345252,
-31638386, -494430, 10530747, 1053335},
},
{
{-29265967, -14186805, -13538216, -12117373, -19457059, -10655384,
-31462369, -2948985, 24018831, 15026644},
{-22592535, -3145277, -2289276, 5953843, -13440189, 9425631,
25310643, 13003497, -2314791, -15145616},
{-27419985, -603321, -8043984, -1669117, -26092265, 13987819,
-27297622, 187899, -23166419, -2531735},
},
{
{-21744398, -13810475, 1844840, 5021428, -10434399, -15911473,
9716667, 16266922, -5070217, 726099},
{29370922, -6053998, 7334071, -15342259, 9385287, 2247707,
-13661962, -4839461, 30007388, -15823341},
{-936379, 16086691, 23751945, -543318, -1167538, -5189036, 9137109,
730663, 9835848, 4555336},
},
{
{-23376435, 1410446, -22253753, -12899614, 30867635, 15826977,
17693930, 544696, -11985298, 12422646},
{31117226, -12215734, -13502838, 6561947, -9876867, -12757670,
-5118685, -4096706, 29120153, 13924425},
{-17400879, -14233209, 19675799, -2734756, -11006962, -5858820,
-9383939, -11317700, 7240931, -237388},
},
{
{-31361739, -11346780, -15007447, -5856218, -22453340, -12152771,
1222336, 4389483, 3293637, -15551743},
{-16684801, -14444245, 11038544, 11054958, -13801175, -3338533,
-24319580, 7733547, 12796905, -6335822},
{-8759414, -10817836, -25418864, 10783769, -30615557, -9746811,
-28253339, 3647836, 3222231, -11160462},
},
{
{18606113, 1693100, -25448386, -15170272, 4112353, 10045021,
23603893, -2048234, -7550776, 2484985},
{9255317, -3131197, -12156162, -1004256, 13098013, -9214866,
16377220, -2102812, -19802075, -3034702},
{-22729289, 7496160, -5742199, 11329249, 19991973, -3347502,
-31718148, 9936966, -30097688, -10618797},
},
{
{21878590, -5001297, 4338336, 13643897, -3036865, 13160960,
19708896, 5415497, -7360503, -4109293},
{27736861, 10103576, 12500508, 8502413, -3413016, -9633558,
10436918, -1550276, -23659143, -8132100},
{19492550, -12104365, -29681976, -852630, -3208171, 12403437,
30066266, 8367329, 13243957, 8709688},
},
},
{
{
{12015105, 2801261, 28198131, 10151021, 24818120, -4743133,
-11194191, -5645734, 5150968, 7274186},
{2831366, -12492146, 1478975, 6122054, 23825128, -12733586,
31097299, 6083058, 31021603, -9793610},
{-2529932, -2229646, 445613, 10720828, -13849527, -11505937,
-23507731, 16354465, 15067285, -14147707},
},
{
{7840942, 14037873, -33364863, 15934016, -728213, -3642706,
21403988, 1057586, -19379462, -12403220},
{915865, -16469274, 15608285, -8789130, -24357026, 6060030,
-17371319, 8410997, -7220461, 16527025},
{32922597, -556987, 20336074, -16184568, 10903705, -5384487,
16957574, 52992, 23834301, 6588044},
},
{
{32752030, 11232950, 3381995, -8714866, 22652988, -10744103,
17159699, 16689107, -20314580, -1305992},
{-4689649, 9166776, -25710296, -10847306, 11576752, 12733943,
7924251, -2752281, 1976123, -7249027},
{21251222, 16309901, -2983015, -6783122, 30810597, 12967303, 156041,
-3371252, 12331345, -8237197},
},
{
{8651614, -4477032, -16085636, -4996994, 13002507, 2950805,
29054427, -5106970, 10008136, -4667901},
{31486080, 15114593, -14261250, 12951354, 14369431, -7387845,
16347321, -13662089, 8684155, -10532952},
{19443825, 11385320, 24468943, -9659068, -23919258, 2187569,
-26263207, -6086921, 31316348, 14219878},
},
{
{-28594490, 1193785, 32245219, 11392485, 31092169, 15722801,
27146014, 6992409, 29126555, 9207390},
{32382935, 1110093, 18477781, 11028262, -27411763, -7548111,
-4980517, 10843782, -7957600, -14435730},
{2814918, 7836403, 27519878, -7868156, -20894015, -11553689,
-21494559, 8550130, 28346258, 1994730},
},
{
{-19578299, 8085545, -14000519, -3948622, 2785838, -16231307,
-19516951, 7174894, 22628102, 8115180},
{-30405132, 955511, -11133838, -15078069, -32447087, -13278079,
-25651578, 3317160, -9943017, 930272},
{-15303681, -6833769, 28856490, 1357446, 23421993, 1057177,
24091212, -1388970, -22765376, -10650715},
},
{
{-22751231, -5303997, -12907607, -12768866, -15811511, -7797053,
-14839018, -16554220, -1867018, 8398970},
{-31969310, 2106403, -4736360, 1362501, 12813763, 16200670,
22981545, -6291273, 18009408, -15772772},
{-17220923, -9545221, -27784654, 14166835, 29815394, 7444469,
29551787, -3727419, 19288549, 1325865},
},
{
{15100157, -15835752, -23923978, -1005098, -26450192, 15509408,
12376730, -3479146, 33166107, -8042750},
{20909231, 13023121, -9209752, 16251778, -5778415, -8094914,
12412151, 10018715, 2213263, -13878373},
{32529814, -11074689, 30361439, -16689753, -9135940, 1513226,
22922121, 6382134, -5766928, 8371348},
},
},
{
{
{9923462, 11271500, 12616794, 3544722, -29998368, -1721626,
12891687, -8193132, -26442943, 10486144},
{-22597207, -7012665, 8587003, -8257861, 4084309, -12970062, 361726,
2610596, -23921530, -11455195},
{5408411, -1136691, -4969122, 10561668, 24145918, 14240566,
31319731, -4235541, 19985175, -3436086},
},
{
{-13994457, 16616821, 14549246, 3341099, 32155958, 13648976,
-17577068, 8849297, 65030, 8370684},
{-8320926, -12049626, 31204563, 5839400, -20627288, -1057277,
-19442942, 6922164, 12743482, -9800518},
{-2361371, 12678785, 28815050, 4759974, -23893047, 4884717,
23783145, 11038569, 18800704, 255233},
},
{
{-5269658, -1773886, 13957886, 7990715, 23132995, 728773, 13393847,
9066957, 19258688, -14753793},
{-2936654, -10827535, -10432089, 14516793, -3640786, 4372541,
-31934921, 2209390, -1524053, 2055794},
{580882, 16705327, 5468415, -2683018, -30926419, -14696000,
-7203346, -8994389, -30021019, 7394435},
},
{
{23838809, 1822728, -15738443, 15242727, 8318092, -3733104,
-21672180, -3492205, -4821741, 14799921},
{13345610, 9759151, 3371034, -16137791, 16353039, 8577942, 31129804,
13496856, -9056018, 7402518},
{2286874, -4435931, -20042458, -2008336, -13696227, 5038122,
11006906, -15760352, 8205061, 1607563},
},
{
{14414086, -8002132, 3331830, -3208217, 22249151, -5594188,
18364661, -2906958, 30019587, -9029278},
{-27688051, 1585953, -10775053, 931069, -29120221, -11002319,
-14410829, 12029093, 9944378, 8024},
{4368715, -3709630, 29874200, -15022983, -20230386, -11410704,
-16114594, -999085, -8142388, 5640030},
},
{
{10299610, 13746483, 11661824, 16234854, 7630238, 5998374, 9809887,
-16694564, 15219798, -14327783},
{27425505, -5719081, 3055006, 10660664, 23458024, 595578, -15398605,
-1173195, -18342183, 9742717},
{6744077, 2427284, 26042789, 2720740, -847906, 1118974, 32324614,
7406442, 12420155, 1994844},
},
{
{14012521, -5024720, -18384453, -9578469, -26485342, -3936439,
-13033478, -10909803, 24319929, -6446333},
{16412690, -4507367, 10772641, 15929391, -17068788, -4658621,
10555945, -10484049, -30102368, -4739048},
{22397382, -7767684, -9293161, -12792868, 17166287, -9755136,
-27333065, 6199366, 21880021, -12250760},
},
{
{-4283307, 5368523, -31117018, 8163389, -30323063, 3209128,
16557151, 8890729, 8840445, 4957760},
{-15447727, 709327, -6919446, -10870178, -29777922, 6522332,
-21720181, 12130072, -14796503, 5005757},
{-2114751, -14308128, 23019042, 15765735, -25269683, 6002752,
10183197, -13239326, -16395286, -2176112},
},
},
{
{
{-19025756, 1632005, 13466291, -7995100, -23640451, 16573537,
-32013908, -3057104, 22208662, 2000468},
{3065073, -1412761, -25598674, -361432, -17683065, -5703415,
-8164212, 11248527, -3691214, -7414184},
{10379208, -6045554, 8877319, 1473647, -29291284, -12507580,
16690915, 2553332, -3132688, 16400289},
},
{
{15716668, 1254266, -18472690, 7446274, -8448918, 6344164,
-22097271, -7285580, 26894937, 9132066},
{24158887, 12938817, 11085297, -8177598, -28063478, -4457083,
-30576463, 64452, -6817084, -2692882},
{13488534, 7794716, 22236231, 5989356, 25426474, -12578208, 2350710,
-3418511, -4688006, 2364226},
},
{
{16335052, 9132434, 25640582, 6678888, 1725628, 8517937, -11807024,
-11697457, 15445875, -7798101},
{29004207, -7867081, 28661402, -640412, -12794003, -7943086,
31863255, -4135540, -278050, -15759279},
{-6122061, -14866665, -28614905, 14569919, -10857999, -3591829,
10343412, -6976290, -29828287, -10815811},
},
{
{27081650, 3463984, 14099042, -4517604, 1616303, -6205604, 29542636,
15372179, 17293797, 960709},
{20263915, 11434237, -5765435, 11236810, 13505955, -10857102,
-16111345, 6493122, -19384511, 7639714},
{-2830798, -14839232, 25403038, -8215196, -8317012, -16173699,
18006287, -16043750, 29994677, -15808121},
},
{
{9769828, 5202651, -24157398, -13631392, -28051003, -11561624,
-24613141, -13860782, -31184575, 709464},
{12286395, 13076066, -21775189, -1176622, -25003198, 4057652,
-32018128, -8890874, 16102007, 13205847},
{13733362, 5599946, 10557076, 3195751, -5557991, 8536970, -25540170,
8525972, 10151379, 10394400},
},
{
{4024660, -16137551, 22436262, 12276534, -9099015, -2686099,
19698229, 11743039, -33302334, 8934414},
{-15879800, -4525240, -8580747, -2934061, 14634845, -698278,
-9449077, 3137094, -11536886, 11721158},
{17555939, -5013938, 8268606, 2331751, -22738815, 9761013, 9319229,
8835153, -9205489, -1280045},
},
{
{-461409, -7830014, 20614118, 16688288, -7514766, -4807119,
22300304, 505429, 6108462, -6183415},
{-5070281, 12367917, -30663534, 3234473, 32617080, -8422642,
29880583, -13483331, -26898490, -7867459},
{-31975283, 5726539, 26934134, 10237677, -3173717, -605053,
24199304, 3795095, 7592688, -14992079},
},
{
{21594432, -14964228, 17466408, -4077222, 32537084, 2739898,
6407723, 12018833, -28256052, 4298412},
{-20650503, -11961496, -27236275, 570498, 3767144, -1717540,
13891942, -1569194, 13717174, 10805743},
{-14676630, -15644296, 15287174, 11927123, 24177847, -8175568,
-796431, 14860609, -26938930, -5863836},
},
},
{
{
{12962541, 5311799, -10060768, 11658280, 18855286, -7954201,
13286263, -12808704, -4381056, 9882022},
{18512079, 11319350, -20123124, 15090309, 18818594, 5271736,
-22727904, 3666879, -23967430, -3299429},
{-6789020, -3146043, 16192429, 13241070, 15898607, -14206114,
-10084880, -6661110, -2403099, 5276065},
},
{
{30169808, -5317648, 26306206, -11750859, 27814964, 7069267,
7152851, 3684982, 1449224, 13082861},
{10342826, 3098505, 2119311, 193222, 25702612, 12233820, 23697382,
15056736, -21016438, -8202000},
{-33150110, 3261608, 22745853, 7948688, 19370557, -15177665,
-26171976, 6482814, -10300080, -11060101},
},
{
{32869458, -5408545, 25609743, 15678670, -10687769, -15471071,
26112421, 2521008, -22664288, 6904815},
{29506923, 4457497, 3377935, -9796444, -30510046, 12935080, 1561737,
3841096, -29003639, -6657642},
{10340844, -6630377, -18656632, -2278430, 12621151, -13339055,
30878497, -11824370, -25584551, 5181966},
},
{
{25940115, -12658025, 17324188, -10307374, -8671468, 15029094,
24396252, -16450922, -2322852, -12388574},
{-21765684, 9916823, -1300409, 4079498, -1028346, 11909559, 1782390,
12641087, 20603771, -6561742},
{-18882287, -11673380, 24849422, 11501709, 13161720, -4768874,
1925523, 11914390, 4662781, 7820689},
},
{
{12241050, -425982, 8132691, 9393934, 32846760, -1599620, 29749456,
12172924, 16136752, 15264020},
{-10349955, -14680563, -8211979, 2330220, -17662549, -14545780,
10658213, 6671822, 19012087, 3772772},
{3753511, -3421066, 10617074, 2028709, 14841030, -6721664, 28718732,
-15762884, 20527771, 12988982},
},
{
{-14822485, -5797269, -3707987, 12689773, -898983, -10914866,
-24183046, -10564943, 3299665, -12424953},
{-16777703, -15253301, -9642417, 4978983, 3308785, 8755439, 6943197,
6461331, -25583147, 8991218},
{-17226263, 1816362, -1673288, -6086439, 31783888, -8175991,
-32948145, 7417950, -30242287, 1507265},
},
{
{29692663, 6829891, -10498800, 4334896, 20945975, -11906496,
-28887608, 8209391, 14606362, -10647073},
{-3481570, 8707081, 32188102, 5672294, 22096700, 1711240, -33020695,
9761487, 4170404, -2085325},
{-11587470, 14855945, -4127778, -1531857, -26649089, 15084046,
22186522, 16002000, -14276837, -8400798},
},
{
{-4811456, 13761029, -31703877, -2483919, -3312471, 7869047,
-7113572, -9620092, 13240845, 10965870},
{-7742563, -8256762, -14768334, -13656260, -23232383, 12387166,
4498947, 14147411, 29514390, 4302863},
{-13413405, -12407859, 20757302, -13801832, 14785143, 8976368,
-5061276, -2144373, 17846988, -13971927},
},
},
{
{
{-2244452, -754728, -4597030, -1066309, -6247172, 1455299,
-21647728, -9214789, -5222701, 12650267},
{-9906797, -16070310, 21134160, 12198166, -27064575, 708126, 387813,
13770293, -19134326, 10958663},
{22470984, 12369526, 23446014, -5441109, -21520802, -9698723,
-11772496, -11574455, -25083830, 4271862},
},
{
{-25169565, -10053642, -19909332, 15361595, -5984358, 2159192,
75375, -4278529, -32526221, 8469673},
{15854970, 4148314, -8893890, 7259002, 11666551, 13824734,
-30531198, 2697372, 24154791, -9460943},
{15446137, -15806644, 29759747, 14019369, 30811221, -9610191,
-31582008, 12840104, 24913809, 9815020},
},
{
{-4709286, -5614269, -31841498, -12288893, -14443537, 10799414,
-9103676, 13438769, 18735128, 9466238},
{11933045, 9281483, 5081055, -5183824, -2628162, -4905629, -7727821,
-10896103, -22728655, 16199064},
{14576810, 379472, -26786533, -8317236, -29426508, -10812974,
-102766, 1876699, 30801119, 2164795},
},
{
{15995086, 3199873, 13672555, 13712240, -19378835, -4647646,
-13081610, -15496269, -13492807, 1268052},
{-10290614, -3659039, -3286592, 10948818, 23037027, 3794475,
-3470338, -12600221, -17055369, 3565904},
{29210088, -9419337, -5919792, -4952785, 10834811, -13327726,
-16512102, -10820713, -27162222, -14030531},
},
{
{-13161890, 15508588, 16663704, -8156150, -28349942, 9019123,
-29183421, -3769423, 2244111, -14001979},
{-5152875, -3800936, -9306475, -6071583, 16243069, 14684434,
-25673088, -16180800, 13491506, 4641841},
{10813417, 643330, -19188515, -728916, 30292062, -16600078,
27548447, -7721242, 14476989, -12767431},
},
{
{10292079, 9984945, 6481436, 8279905, -7251514, 7032743, 27282937,
-1644259, -27912810, 12651324},
{-31185513, -813383, 22271204, 11835308, 10201545, 15351028,
17099662, 3988035, 21721536, -3148940},
{10202177, -6545839, -31373232, -9574638, -32150642, -8119683,
-12906320, 3852694, 13216206, 14842320},
},
{
{-15815640, -10601066, -6538952, -7258995, -6984659, -6581778,
-31500847, 13765824, -27434397, 9900184},
{14465505, -13833331, -32133984, -14738873, -27443187, 12990492,
33046193, 15796406, -7051866, -8040114},
{30924417, -8279620, 6359016, -12816335, 16508377, 9071735,
-25488601, 15413635, 9524356, -7018878},
},
{
{12274201, -13175547, 32627641, -1785326, 6736625, 13267305,
5237659, -5109483, 15663516, 4035784},
{-2951309, 8903985, 17349946, 601635, -16432815, -4612556,
-13732739, -15889334, -22258478, 4659091},
{-16916263, -4952973, -30393711, -15158821, 20774812, 15897498,
5736189, 15026997, -2178256, -13455585},
},
},
{
{
{-8858980, -2219056, 28571666, -10155518, -474467, -10105698,
-3801496, 278095, 23440562, -290208},
{10226241, -5928702, 15139956, 120818, -14867693, 5218603, 32937275,
11551483, -16571960, -7442864},
{17932739, -12437276, -24039557, 10749060, 11316803, 7535897,
22503767, 5561594, -3646624, 3898661},
},
{
{7749907, -969567, -16339731, -16464, -25018111, 15122143, -1573531,
7152530, 21831162, 1245233},
{26958459, -14658026, 4314586, 8346991, -5677764, 11960072,
-32589295, -620035, -30402091, -16716212},
{-12165896, 9166947, 33491384, 13673479, 29787085, 13096535,
6280834, 14587357, -22338025, 13987525},
},
{
{-24349909, 7778775, 21116000, 15572597, -4833266, -5357778,
-4300898, -5124639, -7469781, -2858068},
{9681908, -6737123, -31951644, 13591838, -6883821, 386950, 31622781,
6439245, -14581012, 4091397},
{-8426427, 1470727, -28109679, -1596990, 3978627, -5123623,
-19622683, 12092163, 29077877, -14741988},
},
{
{5269168, -6859726, -13230211, -8020715, 25932563, 1763552,
-5606110, -5505881, -20017847, 2357889},
{32264008, -15407652, -5387735, -1160093, -2091322, -3946900,
23104804, -12869908, 5727338, 189038},
{14609123, -8954470, -6000566, -16622781, -14577387, -7743898,
-26745169, 10942115, -25888931, -14884697},
},
{
{20513500, 5557931, -15604613, 7829531, 26413943, -2019404,
-21378968, 7471781, 13913677, -5137875},
{-25574376, 11967826, 29233242, 12948236, -6754465, 4713227,
-8940970, 14059180, 12878652, 8511905},
{-25656801, 3393631, -2955415, -7075526, -2250709, 9366908,
-30223418, 6812974, 5568676, -3127656},
},
{
{11630004, 12144454, 2116339, 13606037, 27378885, 15676917,
-17408753, -13504373, -14395196, 8070818},
{27117696, -10007378, -31282771, -5570088, 1127282, 12772488,
-29845906, 10483306, -11552749, -1028714},
{10637467, -5688064, 5674781, 1072708, -26343588, -6982302,
-1683975, 9177853, -27493162, 15431203},
},
{
{20525145, 10892566, -12742472, 12779443, -29493034, 16150075,
-28240519, 14943142, -15056790, -7935931},
{-30024462, 5626926, -551567, -9981087, 753598, 11981191, 25244767,
-3239766, -3356550, 9594024},
{-23752644, 2636870, -5163910, -10103818, 585134, 7877383, 11345683,
-6492290, 13352335, -10977084},
},
{
{-1931799, -5407458, 3304649, -12884869, 17015806, -4877091,
-29783850, -7752482, -13215537, -319204},
{20239939, 6607058, 6203985, 3483793, -18386976, -779229, -20723742,
15077870, -22750759, 14523817},
{27406042, -6041657, 27423596, -4497394, 4996214, 10002360,
-28842031, -4545494, -30172742, -4805667},
},
},
{
{
{11374242, 12660715, 17861383, -12540833, 10935568, 1099227,
-13886076, -9091740, -27727044, 11358504},
{-12730809, 10311867, 1510375, 10778093, -2119455, -9145702,
32676003, 11149336, -26123651, 4985768},
{-19096303, 341147, -6197485, -239033, 15756973, -8796662, -983043,
13794114, -19414307, -15621255},
},
{
{6490081, 11940286, 25495923, -7726360, 8668373, -8751316, 3367603,
6970005, -1691065, -9004790},
{1656497, 13457317, 15370807, 6364910, 13605745, 8362338, -19174622,
-5475723, -16796596, -5031438},
{-22273315, -13524424, -64685, -4334223, -18605636, -10921968,
-20571065, -7007978, -99853, -10237333},
},
{
{17747465, 10039260, 19368299, -4050591, -20630635, -16041286,
31992683, -15857976, -29260363, -5511971},
{31932027, -4986141, -19612382, 16366580, 22023614, 88450, 11371999,
-3744247, 4882242, -10626905},
{29796507, 37186, 19818052, 10115756, -11829032, 3352736, 18551198,
3272828, -5190932, -4162409},
},
{
{12501286, 4044383, -8612957, -13392385, -32430052, 5136599,
-19230378, -3529697, 330070, -3659409},
{6384877, 2899513, 17807477, 7663917, -2358888, 12363165, 25366522,
-8573892, -271295, 12071499},
{-8365515, -4042521, 25133448, -4517355, -6211027, 2265927,
-32769618, 1936675, -5159697, 3829363},
},
{
{28425966, -5835433, -577090, -4697198, -14217555, 6870930, 7921550,
-6567787, 26333140, 14267664},
{-11067219, 11871231, 27385719, -10559544, -4585914, -11189312,
10004786, -8709488, -21761224, 8930324},
{-21197785, -16396035, 25654216, -1725397, 12282012, 11008919,
1541940, 4757911, -26491501, -16408940},
},
{
{13537262, -7759490, -20604840, 10961927, -5922820, -13218065,
-13156584, 6217254, -15943699, 13814990},
{-17422573, 15157790, 18705543, 29619, 24409717, -260476, 27361681,
9257833, -1956526, -1776914},
{-25045300, -10191966, 15366585, 15166509, -13105086, 8423556,
-29171540, 12361135, -18685978, 4578290},
},
{
{24579768, 3711570, 1342322, -11180126, -27005135, 14124956,
-22544529, 14074919, 21964432, 8235257},
{-6528613, -2411497, 9442966, -5925588, 12025640, -1487420,
-2981514, -1669206, 13006806, 2355433},
{-16304899, -13605259, -6632427, -5142349, 16974359, -10911083,
27202044, 1719366, 1141648, -12796236},
},
{
{-12863944, -13219986, -8318266, -11018091, -6810145, -4843894,
13475066, -3133972, 32674895, 13715045},
{11423335, -5468059, 32344216, 8962751, 24989809, 9241752,
-13265253, 16086212, -28740881, -15642093},
{-1409668, 12530728, -6368726, 10847387, 19531186, -14132160,
-11709148, 7791794, -27245943, 4383347},
},
},
{
{
{-28970898, 5271447, -1266009, -9736989, -12455236, 16732599,
-4862407, -4906449, 27193557, 6245191},
{-15193956, 5362278, -1783893, 2695834, 4960227, 12840725, 23061898,
3260492, 22510453, 8577507},
{-12632451, 11257346, -32692994, 13548177, -721004, 10879011,
31168030, 13952092, -29571492, -3635906},
},
{
{3877321, -9572739, 32416692, 5405324, -11004407, -13656635,
3759769, 11935320, 5611860, 8164018},
{-16275802, 14667797, 15906460, 12155291, -22111149, -9039718,
32003002, -8832289, 5773085, -8422109},
{-23788118, -8254300, 1950875, 8937633, 18686727, 16459170, -905725,
12376320, 31632953, 190926},
},
{
{-24593607, -16138885, -8423991, 13378746, 14162407, 6901328,
-8288749, 4508564, -25341555, -3627528},
{8884438, -5884009, 6023974, 10104341, -6881569, -4941533, 18722941,
-14786005, -1672488, 827625},
{-32720583, -16289296, -32503547, 7101210, 13354605, 2659080,
-1800575, -14108036, -24878478, 1541286},
},
{
{2901347, -1117687, 3880376, -10059388, -17620940, -3612781,
-21802117, -3567481, 20456845, -1885033},
{27019610, 12299467, -13658288, -1603234, -12861660, -4861471,
-19540150, -5016058, 29439641, 15138866},
{21536104, -6626420, -32447818, -10690208, -22408077, 5175814,
-5420040, -16361163, 7779328, 109896},
},
{
{30279744, 14648750, -8044871, 6425558, 13639621, -743509, 28698390,
12180118, 23177719, -554075},
{26572847, 3405927, -31701700, 12890905, -19265668, 5335866,
-6493768, 2378492, 4439158, -13279347},
{-22716706, 3489070, -9225266, -332753, 18875722, -1140095,
14819434, -12731527, -17717757, -5461437},
},
{
{-5056483, 16566551, 15953661, 3767752, -10436499, 15627060,
-820954, 2177225, 8550082, -15114165},
{-18473302, 16596775, -381660, 15663611, 22860960, 15585581,
-27844109, -3582739, -23260460, -8428588},
{-32480551, 15707275, -8205912, -5652081, 29464558, 2713815,
-22725137, 15860482, -21902570, 1494193},
},
{
{-19562091, -14087393, -25583872, -9299552, 13127842, 759709,
21923482, 16529112, 8742704, 12967017},
{-28464899, 1553205, 32536856, -10473729, -24691605, -406174,
-8914625, -2933896, -29903758, 15553883},
{21877909, 3230008, 9881174, 10539357, -4797115, 2841332, 11543572,
14513274, 19375923, -12647961},
},
{
{8832269, -14495485, 13253511, 5137575, 5037871, 4078777, 24880818,
-6222716, 2862653, 9455043},
{29306751, 5123106, 20245049, -14149889, 9592566, 8447059, -2077124,
-2990080, 15511449, 4789663},
{-20679756, 7004547, 8824831, -9434977, -4045704, -3750736,
-5754762, 108893, 23513200, 16652362},
},
},
{
{
{-33256173, 4144782, -4476029, -6579123, 10770039, -7155542,
-6650416, -12936300, -18319198, 10212860},
{2756081, 8598110, 7383731, -6859892, 22312759, -1105012, 21179801,
2600940, -9988298, -12506466},
{-24645692, 13317462, -30449259, -15653928, 21365574, -10869657,
11344424, 864440, -2499677, -16710063},
},
{
{-26432803, 6148329, -17184412, -14474154, 18782929, -275997,
-22561534, 211300, 2719757, 4940997},
{-1323882, 3911313, -6948744, 14759765, -30027150, 7851207,
21690126, 8518463, 26699843, 5276295},
{-13149873, -6429067, 9396249, 365013, 24703301, -10488939, 1321586,
149635, -15452774, 7159369},
},
{
{9987780, -3404759, 17507962, 9505530, 9731535, -2165514, 22356009,
8312176, 22477218, -8403385},
{18155857, -16504990, 19744716, 9006923, 15154154, -10538976,
24256460, -4864995, -22548173, 9334109},
{2986088, -4911893, 10776628, -3473844, 10620590, -7083203,
-21413845, 14253545, -22587149, 536906},
},
{
{4377756, 8115836, 24567078, 15495314, 11625074, 13064599, 7390551,
10589625, 10838060, -15420424},
{-19342404, 867880, 9277171, -3218459, -14431572, -1986443,
19295826, -15796950, 6378260, 699185},
{7895026, 4057113, -7081772, -13077756, -17886831, -323126, -716039,
15693155, -5045064, -13373962},
},
{
{-7737563, -5869402, -14566319, -7406919, 11385654, 13201616,
31730678, -10962840, -3918636, -9669325},
{10188286, -15770834, -7336361, 13427543, 22223443, 14896287,
30743455, 7116568, -21786507, 5427593},
{696102, 13206899, 27047647, -10632082, 15285305, -9853179,
10798490, -4578720, 19236243, 12477404},
},
{
{-11229439, 11243796, -17054270, -8040865, -788228, -8167967,
-3897669, 11180504, -23169516, 7733644},
{17800790, -14036179, -27000429, -11766671, 23887827, 3149671,
23466177, -10538171, 10322027, 15313801},
{26246234, 11968874, 32263343, -5468728, 6830755, -13323031,
-15794704, -101982, -24449242, 10890804},
},
{
{-31365647, 10271363, -12660625, -6267268, 16690207, -13062544,
-14982212, 16484931, 25180797, -5334884},
{-586574, 10376444, -32586414, -11286356, 19801893, 10997610,
2276632, 9482883, 316878, 13820577},
{-9882808, -4510367, -2115506, 16457136, -11100081, 11674996,
30756178, -7515054, 30696930, -3712849},
},
{
{32988917, -9603412, 12499366, 7910787, -10617257, -11931514,
-7342816, -9985397, -32349517, 7392473},
{-8855661, 15927861, 9866406, -3649411, -2396914, -16655781,
-30409476, -9134995, 25112947, -2926644},
{-2504044, -436966, 25621774, -5678772, 15085042, -5479877,
-24884878, -13526194, 5537438, -13914319},
},
},
{
{
{-11225584, 2320285, -9584280, 10149187, -33444663, 5808648,
-14876251, -1729667, 31234590, 6090599},
{-9633316, 116426, 26083934, 2897444, -6364437, -2688086, 609721,
15878753, -6970405, -9034768},
{-27757857, 247744, -15194774, -9002551, 23288161, -10011936,
-23869595, 6503646, 20650474, 1804084},
},
{
{-27589786, 15456424, 8972517, 8469608, 15640622, 4439847, 3121995,
-10329713, 27842616, -202328},
{-15306973, 2839644, 22530074, 10026331, 4602058, 5048462, 28248656,
5031932, -11375082, 12714369},
{20807691, -7270825, 29286141, 11421711, -27876523, -13868230,
-21227475, 1035546, -19733229, 12796920},
},
{
{12076899, -14301286, -8785001, -11848922, -25012791, 16400684,
-17591495, -12899438, 3480665, -15182815},
{-32361549, 5457597, 28548107, 7833186, 7303070, -11953545,
-24363064, -15921875, -33374054, 2771025},
{-21389266, 421932, 26597266, 6860826, 22486084, -6737172,
-17137485, -4210226, -24552282, 15673397},
},
{
{-20184622, 2338216, 19788685, -9620956, -4001265, -8740893,
-20271184, 4733254, 3727144, -12934448},
{6120119, 814863, -11794402, -622716, 6812205, -15747771, 2019594,
7975683, 31123697, -10958981},
{30069250, -11435332, 30434654, 2958439, 18399564, -976289,
12296869, 9204260, -16432438, 9648165},
},
{
{32705432, -1550977, 30705658, 7451065, -11805606, 9631813, 3305266,
5248604, -26008332, -11377501},
{17219865, 2375039, -31570947, -5575615, -19459679, 9219903, 294711,
15298639, 2662509, -16297073},
{-1172927, -7558695, -4366770, -4287744, -21346413, -8434326,
32087529, -1222777, 32247248, -14389861},
},
{
{14312628, 1221556, 17395390, -8700143, -4945741, -8684635,
-28197744, -9637817, -16027623, -13378845},
{-1428825, -9678990, -9235681, 6549687, -7383069, -468664, 23046502,
9803137, 17597934, 2346211},
{18510800, 15337574, 26171504, 981392, -22241552, 7827556,
-23491134, -11323352, 3059833, -11782870},
},
{
{10141598, 6082907, 17829293, -1947643, 9830092, 13613136,
-25556636, -5544586, -33502212, 3592096},
{33114168, -15889352, -26525686, -13343397, 33076705, 8716171,
1151462, 1521897, -982665, -6837803},
{-32939165, -4255815, 23947181, -324178, -33072974, -12305637,
-16637686, 3891704, 26353178, 693168},
},
{
{30374239, 1595580, -16884039, 13186931, 4600344, 406904, 9585294,
-400668, 31375464, 14369965},
{-14370654, -7772529, 1510301, 6434173, -18784789, -6262728,
32732230, -13108839, 17901441, 16011505},
{18171223, -11934626, -12500402, 15197122, -11038147, -15230035,
-19172240, -16046376, 8764035, 12309598},
},
},
{
{
{5975908, -5243188, -19459362, -9681747, -11541277, 14015782,
-23665757, 1228319, 17544096, -10593782},
{5811932, -1715293, 3442887, -2269310, -18367348, -8359541,
-18044043, -15410127, -5565381, 12348900},
{-31399660, 11407555, 25755363, 6891399, -3256938, 14872274,
-24849353, 8141295, -10632534, -585479},
},
{
{-12675304, 694026, -5076145, 13300344, 14015258, -14451394,
-9698672, -11329050, 30944593, 1130208},
{8247766, -6710942, -26562381, -7709309, -14401939, -14648910,
4652152, 2488540, 23550156, -271232},
{17294316, -3788438, 7026748, 15626851, 22990044, 113481, 2267737,
-5908146, -408818, -137719},
},
{
{16091085, -16253926, 18599252, 7340678, 2137637, -1221657,
-3364161, 14550936, 3260525, -7166271},
{-4910104, -13332887, 18550887, 10864893, -16459325, -7291596,
-23028869, -13204905, -12748722, 2701326},
{-8574695, 16099415, 4629974, -16340524, -20786213, -6005432,
-10018363, 9276971, 11329923, 1862132},
},
{
{14763076, -15903608, -30918270, 3689867, 3511892, 10313526,
-21951088, 12219231, -9037963, -940300},
{8894987, -3446094, 6150753, 3013931, 301220, 15693451, -31981216,
-2909717, -15438168, 11595570},
{15214962, 3537601, -26238722, -14058872, 4418657, -15230761,
13947276, 10730794, -13489462, -4363670},
},
{
{-2538306, 7682793, 32759013, 263109, -29984731, -7955452,
-22332124, -10188635, 977108, 699994},
{-12466472, 4195084, -9211532, 550904, -15565337, 12917920,
19118110, -439841, -30534533, -14337913},
{31788461, -14507657, 4799989, 7372237, 8808585, -14747943, 9408237,
-10051775, 12493932, -5409317},
},
{
{-25680606, 5260744, -19235809, -6284470, -3695942, 16566087,
27218280, 2607121, 29375955, 6024730},
{842132, -2794693, -4763381, -8722815, 26332018, -12405641,
11831880, 6985184, -9940361, 2854096},
{-4847262, -7969331, 2516242, -5847713, 9695691, -7221186, 16512645,
960770, 12121869, 16648078},
},
{
{-15218652, 14667096, -13336229, 2013717, 30598287, -464137,
-31504922, -7882064, 20237806, 2838411},
{-19288047, 4453152, 15298546, -16178388, 22115043, -15972604,
12544294, -13470457, 1068881, -12499905},
{-9558883, -16518835, 33238498, 13506958, 30505848, -1114596,
-8486907, -2630053, 12521378, 4845654},
},
{
{-28198521, 10744108, -2958380, 10199664, 7759311, -13088600,
3409348, -873400, -6482306, -12885870},
{-23561822, 6230156, -20382013, 10655314, -24040585, -11621172,
10477734, -1240216, -3113227, 13974498},
{12966261, 15550616, -32038948, -1615346, 21025980, -629444,
5642325, 7188737, 18895762, 12629579},
},
},
{
{
{14741879, -14946887, 22177208, -11721237, 1279741, 8058600,
11758140, 789443, 32195181, 3895677},
{10758205, 15755439, -4509950, 9243698, -4879422, 6879879, -2204575,
-3566119, -8982069, 4429647},
{-2453894, 15725973, -20436342, -10410672, -5803908, -11040220,
-7135870, -11642895, 18047436, -15281743},
},
{
{-25173001, -11307165, 29759956, 11776784, -22262383, -15820455,
10993114, -12850837, -17620701, -9408468},
{21987233, 700364, -24505048, 14972008, -7774265, -5718395,
32155026, 2581431, -29958985, 8773375},
{-25568350, 454463, -13211935, 16126715, 25240068, 8594567,
20656846, 12017935, -7874389, -13920155},
},
{
{6028182, 6263078, -31011806, -11301710, -818919, 2461772,
-31841174, -5468042, -1721788, -2776725},
{-12278994, 16624277, 987579, -5922598, 32908203, 1248608, 7719845,
-4166698, 28408820, 6816612},
{-10358094, -8237829, 19549651, -12169222, 22082623, 16147817,
20613181, 13982702, -10339570, 5067943},
},
{
{-30505967, -3821767, 12074681, 13582412, -19877972, 2443951,
-19719286, 12746132, 5331210, -10105944},
{30528811, 3601899, -1957090, 4619785, -27361822, -15436388,
24180793, -12570394, 27679908, -1648928},
{9402404, -13957065, 32834043, 10838634, -26580150, -13237195,
26653274, -8685565, 22611444, -12715406},
},
{
{22190590, 1118029, 22736441, 15130463, -30460692, -5991321,
19189625, -4648942, 4854859, 6622139},
{-8310738, -2953450, -8262579, -3388049, -10401731, -271929,
13424426, -3567227, 26404409, 13001963},
{-31241838, -15415700, -2994250, 8939346, 11562230, -12840670,
-26064365, -11621720, -15405155, 11020693},
},
{
{1866042, -7949489, -7898649, -10301010, 12483315, 13477547,
3175636, -12424163, 28761762, 1406734},
{-448555, -1777666, 13018551, 3194501, -9580420, -11161737,
24760585, -4347088, 25577411, -13378680},
{-24290378, 4759345, -690653, -1852816, 2066747, 10693769,
-29595790, 9884936, -9368926, 4745410},
},
{
{-9141284, 6049714, -19531061, -4341411, -31260798, 9944276,
-15462008, -11311852, 10931924, -11931931},
{-16561513, 14112680, -8012645, 4817318, -8040464, -11414606,
-22853429, 10856641, -20470770, 13434654},
{22759489, -10073434, -16766264, -1871422, 13637442, -10168091,
1765144, -12654326, 28445307, -5364710},
},
{
{29875063, 12493613, 2795536, -3786330, 1710620, 15181182,
-10195717, -8788675, 9074234, 1167180},
{-26205683, 11014233, -9842651, -2635485, -26908120, 7532294,
-18716888, -9535498, 3843903, 9367684},
{-10969595, -6403711, 9591134, 9582310, 11349256, 108879, 16235123,
8601684, -139197, 4242895},
},
},
{
{
{22092954, -13191123, -2042793, -11968512, 32186753, -11517388,
-6574341, 2470660, -27417366, 16625501},
{-11057722, 3042016, 13770083, -9257922, 584236, -544855, -7770857,
2602725, -27351616, 14247413},
{6314175, -10264892, -32772502, 15957557, -10157730, 168750,
-8618807, 14290061, 27108877, -1180880},
},
{
{-8586597, -7170966, 13241782, 10960156, -32991015, -13794596,
33547976, -11058889, -27148451, 981874},
{22833440, 9293594, -32649448, -13618667, -9136966, 14756819,
-22928859, -13970780, -10479804, -16197962},
{-7768587, 3326786, -28111797, 10783824, 19178761, 14905060,
22680049, 13906969, -15933690, 3797899},
},
{
{21721356, -4212746, -12206123, 9310182, -3882239, -13653110,
23740224, -2709232, 20491983, -8042152},
{9209270, -15135055, -13256557, -6167798, -731016, 15289673,
25947805, 15286587, 30997318, -6703063},
{7392032, 16618386, 23946583, -8039892, -13265164, -1533858,
-14197445, -2321576, 17649998, -250080},
},
{
{-9301088, -14193827, 30609526, -3049543, -25175069, -1283752,
-15241566, -9525724, -2233253, 7662146},
{-17558673, 1763594, -33114336, 15908610, -30040870, -12174295,
7335080, -8472199, -3174674, 3440183},
{-19889700, -5977008, -24111293, -9688870, 10799743, -16571957,
40450, -4431835, 4862400, 1133},
},
{
{-32856209, -7873957, -5422389, 14860950, -16319031, 7956142,
7258061, 311861, -30594991, -7379421},
{-3773428, -1565936, 28985340, 7499440, 24445838, 9325937, 29727763,
16527196, 18278453, 15405622},
{-4381906, 8508652, -19898366, -3674424, -5984453, 15149970,
-13313598, 843523, -21875062, 13626197},
},
{
{2281448, -13487055, -10915418, -2609910, 1879358, 16164207,
-10783882, 3953792, 13340839, 15928663},
{31727126, -7179855, -18437503, -8283652, 2875793, -16390330,
-25269894, -7014826, -23452306, 5964753},
{4100420, -5959452, -17179337, 6017714, -18705837, 12227141,
-26684835, 11344144, 2538215, -7570755},
},
{
{-9433605, 6123113, 11159803, -2156608, 30016280, 14966241,
-20474983, 1485421, -629256, -15958862},
{-26804558, 4260919, 11851389, 9658551, -32017107, 16367492,
-20205425, -13191288, 11659922, -11115118},
{26180396, 10015009, -30844224, -8581293, 5418197, 9480663, 2231568,
-10170080, 33100372, -1306171},
},
{
{15121113, -5201871, -10389905, 15427821, -27509937, -15992507,
21670947, 4486675, -5931810, -14466380},
{16166486, -9483733, -11104130, 6023908, -31926798, -1364923,
2340060, -16254968, -10735770, -10039824},
{28042865, -3557089, -12126526, 12259706, -3717498, -6945899,
6766453, -8689599, 18036436, 5803270},
},
},
{
{
{-817581, 6763912, 11803561, 1585585, 10958447, -2671165, 23855391,
4598332, -6159431, -14117438},
{-31031306, -14256194, 17332029, -2383520, 31312682, -5967183,
696309, 50292, -20095739, 11763584},
{-594563, -2514283, -32234153, 12643980, 12650761, 14811489, 665117,
-12613632, -19773211, -10713562},
},
{
{30464590, -11262872, -4127476, -12734478, 19835327, -7105613,
-24396175, 2075773, -17020157, 992471},
{18357185, -6994433, 7766382, 16342475, -29324918, 411174, 14578841,
8080033, -11574335, -10601610},
{19598397, 10334610, 12555054, 2555664, 18821899, -10339780,
21873263, 16014234, 26224780, 16452269},
},
{
{-30223925, 5145196, 5944548, 16385966, 3976735, 2009897, -11377804,
-7618186, -20533829, 3698650},
{14187449, 3448569, -10636236, -10810935, -22663880, -3433596,
7268410, -10890444, 27394301, 12015369},
{19695761, 16087646, 28032085, 12999827, 6817792, 11427614,
20244189, -1312777, -13259127, -3402461},
},
{
{30860103, 12735208, -1888245, -4699734, -16974906, 2256940,
-8166013, 12298312, -8550524, -10393462},
{-5719826, -11245325, -1910649, 15569035, 26642876, -7587760,
-5789354, -15118654, -4976164, 12651793},
{-2848395, 9953421, 11531313, -5282879, 26895123, -12697089,
-13118820, -16517902, 9768698, -2533218},
},
{
{-24719459, 1894651, -287698, -4704085, 15348719, -8156530,
32767513, 12765450, 4940095, 10678226},
{18860224, 15980149, -18987240, -1562570, -26233012, -11071856,
-7843882, 13944024, -24372348, 16582019},
{-15504260, 4970268, -29893044, 4175593, -20993212, -2199756,
-11704054, 15444560, -11003761, 7989037},
},
{
{31490452, 5568061, -2412803, 2182383, -32336847, 4531686,
-32078269, 6200206, -19686113, -14800171},
{-17308668, -15879940, -31522777, -2831, -32887382, 16375549,
8680158, -16371713, 28550068, -6857132},
{-28126887, -5688091, 16837845, -1820458, -6850681, 12700016,
-30039981, 4364038, 1155602, 5988841},
},
{
{21890435, -13272907, -12624011, 12154349, -7831873, 15300496,
23148983, -4470481, 24618407, 8283181},
{-33136107, -10512751, 9975416, 6841041, -31559793, 16356536,
3070187, -7025928, 1466169, 10740210},
{-1509399, -15488185, -13503385, -10655916, 32799044, 909394,
-13938903, -5779719, -32164649, -15327040},
},
{
{3960823, -14267803, -28026090, -15918051, -19404858, 13146868,
15567327, 951507, -3260321, -573935},
{24740841, 5052253, -30094131, 8961361, 25877428, 6165135,
-24368180, 14397372, -7380369, -6144105},
{-28888365, 3510803, -28103278, -1158478, -11238128, -10631454,
-15441463, -14453128, -1625486, -6494814},
},
},
{
{
{793299, -9230478, 8836302, -6235707, -27360908, -2369593, 33152843,
-4885251, -9906200, -621852},
{5666233, 525582, 20782575, -8038419, -24538499, 14657740, 16099374,
1468826, -6171428, -15186581},
{-4859255, -3779343, -2917758, -6748019, 7778750, 11688288,
-30404353, -9871238, -1558923, -9863646},
},
{
{10896332, -7719704, 824275, 472601, -19460308, 3009587, 25248958,
14783338, -30581476, -15757844},
{10566929, 12612572, -31944212, 11118703, -12633376, 12362879,
21752402, 8822496, 24003793, 14264025},
{27713862, -7355973, -11008240, 9227530, 27050101, 2504721,
23886875, -13117525, 13958495, -5732453},
},
{
{-23481610, 4867226, -27247128, 3900521, 29838369, -8212291,
-31889399, -10041781, 7340521, -15410068},
{4646514, -8011124, -22766023, -11532654, 23184553, 8566613,
31366726, -1381061, -15066784, -10375192},
{-17270517, 12723032, -16993061, 14878794, 21619651, -6197576,
27584817, 3093888, -8843694, 3849921},
},
{
{-9064912, 2103172, 25561640, -15125738, -5239824, 9582958,
32477045, -9017955, 5002294, -15550259},
{-12057553, -11177906, 21115585, -13365155, 8808712, -12030708,
16489530, 13378448, -25845716, 12741426},
{-5946367, 10645103, -30911586, 15390284, -3286982, -7118677,
24306472, 15852464, 28834118, -7646072},
},
{
{-17335748, -9107057, -24531279, 9434953, -8472084, -583362,
-13090771, 455841, 20461858, 5491305},
{13669248, -16095482, -12481974, -10203039, -14569770, -11893198,
-24995986, 11293807, -28588204, -9421832},
{28497928, 6272777, -33022994, 14470570, 8906179, -1225630,
18504674, -14165166, 29867745, -8795943},
},
{
{-16207023, 13517196, -27799630, -13697798, 24009064, -6373891,
-6367600, -13175392, 22853429, -4012011},
{24191378, 16712145, -13931797, 15217831, 14542237, 1646131,
18603514, -11037887, 12876623, -2112447},
{17902668, 4518229, -411702, -2829247, 26878217, 5258055, -12860753,
608397, 16031844, 3723494},
},
{
{-28632773, 12763728, -20446446, 7577504, 33001348, -13017745,
17558842, -7872890, 23896954, -4314245},
{-20005381, -12011952, 31520464, 605201, 2543521, 5991821, -2945064,
7229064, -9919646, -8826859},
{28816045, 298879, -28165016, -15920938, 19000928, -1665890,
-12680833, -2949325, -18051778, -2082915},
},
{
{16000882, -344896, 3493092, -11447198, -29504595, -13159789,
12577740, 16041268, -19715240, 7847707},
{10151868, 10572098, 27312476, 7922682, 14825339, 4723128,
-32855931, -6519018, -10020567, 3852848},
{-11430470, 15697596, -21121557, -4420647, 5386314, 15063598,
16514493, -15932110, 29330899, -15076224},
},
},
{
{
{-25499735, -4378794, -15222908, -6901211, 16615731, 2051784,
3303702, 15490, -27548796, 12314391},
{15683520, -6003043, 18109120, -9980648, 15337968, -5997823,
-16717435, 15921866, 16103996, -3731215},
{-23169824, -10781249, 13588192, -1628807, -3798557, -1074929,
-19273607, 5402699, -29815713, -9841101},
},
{
{23190676, 2384583, -32714340, 3462154, -29903655, -1529132,
-11266856, 8911517, -25205859, 2739713},
{21374101, -3554250, -33524649, 9874411, 15377179, 11831242,
-33529904, 6134907, 4931255, 11987849},
{-7732, -2978858, -16223486, 7277597, 105524, -322051, -31480539,
13861388, -30076310, 10117930},
},
{
{-29501170, -10744872, -26163768, 13051539, -25625564, 5089643,
-6325503, 6704079, 12890019, 15728940},
{-21972360, -11771379, -951059, -4418840, 14704840, 2695116, 903376,
-10428139, 12885167, 8311031},
{-17516482, 5352194, 10384213, -13811658, 7506451, 13453191,
26423267, 4384730, 1888765, -5435404},
},
{
{-25817338, -3107312, -13494599, -3182506, 30896459, -13921729,
-32251644, -12707869, -19464434, -3340243},
{-23607977, -2665774, -526091, 4651136, 5765089, 4618330, 6092245,
14845197, 17151279, -9854116},
{-24830458, -12733720, -15165978, 10367250, -29530908, -265356,
22825805, -7087279, -16866484, 16176525},
},
{
{-23583256, 6564961, 20063689, 3798228, -4740178, 7359225, 2006182,
-10363426, -28746253, -10197509},
{-10626600, -4486402, -13320562, -5125317, 3432136, -6393229,
23632037, -1940610, 32808310, 1099883},
{15030977, 5768825, -27451236, -2887299, -6427378, -15361371,
-15277896, -6809350, 2051441, -15225865},
},
{
{-3362323, -7239372, 7517890, 9824992, 23555850, 295369, 5148398,
-14154188, -22686354, 16633660},
{4577086, -16752288, 13249841, -15304328, 19958763, -14537274,
18559670, -10759549, 8402478, -9864273},
{-28406330, -1051581, -26790155, -907698, -17212414, -11030789,
9453451, -14980072, 17983010, 9967138},
},
{
{-25762494, 6524722, 26585488, 9969270, 24709298, 1220360, -1677990,
7806337, 17507396, 3651560},
{-10420457, -4118111, 14584639, 15971087, -15768321, 8861010,
26556809, -5574557, -18553322, -11357135},
{2839101, 14284142, 4029895, 3472686, 14402957, 12689363, -26642121,
8459447, -5605463, -7621941},
},
{
{-4839289, -3535444, 9744961, 2871048, 25113978, 3187018, -25110813,
-849066, 17258084, -7977739},
{18164541, -10595176, -17154882, -1542417, 19237078, -9745295,
23357533, -15217008, 26908270, 12150756},
{-30264870, -7647865, 5112249, -7036672, -1499807, -6974257, 43168,
-5537701, -32302074, 16215819},
},
},
{
{
{-6898905, 9824394, -12304779, -4401089, -31397141, -6276835,
32574489, 12532905, -7503072, -8675347},
{-27343522, -16515468, -27151524, -10722951, 946346, 16291093,
254968, 7168080, 21676107, -1943028},
{21260961, -8424752, -16831886, -11920822, -23677961, 3968121,
-3651949, -6215466, -3556191, -7913075},
},
{
{16544754, 13250366, -16804428, 15546242, -4583003, 12757258,
-2462308, -8680336, -18907032, -9662799},
{-2415239, -15577728, 18312303, 4964443, -15272530, -12653564,
26820651, 16690659, 25459437, -4564609},
{-25144690, 11425020, 28423002, -11020557, -6144921, -15826224,
9142795, -2391602, -6432418, -1644817},
},
{
{-23104652, 6253476, 16964147, -3768872, -25113972, -12296437,
-27457225, -16344658, 6335692, 7249989},
{-30333227, 13979675, 7503222, -12368314, -11956721, -4621693,
-30272269, 2682242, 25993170, -12478523},
{4364628, 5930691, 32304656, -10044554, -8054781, 15091131,
22857016, -10598955, 31820368, 15075278},
},
{
{31879134, -8918693, 17258761, 90626, -8041836, -4917709, 24162788,
-9650886, -17970238, 12833045},
{19073683, 14851414, -24403169, -11860168, 7625278, 11091125,
-19619190, 2074449, -9413939, 14905377},
{24483667, -11935567, -2518866, -11547418, -1553130, 15355506,
-25282080, 9253129, 27628530, -7555480},
},
{
{17597607, 8340603, 19355617, 552187, 26198470, -3176583, 4593324,
-9157582, -14110875, 15297016},
{510886, 14337390, -31785257, 16638632, 6328095, 2713355, -20217417,
-11864220, 8683221, 2921426},
{18606791, 11874196, 27155355, -5281482, -24031742, 6265446,
-25178240, -1278924, 4674690, 13890525},
},
{
{13609624, 13069022, -27372361, -13055908, 24360586, 9592974,
14977157, 9835105, 4389687, 288396},
{9922506, -519394, 13613107, 5883594, -18758345, -434263, -12304062,
8317628, 23388070, 16052080},
{12720016, 11937594, -31970060, -5028689, 26900120, 8561328,
-20155687, -11632979, -14754271, -10812892},
},
{
{15961858, 14150409, 26716931, -665832, -22794328, 13603569,
11829573, 7467844, -28822128, 929275},
{11038231, -11582396, -27310482, -7316562, -10498527, -16307831,
-23479533, -9371869, -21393143, 2465074},
{20017163, -4323226, 27915242, 1529148, 12396362, 15675764,
13817261, -9658066, 2463391, -4622140},
},
{
{-16358878, -12663911, -12065183, 4996454, -1256422, 1073572,
9583558, 12851107, 4003896, 12673717},
{-1731589, -15155870, -3262930, 16143082, 19294135, 13385325,
14741514, -9103726, 7903886, 2348101},
{24536016, -16515207, 12715592, -3862155, 1511293, 10047386,
-3842346, -7129159, -28377538, 10048127},
},
},
{
{
{-12622226, -6204820, 30718825, 2591312, -10617028, 12192840,
18873298, -7297090, -32297756, 15221632},
{-26478122, -11103864, 11546244, -1852483, 9180880, 7656409,
-21343950, 2095755, 29769758, 6593415},
{-31994208, -2907461, 4176912, 3264766, 12538965, -868111, 26312345,
-6118678, 30958054, 8292160},
},
{
{31429822, -13959116, 29173532, 15632448, 12174511, -2760094,
32808831, 3977186, 26143136, -3148876},
{22648901, 1402143, -22799984, 13746059, 7936347, 365344, -8668633,
-1674433, -3758243, -2304625},
{-15491917, 8012313, -2514730, -12702462, -23965846, -10254029,
-1612713, -1535569, -16664475, 8194478},
},
{
{27338066, -7507420, -7414224, 10140405, -19026427, -6589889,
27277191, 8855376, 28572286, 3005164},
{26287124, 4821776, 25476601, -4145903, -3764513, -15788984,
-18008582, 1182479, -26094821, -13079595},
{-7171154, 3178080, 23970071, 6201893, -17195577, -4489192,
-21876275, -13982627, 32208683, -1198248},
},
{
{-16657702, 2817643, -10286362, 14811298, 6024667, 13349505,
-27315504, -10497842, -27672585, -11539858},
{15941029, -9405932, -21367050, 8062055, 31876073, -238629,
-15278393, -1444429, 15397331, -4130193},
{8934485, -13485467, -23286397, -13423241, -32446090, 14047986,
31170398, -1441021, -27505566, 15087184},
},
{
{-18357243, -2156491, 24524913, -16677868, 15520427, -6360776,
-15502406, 11461896, 16788528, -5868942},
{-1947386, 16013773, 21750665, 3714552, -17401782, -16055433,
-3770287, -10323320, 31322514, -11615635},
{21426655, -5650218, -13648287, -5347537, -28812189, -4920970,
-18275391, -14621414, 13040862, -12112948},
},
{
{11293895, 12478086, -27136401, 15083750, -29307421, 14748872,
14555558, -13417103, 1613711, 4896935},
{-25894883, 15323294, -8489791, -8057900, 25967126, -13425460,
2825960, -4897045, -23971776, -11267415},
{-15924766, -5229880, -17443532, 6410664, 3622847, 10243618,
20615400, 12405433, -23753030, -8436416},
},
{
{-7091295, 12556208, -20191352, 9025187, -17072479, 4333801,
4378436, 2432030, 23097949, -566018},
{4565804, -16025654, 20084412, -7842817, 1724999, 189254, 24767264,
10103221, -18512313, 2424778},
{366633, -11976806, 8173090, -6890119, 30788634, 5745705, -7168678,
1344109, -3642553, 12412659},
},
{
{-24001791, 7690286, 14929416, -168257, -32210835, -13412986,
24162697, -15326504, -3141501, 11179385},
{18289522, -14724954, 8056945, 16430056, -21729724, 7842514,
-6001441, -1486897, -18684645, -11443503},
{476239, 6601091, -6152790, -9723375, 17503545, -4863900, 27672959,
13403813, 11052904, 5219329},
},
},
{
{
{20678546, -8375738, -32671898, 8849123, -5009758, 14574752,
31186971, -3973730, 9014762, -8579056},
{-13644050, -10350239, -15962508, 5075808, -1514661, -11534600,
-33102500, 9160280, 8473550, -3256838},
{24900749, 14435722, 17209120, -15292541, -22592275, 9878983,
-7689309, -16335821, -24568481, 11788948},
},
{
{-3118155, -11395194, -13802089, 14797441, 9652448, -6845904,
-20037437, 10410733, -24568470, -1458691},
{-15659161, 16736706, -22467150, 10215878, -9097177, 7563911,
11871841, -12505194, -18513325, 8464118},
{-23400612, 8348507, -14585951, -861714, -3950205, -6373419,
14325289, 8628612, 33313881, -8370517},
},
{
{-20186973, -4967935, 22367356, 5271547, -1097117, -4788838,
-24805667, -10236854, -8940735, -5818269},
{-6948785, -1795212, -32625683, -16021179, 32635414, -7374245,
15989197, -12838188, 28358192, -4253904},
{-23561781, -2799059, -32351682, -1661963, -9147719, 10429267,
-16637684, 4072016, -5351664, 5596589},
},
{
{-28236598, -3390048, 12312896, 6213178, 3117142, 16078565,
29266239, 2557221, 1768301, 15373193},
{-7243358, -3246960, -4593467, -7553353, -127927, -912245, -1090902,
-4504991, -24660491, 3442910},
{-30210571, 5124043, 14181784, 8197961, 18964734, -11939093,
22597931, 7176455, -18585478, 13365930},
},
{
{-7877390, -1499958, 8324673, 4690079, 6261860, 890446, 24538107,
-8570186, -9689599, -3031667},
{25008904, -10771599, -4305031, -9638010, 16265036, 15721635,
683793, -11823784, 15723479, -15163481},
{-9660625, 12374379, -27006999, -7026148, -7724114, -12314514,
11879682, 5400171, 519526, -1235876},
},
{
{22258397, -16332233, -7869817, 14613016, -22520255, -2950923,
-20353881, 7315967, 16648397, 7605640},
{-8081308, -8464597, -8223311, 9719710, 19259459, -15348212,
23994942, -5281555, -9468848, 4763278},
{-21699244, 9220969, -15730624, 1084137, -25476107, -2852390,
31088447, -7764523, -11356529, 728112},
},
{
{26047220, -11751471, -6900323, -16521798, 24092068, 9158119,
-4273545, -12555558, -29365436, -5498272},
{17510331, -322857, 5854289, 8403524, 17133918, -3112612, -28111007,
12327945, 10750447, 10014012},
{-10312768, 3936952, 9156313, -8897683, 16498692, -994647,
-27481051, -666732, 3424691, 7540221},
},
{
{30322361, -6964110, 11361005, -4143317, 7433304, 4989748, -7071422,
-16317219, -9244265, 15258046},
{13054562, -2779497, 19155474, 469045, -12482797, 4566042, 5631406,
2711395, 1062915, -5136345},
{-19240248, -11254599, -29509029, -7499965, -5835763, 13005411,
-6066489, 12194497, 32960380, 1459310},
},
},
{
{
{19852034, 7027924, 23669353, 10020366, 8586503, -6657907, 394197,
-6101885, 18638003, -11174937},
{31395534, 15098109, 26581030, 8030562, -16527914, -5007134,
9012486, -7584354, -6643087, -5442636},
{-9192165, -2347377, -1997099, 4529534, 25766844, 607986, -13222,
9677543, -32294889, -6456008},
},
{
{-2444496, -149937, 29348902, 8186665, 1873760, 12489863, -30934579,
-7839692, -7852844, -8138429},
{-15236356, -15433509, 7766470, 746860, 26346930, -10221762,
-27333451, 10754588, -9431476, 5203576},
{31834314, 14135496, -770007, 5159118, 20917671, -16768096,
-7467973, -7337524, 31809243, 7347066},
},
{
{-9606723, -11874240, 20414459, 13033986, 13716524, -11691881,
19797970, -12211255, 15192876, -2087490},
{-12663563, -2181719, 1168162, -3804809, 26747877, -14138091,
10609330, 12694420, 33473243, -13382104},
{33184999, 11180355, 15832085, -11385430, -1633671, 225884,
15089336, -11023903, -6135662, 14480053},
},
{
{31308717, -5619998, 31030840, -1897099, 15674547, -6582883,
5496208, 13685227, 27595050, 8737275},
{-20318852, -15150239, 10933843, -16178022, 8335352, -7546022,
-31008351, -12610604, 26498114, 66511},
{22644454, -8761729, -16671776, 4884562, -3105614, -13559366,
30540766, -4286747, -13327787, -7515095},
},
{
{-28017847, 9834845, 18617207, -2681312, -3401956, -13307506,
8205540, 13585437, -17127465, 15115439},
{23711543, -672915, 31206561, -8362711, 6164647, -9709987,
-33535882, -1426096, 8236921, 16492939},
{-23910559, -13515526, -26299483, -4503841, 25005590, -7687270,
19574902, 10071562, 6708380, -6222424},
},
{
{2101391, -4930054, 19702731, 2367575, -15427167, 1047675, 5301017,
9328700, 29955601, -11678310},
{3096359, 9271816, -21620864, -15521844, -14847996, -7592937,
-25892142, -12635595, -9917575, 6216608},
{-32615849, 338663, -25195611, 2510422, -29213566, -13820213,
24822830, -6146567, -26767480, 7525079},
},
{
{-23066649, -13985623, 16133487, -7896178, -3389565, 778788,
-910336, -2782495, -19386633, 11994101},
{21691500, -13624626, -641331, -14367021, 3285881, -3483596,
-25064666, 9718258, -7477437, 13381418},
{18445390, -4202236, 14979846, 11622458, -1727110, -3582980,
23111648, -6375247, 28535282, 15779576},
},
{
{30098053, 3089662, -9234387, 16662135, -21306940, 11308411,
-14068454, 12021730, 9955285, -16303356},
{9734894, -14576830, -7473633, -9138735, 2060392, 11313496,
-18426029, 9924399, 20194861, 13380996},
{-26378102, -7965207, -22167821, 15789297, -18055342, -6168792,
-1984914, 15707771, 26342023, 10146099},
},
},
{
{
{-26016874, -219943, 21339191, -41388, 19745256, -2878700,
-29637280, 2227040, 21612326, -545728},
{-13077387, 1184228, 23562814, -5970442, -20351244, -6348714,
25764461, 12243797, -20856566, 11649658},
{-10031494, 11262626, 27384172, 2271902, 26947504, -15997771, 39944,
6114064, 33514190, 2333242},
},
{
{-21433588, -12421821, 8119782, 7219913, -21830522, -9016134,
-6679750, -12670638, 24350578, -13450001},
{-4116307, -11271533, -23886186, 4843615, -30088339, 690623,
-31536088, -10406836, 8317860, 12352766},
{18200138, -14475911, -33087759, -2696619, -23702521, -9102511,
-23552096, -2287550, 20712163, 6719373},
},
{
{26656208, 6075253, -7858556, 1886072, -28344043, 4262326, 11117530,
-3763210, 26224235, -3297458},
{-17168938, -14854097, -3395676, -16369877, -19954045, 14050420,
21728352, 9493610, 18620611, -16428628},
{-13323321, 13325349, 11432106, 5964811, 18609221, 6062965,
-5269471, -9725556, -30701573, -16479657},
},
{
{-23860538, -11233159, 26961357, 1640861, -32413112, -16737940,
12248509, -5240639, 13735342, 1934062},
{25089769, 6742589, 17081145, -13406266, 21909293, -16067981,
-15136294, -3765346, -21277997, 5473616},
{31883677, -7961101, 1083432, -11572403, 22828471, 13290673,
-7125085, 12469656, 29111212, -5451014},
},
{
{24244947, -15050407, -26262976, 2791540, -14997599, 16666678,
24367466, 6388839, -10295587, 452383},
{-25640782, -3417841, 5217916, 16224624, 19987036, -4082269,
-24236251, -5915248, 15766062, 8407814},
{-20406999, 13990231, 15495425, 16395525, 5377168, 15166495,
-8917023, -4388953, -8067909, 2276718},
},
{
{30157918, 12924066, -17712050, 9245753, 19895028, 3368142,
-23827587, 5096219, 22740376, -7303417},
{2041139, -14256350, 7783687, 13876377, -25946985, -13352459,
24051124, 13742383, -15637599, 13295222},
{33338237, -8505733, 12532113, 7977527, 9106186, -1715251,
-17720195, -4612972, -4451357, -14669444},
},
{
{-20045281, 5454097, -14346548, 6447146, 28862071, 1883651,
-2469266, -4141880, 7770569, 9620597},
{23208068, 7979712, 33071466, 8149229, 1758231, -10834995, 30945528,
-1694323, -33502340, -14767970},
{1439958, -16270480, -1079989, -793782, 4625402, 10647766, -5043801,
1220118, 30494170, -11440799},
},
{
{-5037580, -13028295, -2970559, -3061767, 15640974, -6701666,
-26739026, 926050, -1684339, -13333647},
{13908495, -3549272, 30919928, -6273825, -21521863, 7989039,
9021034, 9078865, 3353509, 4033511},
{-29663431, -15113610, 32259991, -344482, 24295849, -12912123,
23161163, 8839127, 27485041, 7356032},
},
},
{
{
{9661027, 705443, 11980065, -5370154, -1628543, 14661173, -6346142,
2625015, 28431036, -16771834},
{-23839233, -8311415, -25945511, 7480958, -17681669, -8354183,
-22545972, 14150565, 15970762, 4099461},
{29262576, 16756590, 26350592, -8793563, 8529671, -11208050,
13617293, -9937143, 11465739, 8317062},
},
{
{-25493081, -6962928, 32500200, -9419051, -23038724, -2302222,
14898637, 3848455, 20969334, -5157516},
{-20384450, -14347713, -18336405, 13884722, -33039454, 2842114,
-21610826, -3649888, 11177095, 14989547},
{-24496721, -11716016, 16959896, 2278463, 12066309, 10137771,
13515641, 2581286, -28487508, 9930240},
},
{
{-17751622, -2097826, 16544300, -13009300, -15914807, -14949081,
18345767, -13403753, 16291481, -5314038},
{-33229194, 2553288, 32678213, 9875984, 8534129, 6889387, -9676774,
6957617, 4368891, 9788741},
{16660756, 7281060, -10830758, 12911820, 20108584, -8101676,
-21722536, -8613148, 16250552, -11111103},
},
{
{-19765507, 2390526, -16551031, 14161980, 1905286, 6414907, 4689584,
10604807, -30190403, 4782747},
{-1354539, 14736941, -7367442, -13292886, 7710542, -14155590,
-9981571, 4383045, 22546403, 437323},
{31665577, -12180464, -16186830, 1491339, -18368625, 3294682,
27343084, 2786261, -30633590, -14097016},
},
{
{-14467279, -683715, -33374107, 7448552, 19294360, 14334329,
-19690631, 2355319, -19284671, -6114373},
{15121312, -15796162, 6377020, -6031361, -10798111, -12957845,
18952177, 15496498, -29380133, 11754228},
{-2637277, -13483075, 8488727, -14303896, 12728761, -1622493,
7141596, 11724556, 22761615, -10134141},
},
{
{16918416, 11729663, -18083579, 3022987, -31015732, -13339659,
-28741185, -12227393, 32851222, 11717399},
{11166634, 7338049, -6722523, 4531520, -29468672, -7302055,
31474879, 3483633, -1193175, -4030831},
{-185635, 9921305, 31456609, -13536438, -12013818, 13348923,
33142652, 6546660, -19985279, -3948376},
},
{
{-32460596, 11266712, -11197107, -7899103, 31703694, 3855903,
-8537131, -12833048, -30772034, -15486313},
{-18006477, 12709068, 3991746, -6479188, -21491523, -10550425,
-31135347, -16049879, 10928917, 3011958},
{-6957757, -15594337, 31696059, 334240, 29576716, 14796075,
-30831056, -12805180, 18008031, 10258577},
},
{
{-22448644, 15655569, 7018479, -4410003, -30314266, -1201591,
-1853465, 1367120, 25127874, 6671743},
{29701166, -14373934, -10878120, 9279288, -17568, 13127210,
21382910, 11042292, 25838796, 4642684},
{-20430234, 14955537, -24126347, 8124619, -5369288, -5990470,
30468147, -13900640, 18423289, 4177476},
},
},
};
static uint8_t negative(signed char b)
{
uint32_t x = b;
x >>= 31; /* 1: yes; 0: no */
return x;
}
static void table_select(ge_precomp *t, int pos, signed char b)
{
ge_precomp minust;
uint8_t bnegative = negative(b);
uint8_t babs = b - ((uint8_t)((-bnegative) & b) << 1);
ge_precomp_0(t);
cmov(t, &k25519Precomp[pos][0], equal(babs, 1));
cmov(t, &k25519Precomp[pos][1], equal(babs, 2));
cmov(t, &k25519Precomp[pos][2], equal(babs, 3));
cmov(t, &k25519Precomp[pos][3], equal(babs, 4));
cmov(t, &k25519Precomp[pos][4], equal(babs, 5));
cmov(t, &k25519Precomp[pos][5], equal(babs, 6));
cmov(t, &k25519Precomp[pos][6], equal(babs, 7));
cmov(t, &k25519Precomp[pos][7], equal(babs, 8));
fe_copy(minust.yplusx, t->yminusx);
fe_copy(minust.yminusx, t->yplusx);
fe_neg(minust.xy2d, t->xy2d);
cmov(t, &minust, bnegative);
}
/*
* h = a * B
*
* where a = a[0]+256*a[1]+...+256^31 a[31]
* B is the Ed25519 base point (x,4/5) with x positive.
*
* Preconditions:
* a[31] <= 127
*/
static void ge_scalarmult_base(ge_p3 *h, const uint8_t *a)
{
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
/* each e[i] is between 0 and 15 */
/* e[63] is between 0 and 7 */
carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= carry << 4;
}
e[63] += carry;
/* each e[i] is between -8 and 8 */
ge_p3_0(h);
for (i = 1; i < 64; i += 2) {
table_select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
table_select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
ge_p1p1_to_p3(h, &r);
}
OPENSSL_cleanse(e, sizeof(e));
}
#if !defined(BASE_2_51_IMPLEMENTED)
/*
* Replace (f,g) with (g,f) if b == 1;
* replace (f,g) with (f,g) if b == 0.
*
* Preconditions: b in {0,1}.
*/
static void fe_cswap(fe f, fe g, unsigned int b)
{
size_t i;
b = 0-b;
for (i = 0; i < 10; i++) {
int32_t x = f[i] ^ g[i];
x &= b;
f[i] ^= x;
g[i] ^= x;
}
}
/*
* h = f * 121666
*
* Can overlap h with f.
*
* Preconditions:
* |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc.
*
* Postconditions:
* |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc.
*/
static void fe_mul121666(fe h, fe f)
{
int32_t f0 = f[0];
int32_t f1 = f[1];
int32_t f2 = f[2];
int32_t f3 = f[3];
int32_t f4 = f[4];
int32_t f5 = f[5];
int32_t f6 = f[6];
int32_t f7 = f[7];
int32_t f8 = f[8];
int32_t f9 = f[9];
int64_t h0 = f0 * (int64_t) 121666;
int64_t h1 = f1 * (int64_t) 121666;
int64_t h2 = f2 * (int64_t) 121666;
int64_t h3 = f3 * (int64_t) 121666;
int64_t h4 = f4 * (int64_t) 121666;
int64_t h5 = f5 * (int64_t) 121666;
int64_t h6 = f6 * (int64_t) 121666;
int64_t h7 = f7 * (int64_t) 121666;
int64_t h8 = f8 * (int64_t) 121666;
int64_t h9 = f9 * (int64_t) 121666;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
carry9 = h9 + (1 << 24); h0 += (carry9 >> 25) * 19; h9 -= carry9 & kTop39Bits;
carry1 = h1 + (1 << 24); h2 += carry1 >> 25; h1 -= carry1 & kTop39Bits;
carry3 = h3 + (1 << 24); h4 += carry3 >> 25; h3 -= carry3 & kTop39Bits;
carry5 = h5 + (1 << 24); h6 += carry5 >> 25; h5 -= carry5 & kTop39Bits;
carry7 = h7 + (1 << 24); h8 += carry7 >> 25; h7 -= carry7 & kTop39Bits;
carry0 = h0 + (1 << 25); h1 += carry0 >> 26; h0 -= carry0 & kTop38Bits;
carry2 = h2 + (1 << 25); h3 += carry2 >> 26; h2 -= carry2 & kTop38Bits;
carry4 = h4 + (1 << 25); h5 += carry4 >> 26; h4 -= carry4 & kTop38Bits;
carry6 = h6 + (1 << 25); h7 += carry6 >> 26; h6 -= carry6 & kTop38Bits;
carry8 = h8 + (1 << 25); h9 += carry8 >> 26; h8 -= carry8 & kTop38Bits;
h[0] = (int32_t)h0;
h[1] = (int32_t)h1;
h[2] = (int32_t)h2;
h[3] = (int32_t)h3;
h[4] = (int32_t)h4;
h[5] = (int32_t)h5;
h[6] = (int32_t)h6;
h[7] = (int32_t)h7;
h[8] = (int32_t)h8;
h[9] = (int32_t)h9;
}
static void x25519_scalar_mult_generic(uint8_t out[32],
const uint8_t scalar[32],
const uint8_t point[32]) {
fe x1, x2, z2, x3, z3, tmp0, tmp1;
uint8_t e[32];
unsigned swap = 0;
int pos;
memcpy(e, scalar, 32);
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
fe_frombytes(x1, point);
fe_1(x2);
fe_0(z2);
fe_copy(x3, x1);
fe_1(z3);
for (pos = 254; pos >= 0; --pos) {
unsigned b = 1 & (e[pos / 8] >> (pos & 7));
swap ^= b;
fe_cswap(x2, x3, swap);
fe_cswap(z2, z3, swap);
swap = b;
fe_sub(tmp0, x3, z3);
fe_sub(tmp1, x2, z2);
fe_add(x2, x2, z2);
fe_add(z2, x3, z3);
fe_mul(z3, tmp0, x2);
fe_mul(z2, z2, tmp1);
fe_sq(tmp0, tmp1);
fe_sq(tmp1, x2);
fe_add(x3, z3, z2);
fe_sub(z2, z3, z2);
fe_mul(x2, tmp1, tmp0);
fe_sub(tmp1, tmp1, tmp0);
fe_sq(z2, z2);
fe_mul121666(z3, tmp1);
fe_sq(x3, x3);
fe_add(tmp0, tmp0, z3);
fe_mul(z3, x1, z2);
fe_mul(z2, tmp1, tmp0);
}
fe_invert(z2, z2);
fe_mul(x2, x2, z2);
fe_tobytes(out, x2);
OPENSSL_cleanse(e, sizeof(e));
}
static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]) {
x25519_scalar_mult_generic(out, scalar, point);
}
#endif
static void slide(signed char *r, const uint8_t *a)
{
int i;
int b;
int k;
for (i = 0; i < 256; ++i) {
r[i] = 1 & (a[i >> 3] >> (i & 7));
}
for (i = 0; i < 256; ++i) {
if (r[i]) {
for (b = 1; b <= 6 && i + b < 256; ++b) {
if (r[i + b]) {
if (r[i] + (r[i + b] << b) <= 15) {
r[i] += r[i + b] << b;
r[i + b] = 0;
} else if (r[i] - (r[i + b] << b) >= -15) {
r[i] -= r[i + b] << b;
for (k = i + b; k < 256; ++k) {
if (!r[k]) {
r[k] = 1;
break;
}
r[k] = 0;
}
} else {
break;
}
}
}
}
}
}
static const ge_precomp Bi[8] = {
{
{25967493, -14356035, 29566456, 3660896, -12694345, 4014787, 27544626,
-11754271, -6079156, 2047605},
{-12545711, 934262, -2722910, 3049990, -727428, 9406986, 12720692,
5043384, 19500929, -15469378},
{-8738181, 4489570, 9688441, -14785194, 10184609, -12363380, 29287919,
11864899, -24514362, -4438546},
},
{
{15636291, -9688557, 24204773, -7912398, 616977, -16685262, 27787600,
-14772189, 28944400, -1550024},
{16568933, 4717097, -11556148, -1102322, 15682896, -11807043, 16354577,
-11775962, 7689662, 11199574},
{30464156, -5976125, -11779434, -15670865, 23220365, 15915852, 7512774,
10017326, -17749093, -9920357},
},
{
{10861363, 11473154, 27284546, 1981175, -30064349, 12577861, 32867885,
14515107, -15438304, 10819380},
{4708026, 6336745, 20377586, 9066809, -11272109, 6594696, -25653668,
12483688, -12668491, 5581306},
{19563160, 16186464, -29386857, 4097519, 10237984, -4348115, 28542350,
13850243, -23678021, -15815942},
},
{
{5153746, 9909285, 1723747, -2777874, 30523605, 5516873, 19480852,
5230134, -23952439, -15175766},
{-30269007, -3463509, 7665486, 10083793, 28475525, 1649722, 20654025,
16520125, 30598449, 7715701},
{28881845, 14381568, 9657904, 3680757, -20181635, 7843316, -31400660,
1370708, 29794553, -1409300},
},
{
{-22518993, -6692182, 14201702, -8745502, -23510406, 8844726, 18474211,
-1361450, -13062696, 13821877},
{-6455177, -7839871, 3374702, -4740862, -27098617, -10571707, 31655028,
-7212327, 18853322, -14220951},
{4566830, -12963868, -28974889, -12240689, -7602672, -2830569, -8514358,
-10431137, 2207753, -3209784},
},
{
{-25154831, -4185821, 29681144, 7868801, -6854661, -9423865, -12437364,
-663000, -31111463, -16132436},
{25576264, -2703214, 7349804, -11814844, 16472782, 9300885, 3844789,
15725684, 171356, 6466918},
{23103977, 13316479, 9739013, -16149481, 817875, -15038942, 8965339,
-14088058, -30714912, 16193877},
},
{
{-33521811, 3180713, -2394130, 14003687, -16903474, -16270840, 17238398,
4729455, -18074513, 9256800},
{-25182317, -4174131, 32336398, 5036987, -21236817, 11360617, 22616405,
9761698, -19827198, 630305},
{-13720693, 2639453, -24237460, -7406481, 9494427, -5774029, -6554551,
-15960994, -2449256, -14291300},
},
{
{-3151181, -5046075, 9282714, 6866145, -31907062, -863023, -18940575,
15033784, 25105118, -7894876},
{-24326370, 15950226, -31801215, -14592823, -11662737, -5090925,
1573892, -2625887, 2198790, -15804619},
{-3099351, 10324967, -2241613, 7453183, -5446979, -2735503, -13812022,
-16236442, -32461234, -12290683},
},
};
/*
* r = a * A + b * B
*
* where a = a[0]+256*a[1]+...+256^31 a[31].
* and b = b[0]+256*b[1]+...+256^31 b[31].
* B is the Ed25519 base point (x,4/5) with x positive.
*/
static void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
const ge_p3 *A, const uint8_t *b)
{
signed char aslide[256];
signed char bslide[256];
ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
ge_p1p1 t;
ge_p3 u;
ge_p3 A2;
int i;
slide(aslide, a);
slide(bslide, b);
ge_p3_to_cached(&Ai[0], A);
ge_p3_dbl(&t, A);
ge_p1p1_to_p3(&A2, &t);
ge_add(&t, &A2, &Ai[0]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[1], &u);
ge_add(&t, &A2, &Ai[1]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[2], &u);
ge_add(&t, &A2, &Ai[2]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[3], &u);
ge_add(&t, &A2, &Ai[3]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[4], &u);
ge_add(&t, &A2, &Ai[4]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[5], &u);
ge_add(&t, &A2, &Ai[5]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[6], &u);
ge_add(&t, &A2, &Ai[6]);
ge_p1p1_to_p3(&u, &t);
ge_p3_to_cached(&Ai[7], &u);
ge_p2_0(r);
for (i = 255; i >= 0; --i) {
if (aslide[i] || bslide[i]) {
break;
}
}
for (; i >= 0; --i) {
ge_p2_dbl(&t, r);
if (aslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_add(&t, &u, &Ai[aslide[i] / 2]);
} else if (aslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
}
if (bslide[i] > 0) {
ge_p1p1_to_p3(&u, &t);
ge_madd(&t, &u, &Bi[bslide[i] / 2]);
} else if (bslide[i] < 0) {
ge_p1p1_to_p3(&u, &t);
ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
}
ge_p1p1_to_p2(r, &t);
}
}
/*
* The set of scalars is \Z/l
* where l = 2^252 + 27742317777372353535851937790883648493.
*
* Input:
* s[0]+256*s[1]+...+256^63*s[63] = s
*
* Output:
* s[0]+256*s[1]+...+256^31*s[31] = s mod l
* where l = 2^252 + 27742317777372353535851937790883648493.
* Overwrites s in place.
*/
static void x25519_sc_reduce(uint8_t *s)
{
int64_t s0 = kBottom21Bits & load_3(s);
int64_t s1 = kBottom21Bits & (load_4(s + 2) >> 5);
int64_t s2 = kBottom21Bits & (load_3(s + 5) >> 2);
int64_t s3 = kBottom21Bits & (load_4(s + 7) >> 7);
int64_t s4 = kBottom21Bits & (load_4(s + 10) >> 4);
int64_t s5 = kBottom21Bits & (load_3(s + 13) >> 1);
int64_t s6 = kBottom21Bits & (load_4(s + 15) >> 6);
int64_t s7 = kBottom21Bits & (load_3(s + 18) >> 3);
int64_t s8 = kBottom21Bits & load_3(s + 21);
int64_t s9 = kBottom21Bits & (load_4(s + 23) >> 5);
int64_t s10 = kBottom21Bits & (load_3(s + 26) >> 2);
int64_t s11 = kBottom21Bits & (load_4(s + 28) >> 7);
int64_t s12 = kBottom21Bits & (load_4(s + 31) >> 4);
int64_t s13 = kBottom21Bits & (load_3(s + 34) >> 1);
int64_t s14 = kBottom21Bits & (load_4(s + 36) >> 6);
int64_t s15 = kBottom21Bits & (load_3(s + 39) >> 3);
int64_t s16 = kBottom21Bits & load_3(s + 42);
int64_t s17 = kBottom21Bits & (load_4(s + 44) >> 5);
int64_t s18 = kBottom21Bits & (load_3(s + 47) >> 2);
int64_t s19 = kBottom21Bits & (load_4(s + 49) >> 7);
int64_t s20 = kBottom21Bits & (load_4(s + 52) >> 4);
int64_t s21 = kBottom21Bits & (load_3(s + 55) >> 1);
int64_t s22 = kBottom21Bits & (load_4(s + 57) >> 6);
int64_t s23 = (load_4(s + 60) >> 3);
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
int64_t carry10;
int64_t carry11;
int64_t carry12;
int64_t carry13;
int64_t carry14;
int64_t carry15;
int64_t carry16;
s11 += s23 * 666643;
s12 += s23 * 470296;
s13 += s23 * 654183;
s14 -= s23 * 997805;
s15 += s23 * 136657;
s16 -= s23 * 683901;
s23 = 0;
s10 += s22 * 666643;
s11 += s22 * 470296;
s12 += s22 * 654183;
s13 -= s22 * 997805;
s14 += s22 * 136657;
s15 -= s22 * 683901;
s22 = 0;
s9 += s21 * 666643;
s10 += s21 * 470296;
s11 += s21 * 654183;
s12 -= s21 * 997805;
s13 += s21 * 136657;
s14 -= s21 * 683901;
s21 = 0;
s8 += s20 * 666643;
s9 += s20 * 470296;
s10 += s20 * 654183;
s11 -= s20 * 997805;
s12 += s20 * 136657;
s13 -= s20 * 683901;
s20 = 0;
s7 += s19 * 666643;
s8 += s19 * 470296;
s9 += s19 * 654183;
s10 -= s19 * 997805;
s11 += s19 * 136657;
s12 -= s19 * 683901;
s19 = 0;
s6 += s18 * 666643;
s7 += s18 * 470296;
s8 += s18 * 654183;
s9 -= s18 * 997805;
s10 += s18 * 136657;
s11 -= s18 * 683901;
s18 = 0;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 * (1 << 21);
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 * (1 << 21);
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 * (1 << 21);
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 * (1 << 21);
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 * (1 << 21);
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 * (1 << 21);
s5 += s17 * 666643;
s6 += s17 * 470296;
s7 += s17 * 654183;
s8 -= s17 * 997805;
s9 += s17 * 136657;
s10 -= s17 * 683901;
s17 = 0;
s4 += s16 * 666643;
s5 += s16 * 470296;
s6 += s16 * 654183;
s7 -= s16 * 997805;
s8 += s16 * 136657;
s9 -= s16 * 683901;
s16 = 0;
s3 += s15 * 666643;
s4 += s15 * 470296;
s5 += s15 * 654183;
s6 -= s15 * 997805;
s7 += s15 * 136657;
s8 -= s15 * 683901;
s15 = 0;
s2 += s14 * 666643;
s3 += s14 * 470296;
s4 += s14 * 654183;
s5 -= s14 * 997805;
s6 += s14 * 136657;
s7 -= s14 * 683901;
s14 = 0;
s1 += s13 * 666643;
s2 += s13 * 470296;
s3 += s13 * 654183;
s4 -= s13 * 997805;
s5 += s13 * 136657;
s6 -= s13 * 683901;
s13 = 0;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 * (1 << 21);
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 * (1 << 21);
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 * (1 << 21);
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 * (1 << 21);
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 * (1 << 21);
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 * (1 << 21);
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 * (1 << 21);
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 * (1 << 21);
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 * (1 << 21);
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 * (1 << 21);
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 * (1 << 21);
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 * (1 << 21);
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 * (1 << 21);
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
carry11 = s11 >> 21;
s12 += carry11;
s11 -= carry11 * (1 << 21);
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 * (1 << 21);
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 * (1 << 21);
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 * (1 << 21);
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 * (1 << 21);
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 * (1 << 21);
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 * (1 << 21);
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
s[ 0] = (uint8_t) (s0 >> 0);
s[ 1] = (uint8_t) (s0 >> 8);
s[ 2] = (uint8_t)((s0 >> 16) | (s1 << 5));
s[ 3] = (uint8_t) (s1 >> 3);
s[ 4] = (uint8_t) (s1 >> 11);
s[ 5] = (uint8_t)((s1 >> 19) | (s2 << 2));
s[ 6] = (uint8_t) (s2 >> 6);
s[ 7] = (uint8_t)((s2 >> 14) | (s3 << 7));
s[ 8] = (uint8_t) (s3 >> 1);
s[ 9] = (uint8_t) (s3 >> 9);
s[10] = (uint8_t)((s3 >> 17) | (s4 << 4));
s[11] = (uint8_t) (s4 >> 4);
s[12] = (uint8_t) (s4 >> 12);
s[13] = (uint8_t)((s4 >> 20) | (s5 << 1));
s[14] = (uint8_t) (s5 >> 7);
s[15] = (uint8_t)((s5 >> 15) | (s6 << 6));
s[16] = (uint8_t) (s6 >> 2);
s[17] = (uint8_t) (s6 >> 10);
s[18] = (uint8_t)((s6 >> 18) | (s7 << 3));
s[19] = (uint8_t) (s7 >> 5);
s[20] = (uint8_t) (s7 >> 13);
s[21] = (uint8_t) (s8 >> 0);
s[22] = (uint8_t) (s8 >> 8);
s[23] = (uint8_t)((s8 >> 16) | (s9 << 5));
s[24] = (uint8_t) (s9 >> 3);
s[25] = (uint8_t) (s9 >> 11);
s[26] = (uint8_t)((s9 >> 19) | (s10 << 2));
s[27] = (uint8_t) (s10 >> 6);
s[28] = (uint8_t)((s10 >> 14) | (s11 << 7));
s[29] = (uint8_t) (s11 >> 1);
s[30] = (uint8_t) (s11 >> 9);
s[31] = (uint8_t) (s11 >> 17);
}
/*
* Input:
* a[0]+256*a[1]+...+256^31*a[31] = a
* b[0]+256*b[1]+...+256^31*b[31] = b
* c[0]+256*c[1]+...+256^31*c[31] = c
*
* Output:
* s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
* where l = 2^252 + 27742317777372353535851937790883648493.
*/
static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
const uint8_t *c)
{
int64_t a0 = kBottom21Bits & load_3(a);
int64_t a1 = kBottom21Bits & (load_4(a + 2) >> 5);
int64_t a2 = kBottom21Bits & (load_3(a + 5) >> 2);
int64_t a3 = kBottom21Bits & (load_4(a + 7) >> 7);
int64_t a4 = kBottom21Bits & (load_4(a + 10) >> 4);
int64_t a5 = kBottom21Bits & (load_3(a + 13) >> 1);
int64_t a6 = kBottom21Bits & (load_4(a + 15) >> 6);
int64_t a7 = kBottom21Bits & (load_3(a + 18) >> 3);
int64_t a8 = kBottom21Bits & load_3(a + 21);
int64_t a9 = kBottom21Bits & (load_4(a + 23) >> 5);
int64_t a10 = kBottom21Bits & (load_3(a + 26) >> 2);
int64_t a11 = (load_4(a + 28) >> 7);
int64_t b0 = kBottom21Bits & load_3(b);
int64_t b1 = kBottom21Bits & (load_4(b + 2) >> 5);
int64_t b2 = kBottom21Bits & (load_3(b + 5) >> 2);
int64_t b3 = kBottom21Bits & (load_4(b + 7) >> 7);
int64_t b4 = kBottom21Bits & (load_4(b + 10) >> 4);
int64_t b5 = kBottom21Bits & (load_3(b + 13) >> 1);
int64_t b6 = kBottom21Bits & (load_4(b + 15) >> 6);
int64_t b7 = kBottom21Bits & (load_3(b + 18) >> 3);
int64_t b8 = kBottom21Bits & load_3(b + 21);
int64_t b9 = kBottom21Bits & (load_4(b + 23) >> 5);
int64_t b10 = kBottom21Bits & (load_3(b + 26) >> 2);
int64_t b11 = (load_4(b + 28) >> 7);
int64_t c0 = kBottom21Bits & load_3(c);
int64_t c1 = kBottom21Bits & (load_4(c + 2) >> 5);
int64_t c2 = kBottom21Bits & (load_3(c + 5) >> 2);
int64_t c3 = kBottom21Bits & (load_4(c + 7) >> 7);
int64_t c4 = kBottom21Bits & (load_4(c + 10) >> 4);
int64_t c5 = kBottom21Bits & (load_3(c + 13) >> 1);
int64_t c6 = kBottom21Bits & (load_4(c + 15) >> 6);
int64_t c7 = kBottom21Bits & (load_3(c + 18) >> 3);
int64_t c8 = kBottom21Bits & load_3(c + 21);
int64_t c9 = kBottom21Bits & (load_4(c + 23) >> 5);
int64_t c10 = kBottom21Bits & (load_3(c + 26) >> 2);
int64_t c11 = (load_4(c + 28) >> 7);
int64_t s0;
int64_t s1;
int64_t s2;
int64_t s3;
int64_t s4;
int64_t s5;
int64_t s6;
int64_t s7;
int64_t s8;
int64_t s9;
int64_t s10;
int64_t s11;
int64_t s12;
int64_t s13;
int64_t s14;
int64_t s15;
int64_t s16;
int64_t s17;
int64_t s18;
int64_t s19;
int64_t s20;
int64_t s21;
int64_t s22;
int64_t s23;
int64_t carry0;
int64_t carry1;
int64_t carry2;
int64_t carry3;
int64_t carry4;
int64_t carry5;
int64_t carry6;
int64_t carry7;
int64_t carry8;
int64_t carry9;
int64_t carry10;
int64_t carry11;
int64_t carry12;
int64_t carry13;
int64_t carry14;
int64_t carry15;
int64_t carry16;
int64_t carry17;
int64_t carry18;
int64_t carry19;
int64_t carry20;
int64_t carry21;
int64_t carry22;
s0 = c0 + a0 * b0;
s1 = c1 + a0 * b1 + a1 * b0;
s2 = c2 + a0 * b2 + a1 * b1 + a2 * b0;
s3 = c3 + a0 * b3 + a1 * b2 + a2 * b1 + a3 * b0;
s4 = c4 + a0 * b4 + a1 * b3 + a2 * b2 + a3 * b1 + a4 * b0;
s5 = c5 + a0 * b5 + a1 * b4 + a2 * b3 + a3 * b2 + a4 * b1 + a5 * b0;
s6 = c6 + a0 * b6 + a1 * b5 + a2 * b4 + a3 * b3 + a4 * b2 + a5 * b1 + a6 * b0;
s7 = c7 + a0 * b7 + a1 * b6 + a2 * b5 + a3 * b4 + a4 * b3 + a5 * b2 + a6 * b1 + a7 * b0;
s8 = c8 + a0 * b8 + a1 * b7 + a2 * b6 + a3 * b5 + a4 * b4 + a5 * b3 + a6 * b2 + a7 * b1 + a8 * b0;
s9 = c9 + a0 * b9 + a1 * b8 + a2 * b7 + a3 * b6 + a4 * b5 + a5 * b4 + a6 * b3 + a7 * b2 + a8 * b1 + a9 * b0;
s10 = c10 + a0 * b10 + a1 * b9 + a2 * b8 + a3 * b7 + a4 * b6 + a5 * b5 + a6 * b4 + a7 * b3 + a8 * b2 + a9 * b1 + a10 * b0;
s11 = c11 + a0 * b11 + a1 * b10 + a2 * b9 + a3 * b8 + a4 * b7 + a5 * b6 + a6 * b5 + a7 * b4 + a8 * b3 + a9 * b2 + a10 * b1 + a11 * b0;
s12 = a1 * b11 + a2 * b10 + a3 * b9 + a4 * b8 + a5 * b7 + a6 * b6 + a7 * b5 + a8 * b4 + a9 * b3 + a10 * b2 + a11 * b1;
s13 = a2 * b11 + a3 * b10 + a4 * b9 + a5 * b8 + a6 * b7 + a7 * b6 + a8 * b5 + a9 * b4 + a10 * b3 + a11 * b2;
s14 = a3 * b11 + a4 * b10 + a5 * b9 + a6 * b8 + a7 * b7 + a8 * b6 + a9 * b5 + a10 * b4 + a11 * b3;
s15 = a4 * b11 + a5 * b10 + a6 * b9 + a7 * b8 + a8 * b7 + a9 * b6 + a10 * b5 + a11 * b4;
s16 = a5 * b11 + a6 * b10 + a7 * b9 + a8 * b8 + a9 * b7 + a10 * b6 + a11 * b5;
s17 = a6 * b11 + a7 * b10 + a8 * b9 + a9 * b8 + a10 * b7 + a11 * b6;
s18 = a7 * b11 + a8 * b10 + a9 * b9 + a10 * b8 + a11 * b7;
s19 = a8 * b11 + a9 * b10 + a10 * b9 + a11 * b8;
s20 = a9 * b11 + a10 * b10 + a11 * b9;
s21 = a10 * b11 + a11 * b10;
s22 = a11 * b11;
s23 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 * (1 << 21);
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 * (1 << 21);
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 * (1 << 21);
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 * (1 << 21);
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 * (1 << 21);
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 * (1 << 21);
carry18 = (s18 + (1 << 20)) >> 21;
s19 += carry18;
s18 -= carry18 * (1 << 21);
carry20 = (s20 + (1 << 20)) >> 21;
s21 += carry20;
s20 -= carry20 * (1 << 21);
carry22 = (s22 + (1 << 20)) >> 21;
s23 += carry22;
s22 -= carry22 * (1 << 21);
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 * (1 << 21);
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 * (1 << 21);
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 * (1 << 21);
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 * (1 << 21);
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 * (1 << 21);
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 * (1 << 21);
carry17 = (s17 + (1 << 20)) >> 21;
s18 += carry17;
s17 -= carry17 * (1 << 21);
carry19 = (s19 + (1 << 20)) >> 21;
s20 += carry19;
s19 -= carry19 * (1 << 21);
carry21 = (s21 + (1 << 20)) >> 21;
s22 += carry21;
s21 -= carry21 * (1 << 21);
s11 += s23 * 666643;
s12 += s23 * 470296;
s13 += s23 * 654183;
s14 -= s23 * 997805;
s15 += s23 * 136657;
s16 -= s23 * 683901;
s23 = 0;
s10 += s22 * 666643;
s11 += s22 * 470296;
s12 += s22 * 654183;
s13 -= s22 * 997805;
s14 += s22 * 136657;
s15 -= s22 * 683901;
s22 = 0;
s9 += s21 * 666643;
s10 += s21 * 470296;
s11 += s21 * 654183;
s12 -= s21 * 997805;
s13 += s21 * 136657;
s14 -= s21 * 683901;
s21 = 0;
s8 += s20 * 666643;
s9 += s20 * 470296;
s10 += s20 * 654183;
s11 -= s20 * 997805;
s12 += s20 * 136657;
s13 -= s20 * 683901;
s20 = 0;
s7 += s19 * 666643;
s8 += s19 * 470296;
s9 += s19 * 654183;
s10 -= s19 * 997805;
s11 += s19 * 136657;
s12 -= s19 * 683901;
s19 = 0;
s6 += s18 * 666643;
s7 += s18 * 470296;
s8 += s18 * 654183;
s9 -= s18 * 997805;
s10 += s18 * 136657;
s11 -= s18 * 683901;
s18 = 0;
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
carry12 = (s12 + (1 << 20)) >> 21;
s13 += carry12;
s12 -= carry12 * (1 << 21);
carry14 = (s14 + (1 << 20)) >> 21;
s15 += carry14;
s14 -= carry14 * (1 << 21);
carry16 = (s16 + (1 << 20)) >> 21;
s17 += carry16;
s16 -= carry16 * (1 << 21);
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 * (1 << 21);
carry13 = (s13 + (1 << 20)) >> 21;
s14 += carry13;
s13 -= carry13 * (1 << 21);
carry15 = (s15 + (1 << 20)) >> 21;
s16 += carry15;
s15 -= carry15 * (1 << 21);
s5 += s17 * 666643;
s6 += s17 * 470296;
s7 += s17 * 654183;
s8 -= s17 * 997805;
s9 += s17 * 136657;
s10 -= s17 * 683901;
s17 = 0;
s4 += s16 * 666643;
s5 += s16 * 470296;
s6 += s16 * 654183;
s7 -= s16 * 997805;
s8 += s16 * 136657;
s9 -= s16 * 683901;
s16 = 0;
s3 += s15 * 666643;
s4 += s15 * 470296;
s5 += s15 * 654183;
s6 -= s15 * 997805;
s7 += s15 * 136657;
s8 -= s15 * 683901;
s15 = 0;
s2 += s14 * 666643;
s3 += s14 * 470296;
s4 += s14 * 654183;
s5 -= s14 * 997805;
s6 += s14 * 136657;
s7 -= s14 * 683901;
s14 = 0;
s1 += s13 * 666643;
s2 += s13 * 470296;
s3 += s13 * 654183;
s4 -= s13 * 997805;
s5 += s13 * 136657;
s6 -= s13 * 683901;
s13 = 0;
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = (s0 + (1 << 20)) >> 21;
s1 += carry0;
s0 -= carry0 * (1 << 21);
carry2 = (s2 + (1 << 20)) >> 21;
s3 += carry2;
s2 -= carry2 * (1 << 21);
carry4 = (s4 + (1 << 20)) >> 21;
s5 += carry4;
s4 -= carry4 * (1 << 21);
carry6 = (s6 + (1 << 20)) >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry8 = (s8 + (1 << 20)) >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry10 = (s10 + (1 << 20)) >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
carry1 = (s1 + (1 << 20)) >> 21;
s2 += carry1;
s1 -= carry1 * (1 << 21);
carry3 = (s3 + (1 << 20)) >> 21;
s4 += carry3;
s3 -= carry3 * (1 << 21);
carry5 = (s5 + (1 << 20)) >> 21;
s6 += carry5;
s5 -= carry5 * (1 << 21);
carry7 = (s7 + (1 << 20)) >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry9 = (s9 + (1 << 20)) >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry11 = (s11 + (1 << 20)) >> 21;
s12 += carry11;
s11 -= carry11 * (1 << 21);
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 * (1 << 21);
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 * (1 << 21);
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 * (1 << 21);
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 * (1 << 21);
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 * (1 << 21);
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 * (1 << 21);
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
carry11 = s11 >> 21;
s12 += carry11;
s11 -= carry11 * (1 << 21);
s0 += s12 * 666643;
s1 += s12 * 470296;
s2 += s12 * 654183;
s3 -= s12 * 997805;
s4 += s12 * 136657;
s5 -= s12 * 683901;
s12 = 0;
carry0 = s0 >> 21;
s1 += carry0;
s0 -= carry0 * (1 << 21);
carry1 = s1 >> 21;
s2 += carry1;
s1 -= carry1 * (1 << 21);
carry2 = s2 >> 21;
s3 += carry2;
s2 -= carry2 * (1 << 21);
carry3 = s3 >> 21;
s4 += carry3;
s3 -= carry3 * (1 << 21);
carry4 = s4 >> 21;
s5 += carry4;
s4 -= carry4 * (1 << 21);
carry5 = s5 >> 21;
s6 += carry5;
s5 -= carry5 * (1 << 21);
carry6 = s6 >> 21;
s7 += carry6;
s6 -= carry6 * (1 << 21);
carry7 = s7 >> 21;
s8 += carry7;
s7 -= carry7 * (1 << 21);
carry8 = s8 >> 21;
s9 += carry8;
s8 -= carry8 * (1 << 21);
carry9 = s9 >> 21;
s10 += carry9;
s9 -= carry9 * (1 << 21);
carry10 = s10 >> 21;
s11 += carry10;
s10 -= carry10 * (1 << 21);
s[ 0] = (uint8_t) (s0 >> 0);
s[ 1] = (uint8_t) (s0 >> 8);
s[ 2] = (uint8_t)((s0 >> 16) | (s1 << 5));
s[ 3] = (uint8_t) (s1 >> 3);
s[ 4] = (uint8_t) (s1 >> 11);
s[ 5] = (uint8_t)((s1 >> 19) | (s2 << 2));
s[ 6] = (uint8_t) (s2 >> 6);
s[ 7] = (uint8_t)((s2 >> 14) | (s3 << 7));
s[ 8] = (uint8_t) (s3 >> 1);
s[ 9] = (uint8_t) (s3 >> 9);
s[10] = (uint8_t)((s3 >> 17) | (s4 << 4));
s[11] = (uint8_t) (s4 >> 4);
s[12] = (uint8_t) (s4 >> 12);
s[13] = (uint8_t)((s4 >> 20) | (s5 << 1));
s[14] = (uint8_t) (s5 >> 7);
s[15] = (uint8_t)((s5 >> 15) | (s6 << 6));
s[16] = (uint8_t) (s6 >> 2);
s[17] = (uint8_t) (s6 >> 10);
s[18] = (uint8_t)((s6 >> 18) | (s7 << 3));
s[19] = (uint8_t) (s7 >> 5);
s[20] = (uint8_t) (s7 >> 13);
s[21] = (uint8_t) (s8 >> 0);
s[22] = (uint8_t) (s8 >> 8);
s[23] = (uint8_t)((s8 >> 16) | (s9 << 5));
s[24] = (uint8_t) (s9 >> 3);
s[25] = (uint8_t) (s9 >> 11);
s[26] = (uint8_t)((s9 >> 19) | (s10 << 2));
s[27] = (uint8_t) (s10 >> 6);
s[28] = (uint8_t)((s10 >> 14) | (s11 << 7));
s[29] = (uint8_t) (s11 >> 1);
s[30] = (uint8_t) (s11 >> 9);
s[31] = (uint8_t) (s11 >> 17);
}
int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
const uint8_t public_key[32], const uint8_t private_key[32])
{
uint8_t az[SHA512_DIGEST_LENGTH];
uint8_t nonce[SHA512_DIGEST_LENGTH];
ge_p3 R;
uint8_t hram[SHA512_DIGEST_LENGTH];
SHA512_CTX hash_ctx;
SHA512_Init(&hash_ctx);
SHA512_Update(&hash_ctx, private_key, 32);
SHA512_Final(az, &hash_ctx);
az[0] &= 248;
az[31] &= 63;
az[31] |= 64;
SHA512_Init(&hash_ctx);
SHA512_Update(&hash_ctx, az + 32, 32);
SHA512_Update(&hash_ctx, message, message_len);
SHA512_Final(nonce, &hash_ctx);
x25519_sc_reduce(nonce);
ge_scalarmult_base(&R, nonce);
ge_p3_tobytes(out_sig, &R);
SHA512_Init(&hash_ctx);
SHA512_Update(&hash_ctx, out_sig, 32);
SHA512_Update(&hash_ctx, public_key, 32);
SHA512_Update(&hash_ctx, message, message_len);
SHA512_Final(hram, &hash_ctx);
x25519_sc_reduce(hram);
sc_muladd(out_sig + 32, hram, az, nonce);
OPENSSL_cleanse(&hash_ctx, sizeof(hash_ctx));
OPENSSL_cleanse(nonce, sizeof(nonce));
OPENSSL_cleanse(az, sizeof(az));
return 1;
}
static const char allzeroes[15];
int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[64], const uint8_t public_key[32])
{
int i;
ge_p3 A;
const uint8_t *r, *s;
SHA512_CTX hash_ctx;
ge_p2 R;
uint8_t rcheck[32];
uint8_t h[SHA512_DIGEST_LENGTH];
/* 27742317777372353535851937790883648493 in little endian format */
const uint8_t l_low[16] = {
0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2,
0xDE, 0xF9, 0xDE, 0x14
};
r = signature;
s = signature + 32;
/*
* Check 0 <= s < L where L = 2^252 + 27742317777372353535851937790883648493
*
* If not the signature is publicly invalid. Since it's public we can do the
* check in variable time.
*
* First check the most significant byte
*/
if (s[31] > 0x10)
return 0;
if (s[31] == 0x10) {
/*
* Most significant byte indicates a value close to 2^252 so check the
* rest
*/
if (memcmp(s + 16, allzeroes, sizeof(allzeroes)) != 0)
return 0;
for (i = 15; i >= 0; i--) {
if (s[i] < l_low[i])
break;
if (s[i] > l_low[i])
return 0;
}
if (i < 0)
return 0;
}
if (ge_frombytes_vartime(&A, public_key) != 0) {
return 0;
}
fe_neg(A.X, A.X);
fe_neg(A.T, A.T);
SHA512_Init(&hash_ctx);
SHA512_Update(&hash_ctx, r, 32);
SHA512_Update(&hash_ctx, public_key, 32);
SHA512_Update(&hash_ctx, message, message_len);
SHA512_Final(h, &hash_ctx);
x25519_sc_reduce(h);
ge_double_scalarmult_vartime(&R, h, &A, s);
ge_tobytes(rcheck, &R);
return CRYPTO_memcmp(rcheck, r, sizeof(rcheck)) == 0;
}
void ED25519_public_from_private(uint8_t out_public_key[32],
const uint8_t private_key[32])
{
uint8_t az[SHA512_DIGEST_LENGTH];
ge_p3 A;
SHA512(private_key, 32, az);
az[0] &= 248;
az[31] &= 63;
az[31] |= 64;
ge_scalarmult_base(&A, az);
ge_p3_tobytes(out_public_key, &A);
OPENSSL_cleanse(az, sizeof(az));
}
int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peer_public_value[32])
{
static const uint8_t kZeros[32] = {0};
x25519_scalar_mult(out_shared_key, private_key, peer_public_value);
/* The all-zero output results when the input is a point of small order. */
return CRYPTO_memcmp(kZeros, out_shared_key, 32) != 0;
}
void X25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32])
{
uint8_t e[32];
ge_p3 A;
fe zplusy, zminusy, zminusy_inv;
memcpy(e, private_key, 32);
e[0] &= 248;
e[31] &= 127;
e[31] |= 64;
ge_scalarmult_base(&A, e);
/*
* We only need the u-coordinate of the curve25519 point.
* The map is u=(y+1)/(1-y). Since y=Y/Z, this gives
* u=(Z+Y)/(Z-Y).
*/
fe_add(zplusy, A.Z, A.Y);
fe_sub(zminusy, A.Z, A.Y);
fe_invert(zminusy_inv, zminusy);
fe_mul(zplusy, zplusy, zminusy_inv);
fe_tobytes(out_public_value, zplusy);
OPENSSL_cleanse(e, sizeof(e));
}
diff --git a/crypto/ec/curve448/curve448.c b/crypto/ec/curve448/curve448.c
index 7dc68c8853e1..19bd3857812c 100644
--- a/crypto/ec/curve448/curve448.c
+++ b/crypto/ec/curve448/curve448.c
@@ -1,727 +1,727 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Mike Hamburg
*/
#include <openssl/crypto.h>
#include "word.h"
#include "field.h"
#include "point_448.h"
#include "ed448.h"
#include "curve448_lcl.h"
#define COFACTOR 4
#define C448_WNAF_FIXED_TABLE_BITS 5
#define C448_WNAF_VAR_TABLE_BITS 3
#define EDWARDS_D (-39081)
static const curve448_scalar_t precomputed_scalarmul_adjustment = {
{
{
- SC_LIMB(0xc873d6d54a7bb0cf), SC_LIMB(0xe933d8d723a70aad),
- SC_LIMB(0xbb124b65129c96fd), SC_LIMB(0x00000008335dc163)
+ SC_LIMB(0xc873d6d54a7bb0cfULL), SC_LIMB(0xe933d8d723a70aadULL),
+ SC_LIMB(0xbb124b65129c96fdULL), SC_LIMB(0x00000008335dc163ULL)
}
}
};
#define TWISTED_D (EDWARDS_D - 1)
#define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */
/* Inverse. */
static void gf_invert(gf y, const gf x, int assert_nonzero)
{
mask_t ret;
gf t1, t2;
gf_sqr(t1, x); /* o^2 */
ret = gf_isr(t2, t1); /* +-1/sqrt(o^2) = +-1/o */
(void)ret;
if (assert_nonzero)
assert(ret);
gf_sqr(t1, t2);
gf_mul(t2, t1, x); /* not direct to y in case of alias. */
gf_copy(y, t2);
}
/** identity = (0,1) */
const curve448_point_t curve448_point_identity =
{ {{{{0}}}, {{{1}}}, {{{1}}}, {{{0}}}} };
static void point_double_internal(curve448_point_t p, const curve448_point_t q,
int before_double)
{
gf a, b, c, d;
gf_sqr(c, q->x);
gf_sqr(a, q->y);
gf_add_nr(d, c, a); /* 2+e */
gf_add_nr(p->t, q->y, q->x); /* 2+e */
gf_sqr(b, p->t);
gf_subx_nr(b, b, d, 3); /* 4+e */
gf_sub_nr(p->t, a, c); /* 3+e */
gf_sqr(p->x, q->z);
gf_add_nr(p->z, p->x, p->x); /* 2+e */
gf_subx_nr(a, p->z, p->t, 4); /* 6+e */
if (GF_HEADROOM == 5)
gf_weak_reduce(a); /* or 1+e */
gf_mul(p->x, a, b);
gf_mul(p->z, p->t, a);
gf_mul(p->y, p->t, d);
if (!before_double)
gf_mul(p->t, b, d);
}
void curve448_point_double(curve448_point_t p, const curve448_point_t q)
{
point_double_internal(p, q, 0);
}
/* Operations on [p]niels */
static ossl_inline void cond_neg_niels(niels_t n, mask_t neg)
{
gf_cond_swap(n->a, n->b, neg);
gf_cond_neg(n->c, neg);
}
static void pt_to_pniels(pniels_t b, const curve448_point_t a)
{
gf_sub(b->n->a, a->y, a->x);
gf_add(b->n->b, a->x, a->y);
gf_mulw(b->n->c, a->t, 2 * TWISTED_D);
gf_add(b->z, a->z, a->z);
}
static void pniels_to_pt(curve448_point_t e, const pniels_t d)
{
gf eu;
gf_add(eu, d->n->b, d->n->a);
gf_sub(e->y, d->n->b, d->n->a);
gf_mul(e->t, e->y, eu);
gf_mul(e->x, d->z, e->y);
gf_mul(e->y, d->z, eu);
gf_sqr(e->z, d->z);
}
static void niels_to_pt(curve448_point_t e, const niels_t n)
{
gf_add(e->y, n->b, n->a);
gf_sub(e->x, n->b, n->a);
gf_mul(e->t, e->y, e->x);
gf_copy(e->z, ONE);
}
static void add_niels_to_pt(curve448_point_t d, const niels_t e,
int before_double)
{
gf a, b, c;
gf_sub_nr(b, d->y, d->x); /* 3+e */
gf_mul(a, e->a, b);
gf_add_nr(b, d->x, d->y); /* 2+e */
gf_mul(d->y, e->b, b);
gf_mul(d->x, e->c, d->t);
gf_add_nr(c, a, d->y); /* 2+e */
gf_sub_nr(b, d->y, a); /* 3+e */
gf_sub_nr(d->y, d->z, d->x); /* 3+e */
gf_add_nr(a, d->x, d->z); /* 2+e */
gf_mul(d->z, a, d->y);
gf_mul(d->x, d->y, b);
gf_mul(d->y, a, c);
if (!before_double)
gf_mul(d->t, b, c);
}
static void sub_niels_from_pt(curve448_point_t d, const niels_t e,
int before_double)
{
gf a, b, c;
gf_sub_nr(b, d->y, d->x); /* 3+e */
gf_mul(a, e->b, b);
gf_add_nr(b, d->x, d->y); /* 2+e */
gf_mul(d->y, e->a, b);
gf_mul(d->x, e->c, d->t);
gf_add_nr(c, a, d->y); /* 2+e */
gf_sub_nr(b, d->y, a); /* 3+e */
gf_add_nr(d->y, d->z, d->x); /* 2+e */
gf_sub_nr(a, d->z, d->x); /* 3+e */
gf_mul(d->z, a, d->y);
gf_mul(d->x, d->y, b);
gf_mul(d->y, a, c);
if (!before_double)
gf_mul(d->t, b, c);
}
static void add_pniels_to_pt(curve448_point_t p, const pniels_t pn,
int before_double)
{
gf L0;
gf_mul(L0, p->z, pn->z);
gf_copy(p->z, L0);
add_niels_to_pt(p, pn->n, before_double);
}
static void sub_pniels_from_pt(curve448_point_t p, const pniels_t pn,
int before_double)
{
gf L0;
gf_mul(L0, p->z, pn->z);
gf_copy(p->z, L0);
sub_niels_from_pt(p, pn->n, before_double);
}
c448_bool_t curve448_point_eq(const curve448_point_t p,
const curve448_point_t q)
{
mask_t succ;
gf a, b;
/* equality mod 2-torsion compares x/y */
gf_mul(a, p->y, q->x);
gf_mul(b, q->y, p->x);
succ = gf_eq(a, b);
return mask_to_bool(succ);
}
c448_bool_t curve448_point_valid(const curve448_point_t p)
{
mask_t out;
gf a, b, c;
gf_mul(a, p->x, p->y);
gf_mul(b, p->z, p->t);
out = gf_eq(a, b);
gf_sqr(a, p->x);
gf_sqr(b, p->y);
gf_sub(a, b, a);
gf_sqr(b, p->t);
gf_mulw(c, b, TWISTED_D);
gf_sqr(b, p->z);
gf_add(b, b, c);
out &= gf_eq(a, b);
out &= ~gf_eq(p->z, ZERO);
return mask_to_bool(out);
}
static ossl_inline void constant_time_lookup_niels(niels_s * RESTRICT ni,
const niels_t * table,
int nelts, int idx)
{
constant_time_lookup(ni, table, sizeof(niels_s), nelts, idx);
}
void curve448_precomputed_scalarmul(curve448_point_t out,
const curve448_precomputed_s * table,
const curve448_scalar_t scalar)
{
unsigned int i, j, k;
const unsigned int n = COMBS_N, t = COMBS_T, s = COMBS_S;
niels_t ni;
curve448_scalar_t scalar1x;
curve448_scalar_add(scalar1x, scalar, precomputed_scalarmul_adjustment);
curve448_scalar_halve(scalar1x, scalar1x);
for (i = s; i > 0; i--) {
if (i != s)
point_double_internal(out, out, 0);
for (j = 0; j < n; j++) {
int tab = 0;
mask_t invert;
for (k = 0; k < t; k++) {
unsigned int bit = (i - 1) + s * (k + j * t);
if (bit < C448_SCALAR_BITS)
tab |=
(scalar1x->limb[bit / WBITS] >> (bit % WBITS) & 1) << k;
}
invert = (tab >> (t - 1)) - 1;
tab ^= invert;
tab &= (1 << (t - 1)) - 1;
constant_time_lookup_niels(ni, &table->table[j << (t - 1)],
1 << (t - 1), tab);
cond_neg_niels(ni, invert);
if ((i != s) || j != 0)
add_niels_to_pt(out, ni, j == n - 1 && i != 1);
else
niels_to_pt(out, ni);
}
}
OPENSSL_cleanse(ni, sizeof(ni));
OPENSSL_cleanse(scalar1x, sizeof(scalar1x));
}
void curve448_point_mul_by_ratio_and_encode_like_eddsa(
uint8_t enc[EDDSA_448_PUBLIC_BYTES],
const curve448_point_t p)
{
gf x, y, z, t;
curve448_point_t q;
/* The point is now on the twisted curve. Move it to untwisted. */
curve448_point_copy(q, p);
{
/* 4-isogeny: 2xy/(y^+x^2), (y^2-x^2)/(2z^2-y^2+x^2) */
gf u;
gf_sqr(x, q->x);
gf_sqr(t, q->y);
gf_add(u, x, t);
gf_add(z, q->y, q->x);
gf_sqr(y, z);
gf_sub(y, y, u);
gf_sub(z, t, x);
gf_sqr(x, q->z);
gf_add(t, x, x);
gf_sub(t, t, z);
gf_mul(x, t, y);
gf_mul(y, z, u);
gf_mul(z, u, t);
OPENSSL_cleanse(u, sizeof(u));
}
/* Affinize */
gf_invert(z, z, 1);
gf_mul(t, x, z);
gf_mul(x, y, z);
/* Encode */
enc[EDDSA_448_PRIVATE_BYTES - 1] = 0;
gf_serialize(enc, x, 1);
enc[EDDSA_448_PRIVATE_BYTES - 1] |= 0x80 & gf_lobit(t);
OPENSSL_cleanse(x, sizeof(x));
OPENSSL_cleanse(y, sizeof(y));
OPENSSL_cleanse(z, sizeof(z));
OPENSSL_cleanse(t, sizeof(t));
curve448_point_destroy(q);
}
c448_error_t curve448_point_decode_like_eddsa_and_mul_by_ratio(
curve448_point_t p,
const uint8_t enc[EDDSA_448_PUBLIC_BYTES])
{
uint8_t enc2[EDDSA_448_PUBLIC_BYTES];
mask_t low;
mask_t succ;
memcpy(enc2, enc, sizeof(enc2));
low = ~word_is_zero(enc2[EDDSA_448_PRIVATE_BYTES - 1] & 0x80);
enc2[EDDSA_448_PRIVATE_BYTES - 1] &= ~0x80;
succ = gf_deserialize(p->y, enc2, 1, 0);
succ &= word_is_zero(enc2[EDDSA_448_PRIVATE_BYTES - 1]);
gf_sqr(p->x, p->y);
gf_sub(p->z, ONE, p->x); /* num = 1-y^2 */
gf_mulw(p->t, p->x, EDWARDS_D); /* dy^2 */
gf_sub(p->t, ONE, p->t); /* denom = 1-dy^2 or 1-d + dy^2 */
gf_mul(p->x, p->z, p->t);
succ &= gf_isr(p->t, p->x); /* 1/sqrt(num * denom) */
gf_mul(p->x, p->t, p->z); /* sqrt(num / denom) */
gf_cond_neg(p->x, gf_lobit(p->x) ^ low);
gf_copy(p->z, ONE);
{
gf a, b, c, d;
/* 4-isogeny 2xy/(y^2-ax^2), (y^2+ax^2)/(2-y^2-ax^2) */
gf_sqr(c, p->x);
gf_sqr(a, p->y);
gf_add(d, c, a);
gf_add(p->t, p->y, p->x);
gf_sqr(b, p->t);
gf_sub(b, b, d);
gf_sub(p->t, a, c);
gf_sqr(p->x, p->z);
gf_add(p->z, p->x, p->x);
gf_sub(a, p->z, d);
gf_mul(p->x, a, b);
gf_mul(p->z, p->t, a);
gf_mul(p->y, p->t, d);
gf_mul(p->t, b, d);
OPENSSL_cleanse(a, sizeof(a));
OPENSSL_cleanse(b, sizeof(b));
OPENSSL_cleanse(c, sizeof(c));
OPENSSL_cleanse(d, sizeof(d));
}
OPENSSL_cleanse(enc2, sizeof(enc2));
assert(curve448_point_valid(p) || ~succ);
return c448_succeed_if(mask_to_bool(succ));
}
c448_error_t x448_int(uint8_t out[X_PUBLIC_BYTES],
const uint8_t base[X_PUBLIC_BYTES],
const uint8_t scalar[X_PRIVATE_BYTES])
{
gf x1, x2, z2, x3, z3, t1, t2;
int t;
mask_t swap = 0;
mask_t nz;
(void)gf_deserialize(x1, base, 1, 0);
gf_copy(x2, ONE);
gf_copy(z2, ZERO);
gf_copy(x3, x1);
gf_copy(z3, ONE);
for (t = X_PRIVATE_BITS - 1; t >= 0; t--) {
uint8_t sb = scalar[t / 8];
mask_t k_t;
/* Scalar conditioning */
if (t / 8 == 0)
sb &= -(uint8_t)COFACTOR;
else if (t == X_PRIVATE_BITS - 1)
sb = -1;
k_t = (sb >> (t % 8)) & 1;
k_t = 0 - k_t; /* set to all 0s or all 1s */
swap ^= k_t;
gf_cond_swap(x2, x3, swap);
gf_cond_swap(z2, z3, swap);
swap = k_t;
/*
* The "_nr" below skips coefficient reduction. In the following
* comments, "2+e" is saying that the coefficients are at most 2+epsilon
* times the reduction limit.
*/
gf_add_nr(t1, x2, z2); /* A = x2 + z2 */ /* 2+e */
gf_sub_nr(t2, x2, z2); /* B = x2 - z2 */ /* 3+e */
gf_sub_nr(z2, x3, z3); /* D = x3 - z3 */ /* 3+e */
gf_mul(x2, t1, z2); /* DA */
gf_add_nr(z2, z3, x3); /* C = x3 + z3 */ /* 2+e */
gf_mul(x3, t2, z2); /* CB */
gf_sub_nr(z3, x2, x3); /* DA-CB */ /* 3+e */
gf_sqr(z2, z3); /* (DA-CB)^2 */
gf_mul(z3, x1, z2); /* z3 = x1(DA-CB)^2 */
gf_add_nr(z2, x2, x3); /* (DA+CB) */ /* 2+e */
gf_sqr(x3, z2); /* x3 = (DA+CB)^2 */
gf_sqr(z2, t1); /* AA = A^2 */
gf_sqr(t1, t2); /* BB = B^2 */
gf_mul(x2, z2, t1); /* x2 = AA*BB */
gf_sub_nr(t2, z2, t1); /* E = AA-BB */ /* 3+e */
gf_mulw(t1, t2, -EDWARDS_D); /* E*-d = a24*E */
gf_add_nr(t1, t1, z2); /* AA + a24*E */ /* 2+e */
gf_mul(z2, t2, t1); /* z2 = E(AA+a24*E) */
}
/* Finish */
gf_cond_swap(x2, x3, swap);
gf_cond_swap(z2, z3, swap);
gf_invert(z2, z2, 0);
gf_mul(x1, x2, z2);
gf_serialize(out, x1, 1);
nz = ~gf_eq(x1, ZERO);
OPENSSL_cleanse(x1, sizeof(x1));
OPENSSL_cleanse(x2, sizeof(x2));
OPENSSL_cleanse(z2, sizeof(z2));
OPENSSL_cleanse(x3, sizeof(x3));
OPENSSL_cleanse(z3, sizeof(z3));
OPENSSL_cleanse(t1, sizeof(t1));
OPENSSL_cleanse(t2, sizeof(t2));
return c448_succeed_if(mask_to_bool(nz));
}
void curve448_point_mul_by_ratio_and_encode_like_x448(uint8_t
out[X_PUBLIC_BYTES],
const curve448_point_t p)
{
curve448_point_t q;
curve448_point_copy(q, p);
gf_invert(q->t, q->x, 0); /* 1/x */
gf_mul(q->z, q->t, q->y); /* y/x */
gf_sqr(q->y, q->z); /* (y/x)^2 */
gf_serialize(out, q->y, 1);
curve448_point_destroy(q);
}
void x448_derive_public_key(uint8_t out[X_PUBLIC_BYTES],
const uint8_t scalar[X_PRIVATE_BYTES])
{
/* Scalar conditioning */
uint8_t scalar2[X_PRIVATE_BYTES];
curve448_scalar_t the_scalar;
curve448_point_t p;
unsigned int i;
memcpy(scalar2, scalar, sizeof(scalar2));
scalar2[0] &= -(uint8_t)COFACTOR;
scalar2[X_PRIVATE_BYTES - 1] &= ~((0u - 1u) << ((X_PRIVATE_BITS + 7) % 8));
scalar2[X_PRIVATE_BYTES - 1] |= 1 << ((X_PRIVATE_BITS + 7) % 8);
curve448_scalar_decode_long(the_scalar, scalar2, sizeof(scalar2));
/* Compensate for the encoding ratio */
for (i = 1; i < X448_ENCODE_RATIO; i <<= 1)
curve448_scalar_halve(the_scalar, the_scalar);
curve448_precomputed_scalarmul(p, curve448_precomputed_base, the_scalar);
curve448_point_mul_by_ratio_and_encode_like_x448(out, p);
curve448_point_destroy(p);
}
/* Control for variable-time scalar multiply algorithms. */
struct smvt_control {
int power, addend;
};
#if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3))
# define NUMTRAILINGZEROS __builtin_ctz
#else
# define NUMTRAILINGZEROS numtrailingzeros
static uint32_t numtrailingzeros(uint32_t i)
{
uint32_t tmp;
uint32_t num = 31;
if (i == 0)
return 32;
tmp = i << 16;
if (tmp != 0) {
i = tmp;
num -= 16;
}
tmp = i << 8;
if (tmp != 0) {
i = tmp;
num -= 8;
}
tmp = i << 4;
if (tmp != 0) {
i = tmp;
num -= 4;
}
tmp = i << 2;
if (tmp != 0) {
i = tmp;
num -= 2;
}
tmp = i << 1;
if (tmp != 0)
num--;
return num;
}
#endif
static int recode_wnaf(struct smvt_control *control,
/* [nbits/(table_bits + 1) + 3] */
const curve448_scalar_t scalar,
unsigned int table_bits)
{
unsigned int table_size = C448_SCALAR_BITS / (table_bits + 1) + 3;
int position = table_size - 1; /* at the end */
uint64_t current = scalar->limb[0] & 0xFFFF;
uint32_t mask = (1 << (table_bits + 1)) - 1;
unsigned int w;
const unsigned int B_OVER_16 = sizeof(scalar->limb[0]) / 2;
unsigned int n, i;
/* place the end marker */
control[position].power = -1;
control[position].addend = 0;
position--;
/*
* PERF: Could negate scalar if it's large. But then would need more cases
* in the actual code that uses it, all for an expected reduction of like
* 1/5 op. Probably not worth it.
*/
for (w = 1; w < (C448_SCALAR_BITS - 1) / 16 + 3; w++) {
if (w < (C448_SCALAR_BITS - 1) / 16 + 1) {
/* Refill the 16 high bits of current */
current += (uint32_t)((scalar->limb[w / B_OVER_16]
>> (16 * (w % B_OVER_16))) << 16);
}
while (current & 0xFFFF) {
uint32_t pos = NUMTRAILINGZEROS((uint32_t)current);
uint32_t odd = (uint32_t)current >> pos;
int32_t delta = odd & mask;
assert(position >= 0);
if (odd & (1 << (table_bits + 1)))
delta -= (1 << (table_bits + 1));
current -= delta * (1 << pos);
control[position].power = pos + 16 * (w - 1);
control[position].addend = delta;
position--;
}
current >>= 16;
}
assert(current == 0);
position++;
n = table_size - position;
for (i = 0; i < n; i++)
control[i] = control[i + position];
return n - 1;
}
static void prepare_wnaf_table(pniels_t * output,
const curve448_point_t working,
unsigned int tbits)
{
curve448_point_t tmp;
int i;
pniels_t twop;
pt_to_pniels(output[0], working);
if (tbits == 0)
return;
curve448_point_double(tmp, working);
pt_to_pniels(twop, tmp);
add_pniels_to_pt(tmp, output[0], 0);
pt_to_pniels(output[1], tmp);
for (i = 2; i < 1 << tbits; i++) {
add_pniels_to_pt(tmp, twop, 0);
pt_to_pniels(output[i], tmp);
}
curve448_point_destroy(tmp);
OPENSSL_cleanse(twop, sizeof(twop));
}
void curve448_base_double_scalarmul_non_secret(curve448_point_t combo,
const curve448_scalar_t scalar1,
const curve448_point_t base2,
const curve448_scalar_t scalar2)
{
const int table_bits_var = C448_WNAF_VAR_TABLE_BITS;
const int table_bits_pre = C448_WNAF_FIXED_TABLE_BITS;
struct smvt_control control_var[C448_SCALAR_BITS /
(C448_WNAF_VAR_TABLE_BITS + 1) + 3];
struct smvt_control control_pre[C448_SCALAR_BITS /
(C448_WNAF_FIXED_TABLE_BITS + 1) + 3];
int ncb_pre = recode_wnaf(control_pre, scalar1, table_bits_pre);
int ncb_var = recode_wnaf(control_var, scalar2, table_bits_var);
pniels_t precmp_var[1 << C448_WNAF_VAR_TABLE_BITS];
int contp = 0, contv = 0, i;
prepare_wnaf_table(precmp_var, base2, table_bits_var);
i = control_var[0].power;
if (i < 0) {
curve448_point_copy(combo, curve448_point_identity);
return;
}
if (i > control_pre[0].power) {
pniels_to_pt(combo, precmp_var[control_var[0].addend >> 1]);
contv++;
} else if (i == control_pre[0].power && i >= 0) {
pniels_to_pt(combo, precmp_var[control_var[0].addend >> 1]);
add_niels_to_pt(combo, curve448_wnaf_base[control_pre[0].addend >> 1],
i);
contv++;
contp++;
} else {
i = control_pre[0].power;
niels_to_pt(combo, curve448_wnaf_base[control_pre[0].addend >> 1]);
contp++;
}
for (i--; i >= 0; i--) {
int cv = (i == control_var[contv].power);
int cp = (i == control_pre[contp].power);
point_double_internal(combo, combo, i && !(cv || cp));
if (cv) {
assert(control_var[contv].addend);
if (control_var[contv].addend > 0)
add_pniels_to_pt(combo,
precmp_var[control_var[contv].addend >> 1],
i && !cp);
else
sub_pniels_from_pt(combo,
precmp_var[(-control_var[contv].addend)
>> 1], i && !cp);
contv++;
}
if (cp) {
assert(control_pre[contp].addend);
if (control_pre[contp].addend > 0)
add_niels_to_pt(combo,
curve448_wnaf_base[control_pre[contp].addend
>> 1], i);
else
sub_niels_from_pt(combo,
curve448_wnaf_base[(-control_pre
[contp].addend) >> 1], i);
contp++;
}
}
/* This function is non-secret, but whatever this is cheap. */
OPENSSL_cleanse(control_var, sizeof(control_var));
OPENSSL_cleanse(control_pre, sizeof(control_pre));
OPENSSL_cleanse(precmp_var, sizeof(precmp_var));
assert(contv == ncb_var);
(void)ncb_var;
assert(contp == ncb_pre);
(void)ncb_pre;
}
void curve448_point_destroy(curve448_point_t point)
{
OPENSSL_cleanse(point, sizeof(curve448_point_t));
}
int X448(uint8_t out_shared_key[56], const uint8_t private_key[56],
const uint8_t peer_public_value[56])
{
return x448_int(out_shared_key, peer_public_value, private_key)
== C448_SUCCESS;
}
void X448_public_from_private(uint8_t out_public_value[56],
const uint8_t private_key[56])
{
x448_derive_public_key(out_public_value, private_key);
}
diff --git a/crypto/ec/curve448/curve448_tables.c b/crypto/ec/curve448/curve448_tables.c
index a1185b1eee6a..9ef29769e3b3 100644
--- a/crypto/ec/curve448/curve448_tables.c
+++ b/crypto/ec/curve448/curve448_tables.c
@@ -1,475 +1,1483 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Mike Hamburg
*/
#include "field.h"
#include "point_448.h"
static const curve448_precomputed_s curve448_precomputed_base_table = {
{
{{
- {FIELD_LITERAL(0x00cc3b062366f4cc,0x003d6e34e314aa3c,0x00d51c0a7521774d,0x0094e060eec6ab8b,0x00d21291b4d80082,0x00befed12b55ef1e,0x00c3dd2df5c94518,0x00e0a7b112b8d4e6)},
- {FIELD_LITERAL(0x0019eb5608d8723a,0x00d1bab52fb3aedb,0x00270a7311ebc90c,0x0037c12b91be7f13,0x005be16cd8b5c704,0x003e181acda888e1,0x00bc1f00fc3fc6d0,0x00d3839bfa319e20)},
- {FIELD_LITERAL(0x003caeb88611909f,0x00ea8b378c4df3d4,0x00b3295b95a5a19a,0x00a65f97514bdfb5,0x00b39efba743cab1,0x0016ba98b862fd2d,0x0001508812ee71d7,0x000a75740eea114a)},
- }}, {{
- {FIELD_LITERAL(0x00ebcf0eb649f823,0x00166d332e98ea03,0x0059ddf64f5cd5f6,0x0047763123d9471b,0x00a64065c53ef62f,0x00978e44c480153d,0x000b5b2a0265f194,0x0046a24b9f32965a)},
- {FIELD_LITERAL(0x00b9eef787034df0,0x0020bc24de3390cd,0x000022160bae99bb,0x00ae66e886e97946,0x0048d4bbe02cbb8b,0x0072ba97b34e38d4,0x00eae7ec8f03e85a,0x005ba92ecf808b2c)},
- {FIELD_LITERAL(0x00c9cfbbe74258fd,0x00843a979ea9eaa7,0x000cbb4371cfbe90,0x0059bac8f7f0a628,0x004b3dff882ff530,0x0011869df4d90733,0x00595aa71f4abfc2,0x0070e2d38990c2e6)},
- }}, {{
- {FIELD_LITERAL(0x00de2010c0a01733,0x00c739a612e24297,0x00a7212643141d7c,0x00f88444f6b67c11,0x00484b7b16ec28f2,0x009c1b8856af9c68,0x00ff4669591fe9d6,0x0054974be08a32c8)},
- {FIELD_LITERAL(0x0010de3fd682ceed,0x008c07642d83ca4e,0x0013bb064e00a1cc,0x009411ae27870e11,0x00ea8e5b4d531223,0x0032fe7d2aaece2e,0x00d989e243e7bb41,0x000fe79a508e9b8b)},
- {FIELD_LITERAL(0x005e0426b9bfc5b1,0x0041a5b1d29ee4fa,0x0015b0def7774391,0x00bc164f1f51af01,0x00d543b0942797b9,0x003c129b6398099c,0x002b114c6e5adf18,0x00b4e630e4018a7b)},
- }}, {{
- {FIELD_LITERAL(0x00d490afc95f8420,0x00b096bf50c1d9b9,0x00799fd707679866,0x007c74d9334afbea,0x00efaa8be80ff4ed,0x0075c4943bb81694,0x00c21c2fca161f36,0x00e77035d492bfee)},
- {FIELD_LITERAL(0x006658a190dd6661,0x00e0e9bab38609a6,0x0028895c802237ed,0x006a0229c494f587,0x002dcde96c9916b7,0x00d158822de16218,0x00173b917a06856f,0x00ca78a79ae07326)},
- {FIELD_LITERAL(0x00e35bfc79caced4,0x0087238a3e1fe3bb,0x00bcbf0ff4ceff5b,0x00a19c1c94099b91,0x0071e102b49db976,0x0059e3d004eada1e,0x008da78afa58a47e,0x00579c8ebf269187)},
- }}, {{
- {FIELD_LITERAL(0x00a16c2905eee75f,0x009d4bcaea2c7e1d,0x00d3bd79bfad19df,0x0050da745193342c,0x006abdb8f6b29ab1,0x00a24fe0a4fef7ef,0x0063730da1057dfb,0x00a08c312c8eb108)},
- {FIELD_LITERAL(0x00b583be005375be,0x00a40c8f8a4e3df4,0x003fac4a8f5bdbf7,0x00d4481d872cd718,0x004dc8749cdbaefe,0x00cce740d5e5c975,0x000b1c1f4241fd21,0x00a76de1b4e1cd07)},
- {FIELD_LITERAL(0x007a076500d30b62,0x000a6e117b7f090f,0x00c8712ae7eebd9a,0x000fbd6c1d5f6ff7,0x003a7977246ebf11,0x00166ed969c6600e,0x00aa42e469c98bec,0x00dc58f307cf0666)},
- }}, {{
- {FIELD_LITERAL(0x004b491f65a9a28b,0x006a10309e8a55b7,0x00b67210185187ef,0x00cf6497b12d9b8f,0x0085778c56e2b1ba,0x0015b4c07a814d85,0x00686479e62da561,0x008de5d88f114916)},
- {FIELD_LITERAL(0x00e37c88d6bba7b1,0x003e4577e1b8d433,0x0050d8ea5f510ec0,0x0042fc9f2da9ef59,0x003bd074c1141420,0x00561b8b7b68774e,0x00232e5e5d1013a3,0x006b7f2cb3d7e73f)},
- {FIELD_LITERAL(0x004bdd0f0b41e6a0,0x001773057c405d24,0x006029f99915bd97,0x006a5ba70a17fe2f,0x0046111977df7e08,0x004d8124c89fb6b7,0x00580983b2bb2724,0x00207bf330d6f3fe)},
- }}, {{
- {FIELD_LITERAL(0x007efdc93972a48b,0x002f5e50e78d5fee,0x0080dc11d61c7fe5,0x0065aa598707245b,0x009abba2300641be,0x000c68787656543a,0x00ffe0fef2dc0a17,0x00007ffbd6cb4f3a)},
- {FIELD_LITERAL(0x0036012f2b836efc,0x00458c126d6b5fbc,0x00a34436d719ad1e,0x0097be6167117dea,0x0009c219c879cff3,0x0065564493e60755,0x00993ac94a8cdec0,0x002d4885a4d0dbaf)},
- {FIELD_LITERAL(0x00598b60b4c068ba,0x00c547a0be7f1afd,0x009582164acf12af,0x00af4acac4fbbe40,0x005f6ca7c539121a,0x003b6e752ebf9d66,0x00f08a30d5cac5d4,0x00e399bb5f97c5a9)},
- }}, {{
- {FIELD_LITERAL(0x007445a0409c0a66,0x00a65c369f3829c0,0x0031d248a4f74826,0x006817f34defbe8e,0x00649741d95ebf2e,0x00d46466ab16b397,0x00fdc35703bee414,0x00343b43334525f8)},
- {FIELD_LITERAL(0x001796bea93f6401,0x00090c5a42e85269,0x00672412ba1252ed,0x001201d47b6de7de,0x006877bccfe66497,0x00b554fd97a4c161,0x009753f42dbac3cf,0x00e983e3e378270a)},
- {FIELD_LITERAL(0x00ac3eff18849872,0x00f0eea3bff05690,0x00a6d72c21dd505d,0x001b832642424169,0x00a6813017b540e5,0x00a744bd71b385cd,0x0022a7d089130a7b,0x004edeec9a133486)},
- }}, {{
- {FIELD_LITERAL(0x00b2d6729196e8a9,0x0088a9bb2031cef4,0x00579e7787dc1567,0x0030f49feb059190,0x00a0b1d69c7f7d8f,0x0040bdcc6d9d806f,0x00d76c4037edd095,0x00bbf24376415dd7)},
- {FIELD_LITERAL(0x00240465ff5a7197,0x00bb97e76caf27d0,0x004b4edbf8116d39,0x001d8586f708cbaa,0x000f8ee8ff8e4a50,0x00dde5a1945dd622,0x00e6fc1c0957e07c,0x0041c9cdabfd88a0)},
- {FIELD_LITERAL(0x005344b0bf5b548c,0x002957d0b705cc99,0x00f586a70390553d,0x0075b3229f583cc3,0x00a1aa78227490e4,0x001bf09cf7957717,0x00cf6bf344325f52,0x0065bd1c23ca3ecf)},
- }}, {{
- {FIELD_LITERAL(0x009bff3b3239363c,0x00e17368796ef7c0,0x00528b0fe0971f3a,0x0008014fc8d4a095,0x00d09f2e8a521ec4,0x006713ab5dde5987,0x0003015758e0dbb1,0x00215999f1ba212d)},
- {FIELD_LITERAL(0x002c88e93527da0e,0x0077c78f3456aad5,0x0071087a0a389d1c,0x00934dac1fb96dbd,0x008470e801162697,0x005bc2196cd4ad49,0x00e535601d5087c3,0x00769888700f497f)},
- {FIELD_LITERAL(0x00da7a4b557298ad,0x0019d2589ea5df76,0x00ef3e38be0c6497,0x00a9644e1312609a,0x004592f61b2558da,0x0082c1df510d7e46,0x0042809a535c0023,0x00215bcb5afd7757)},
- }}, {{
- {FIELD_LITERAL(0x002b9df55a1a4213,0x00dcfc3b464a26be,0x00c4f9e07a8144d5,0x00c8e0617a92b602,0x008e3c93accafae0,0x00bf1bcb95b2ca60,0x004ce2426a613bf3,0x00266cac58e40921)},
- {FIELD_LITERAL(0x008456d5db76e8f0,0x0032ca9cab2ce163,0x0059f2b8bf91abcf,0x0063c2a021712788,0x00f86155af22f72d,0x00db98b2a6c005a0,0x00ac6e416a693ac4,0x007a93572af53226)},
- {FIELD_LITERAL(0x0087767520f0de22,0x0091f64012279fb5,0x001050f1f0644999,0x004f097a2477ad3c,0x006b37913a9947bd,0x001a3d78645af241,0x0057832bbb3008a7,0x002c1d902b80dc20)},
- }}, {{
- {FIELD_LITERAL(0x001a6002bf178877,0x009bce168aa5af50,0x005fc318ff04a7f5,0x0052818f55c36461,0x008768f5d4b24afb,0x0037ffbae7b69c85,0x0018195a4b61edc0,0x001e12ea088434b2)},
- {FIELD_LITERAL(0x0047d3f804e7ab07,0x00a809ab5f905260,0x00b3ffc7cdaf306d,0x00746e8ec2d6e509,0x00d0dade8887a645,0x00acceeebde0dd37,0x009bc2579054686b,0x0023804f97f1c2bf)},
- {FIELD_LITERAL(0x0043e2e2e50b80d7,0x00143aafe4427e0f,0x005594aaecab855b,0x008b12ccaaecbc01,0x002deeb091082bc3,0x009cca4be2ae7514,0x00142b96e696d047,0x00ad2a2b1c05256a)},
- }}, {{
- {FIELD_LITERAL(0x003914f2f144b78b,0x007a95dd8bee6f68,0x00c7f4384d61c8e6,0x004e51eb60f1bdb2,0x00f64be7aa4621d8,0x006797bfec2f0ac0,0x007d17aab3c75900,0x001893e73cac8bc5)},
- {FIELD_LITERAL(0x00140360b768665b,0x00b68aca4967f977,0x0001089b66195ae4,0x00fe71122185e725,0x000bca2618d49637,0x00a54f0557d7e98a,0x00cdcd2f91d6f417,0x00ab8c13741fd793)},
- {FIELD_LITERAL(0x00725ee6b1e549e0,0x007124a0769777fa,0x000b68fdad07ae42,0x0085b909cd4952df,0x0092d2e3c81606f4,0x009f22f6cac099a0,0x00f59da57f2799a8,0x00f06c090122f777)},
- }}, {{
- {FIELD_LITERAL(0x00ce0bed0a3532bc,0x001a5048a22df16b,0x00e31db4cbad8bf1,0x00e89292120cf00e,0x007d1dd1a9b00034,0x00e2a9041ff8f680,0x006a4c837ae596e7,0x00713af1068070b3)},
- {FIELD_LITERAL(0x00c4fe64ce66d04b,0x00b095d52e09b3d7,0x00758bbecb1a3a8e,0x00f35cce8d0650c0,0x002b878aa5984473,0x0062e0a3b7544ddc,0x00b25b290ed116fe,0x007b0f6abe0bebf2)},
- {FIELD_LITERAL(0x0081d4e3addae0a8,0x003410c836c7ffcc,0x00c8129ad89e4314,0x000e3d5a23922dcd,0x00d91e46f29c31f3,0x006c728cde8c5947,0x002bc655ba2566c0,0x002ca94721533108)},
- }}, {{
- {FIELD_LITERAL(0x0051e4b3f764d8a9,0x0019792d46e904a0,0x00853bc13dbc8227,0x000840208179f12d,0x0068243474879235,0x0013856fbfe374d0,0x00bda12fe8676424,0x00bbb43635926eb2)},
- {FIELD_LITERAL(0x0012cdc880a93982,0x003c495b21cd1b58,0x00b7e5c93f22a26e,0x0044aa82dfb99458,0x009ba092cdffe9c0,0x00a14b3ab2083b73,0x000271c2f70e1c4b,0x00eea9cac0f66eb8)},
- {FIELD_LITERAL(0x001a1847c4ac5480,0x00b1b412935bb03a,0x00f74285983bf2b2,0x00624138b5b5d0f1,0x008820c0b03d38bf,0x00b94e50a18c1572,0x0060f6934841798f,0x00c52f5d66d6ebe2)},
- }}, {{
- {FIELD_LITERAL(0x00da23d59f9bcea6,0x00e0f27007a06a4b,0x00128b5b43a6758c,0x000cf50190fa8b56,0x00fc877aba2b2d72,0x00623bef52edf53f,0x00e6af6b819669e2,0x00e314dc34fcaa4f)},
- {FIELD_LITERAL(0x0066e5eddd164d1e,0x00418a7c6fe28238,0x0002e2f37e962c25,0x00f01f56b5975306,0x0048842fa503875c,0x0057b0e968078143,0x00ff683024f3d134,0x0082ae28fcad12e4)},
- {FIELD_LITERAL(0x0011ddfd21260e42,0x00d05b0319a76892,0x00183ea4368e9b8f,0x00b0815662affc96,0x00b466a5e7ce7c88,0x00db93b07506e6ee,0x0033885f82f62401,0x0086f9090ec9b419)},
- }}, {{
- {FIELD_LITERAL(0x00d95d1c5fcb435a,0x0016d1ed6b5086f9,0x00792aa0b7e54d71,0x0067b65715f1925d,0x00a219755ec6176b,0x00bc3f026b12c28f,0x00700c897ffeb93e,0x0089b83f6ec50b46)},
- {FIELD_LITERAL(0x003c97e6384da36e,0x00423d53eac81a09,0x00b70d68f3cdce35,0x00ee7959b354b92c,0x00f4e9718819c8ca,0x009349f12acbffe9,0x005aee7b62cb7da6,0x00d97764154ffc86)},
- {FIELD_LITERAL(0x00526324babb46dc,0x002ee99b38d7bf9e,0x007ea51794706ef4,0x00abeb04da6e3c39,0x006b457c1d281060,0x00fe243e9a66c793,0x00378de0fb6c6ee4,0x003e4194b9c3cb93)},
- }}, {{
- {FIELD_LITERAL(0x00fed3cd80ca2292,0x0015b043a73ca613,0x000a9fd7bf9be227,0x003b5e03de2db983,0x005af72d46904ef7,0x00c0f1b5c49faa99,0x00dc86fc3bd305e1,0x00c92f08c1cb1797)},
- {FIELD_LITERAL(0x0079680ce111ed3b,0x001a1ed82806122c,0x000c2e7466d15df3,0x002c407f6f7150fd,0x00c5e7c96b1b0ce3,0x009aa44626863ff9,0x00887b8b5b80be42,0x00b6023cec964825)},
- {FIELD_LITERAL(0x00e4a8e1048970c8,0x0062887b7830a302,0x00bcf1c8cd81402b,0x0056dbb81a68f5be,0x0014eced83f12452,0x00139e1a510150df,0x00bb81140a82d1a3,0x000febcc1aaf1aa7)},
- }}, {{
- {FIELD_LITERAL(0x00a7527958238159,0x0013ec9537a84cd6,0x001d7fee7d562525,0x00b9eefa6191d5e5,0x00dbc97db70bcb8a,0x00481affc7a4d395,0x006f73d3e70c31bb,0x00183f324ed96a61)},
- {FIELD_LITERAL(0x0039dd7ce7fc6860,0x00d64f6425653da1,0x003e037c7f57d0af,0x0063477a06e2bcf2,0x001727dbb7ac67e6,0x0049589f5efafe2e,0x00fc0fef2e813d54,0x008baa5d087fb50d)},
- {FIELD_LITERAL(0x0024fb59d9b457c7,0x00a7d4e060223e4c,0x00c118d1b555fd80,0x0082e216c732f22a,0x00cd2a2993089504,0x003638e836a3e13d,0x000d855ee89b4729,0x008ec5b7d4810c91)},
- }}, {{
- {FIELD_LITERAL(0x001bf51f7d65cdfd,0x00d14cdafa16a97d,0x002c38e60fcd10e7,0x00a27446e393efbd,0x000b5d8946a71fdd,0x0063df2cde128f2f,0x006c8679569b1888,0x0059ffc4925d732d)},
- {FIELD_LITERAL(0x00ece96f95f2b66f,0x00ece7952813a27b,0x0026fc36592e489e,0x007157d1a2de0f66,0x00759dc111d86ddf,0x0012881e5780bb0f,0x00c8ccc83ad29496,0x0012b9bd1929eb71)},
- {FIELD_LITERAL(0x000fa15a20da5df0,0x00349ddb1a46cd31,0x002c512ad1d8e726,0x00047611f669318d,0x009e68fba591e17e,0x004320dffa803906,0x00a640874951a3d3,0x00b6353478baa24f)},
- }}, {{
- {FIELD_LITERAL(0x009696510000d333,0x00ec2f788bc04826,0x000e4d02b1f67ba5,0x00659aa8dace08b6,0x00d7a38a3a3ae533,0x008856defa8c746b,0x004d7a4402d3da1a,0x00ea82e06229260f)},
- {FIELD_LITERAL(0x006a15bb20f75c0c,0x0079a144027a5d0c,0x00d19116ce0b4d70,0x0059b83bcb0b268e,0x005f58f63f16c127,0x0079958318ee2c37,0x00defbb063d07f82,0x00f1f0b931d2d446)},
- {FIELD_LITERAL(0x00cb5e4c3c35d422,0x008df885ca43577f,0x00fa50b16ca3e471,0x005a0e58e17488c8,0x00b2ceccd6d34d19,0x00f01d5d235e36e9,0x00db2e7e4be6ca44,0x00260ab77f35fccd)},
- }}, {{
- {FIELD_LITERAL(0x006f6fd9baac61d5,0x002a7710a020a895,0x009de0db7fc03d4d,0x00cdedcb1875f40b,0x00050caf9b6b1e22,0x005e3a6654456ab0,0x00775fdf8c4423d4,0x0028701ea5738b5d)},
- {FIELD_LITERAL(0x009ffd90abfeae96,0x00cba3c2b624a516,0x005ef08bcee46c91,0x00e6fde30afb6185,0x00f0b4db4f818ce4,0x006c54f45d2127f5,0x00040125035854c7,0x00372658a3287e13)},
- {FIELD_LITERAL(0x00d7070fb1beb2ab,0x0078fc845a93896b,0x006894a4b2f224a6,0x005bdd8192b9dbde,0x00b38839874b3a9e,0x00f93618b04b7a57,0x003e3ec75fd2c67e,0x00bf5e6bfc29494a)},
- }}, {{
- {FIELD_LITERAL(0x00f19224ebba2aa5,0x0074f89d358e694d,0x00eea486597135ad,0x0081579a4555c7e1,0x0010b9b872930a9d,0x00f002e87a30ecc0,0x009b9d66b6de56e2,0x00a3c4f45e8004eb)},
- {FIELD_LITERAL(0x0045e8dda9400888,0x002ff12e5fc05db7,0x00a7098d54afe69c,0x00cdbe846a500585,0x00879c1593ca1882,0x003f7a7fea76c8b0,0x002cd73dd0c8e0a1,0x00645d6ce96f51fe)},
- {FIELD_LITERAL(0x002b7e83e123d6d6,0x00398346f7419c80,0x0042922e55940163,0x005e7fc5601886a3,0x00e88f2cee1d3103,0x00e7fab135f2e377,0x00b059984dbf0ded,0x0009ce080faa5bb8)},
- }}, {{
- {FIELD_LITERAL(0x0085e78af7758979,0x00275a4ee1631a3a,0x00d26bc0ed78b683,0x004f8355ea21064f,0x00d618e1a32696e5,0x008d8d7b150e5680,0x00a74cd854b278d2,0x001dd62702203ea0)},
- {FIELD_LITERAL(0x00f89335c2a59286,0x00a0f5c905d55141,0x00b41fb836ee9382,0x00e235d51730ca43,0x00a5cb37b5c0a69a,0x009b966ffe136c45,0x00cb2ea10bf80ed1,0x00fb2b370b40dc35)},
- {FIELD_LITERAL(0x00d687d16d4ee8ba,0x0071520bdd069dff,0x00de85c60d32355d,0x0087d2e3565102f4,0x00cde391b8dfc9aa,0x00e18d69efdfefe5,0x004a9d0591954e91,0x00fa36dd8b50eee5)},
- }}, {{
- {FIELD_LITERAL(0x002e788749a865f7,0x006e4dc3116861ea,0x009f1428c37276e6,0x00e7d2e0fc1e1226,0x003aeebc6b6c45f6,0x0071a8073bf500c9,0x004b22ad986b530c,0x00f439e63c0d79d4)},
- {FIELD_LITERAL(0x006bc3d53011f470,0x00032d6e692b83e8,0x00059722f497cd0b,0x0009b4e6f0c497cc,0x0058a804b7cce6c0,0x002b71d3302bbd5d,0x00e2f82a36765fce,0x008dded99524c703)},
- {FIELD_LITERAL(0x004d058953747d64,0x00701940fe79aa6f,0x00a620ac71c760bf,0x009532b611158b75,0x00547ed7f466f300,0x003cb5ab53a8401a,0x00c7763168ce3120,0x007e48e33e4b9ab2)},
- }}, {{
- {FIELD_LITERAL(0x001b2fc57bf3c738,0x006a3f918993fb80,0x0026f7a14fdec288,0x0075a2cdccef08db,0x00d3ecbc9eecdbf1,0x0048c40f06e5bf7f,0x00d63e423009896b,0x000598bc99c056a8)},
- {FIELD_LITERAL(0x002f194eaafa46dc,0x008e38f57fe87613,0x00dc8e5ae25f4ab2,0x000a17809575e6bd,0x00d3ec7923ba366a,0x003a7e72e0ad75e3,0x0010024b88436e0a,0x00ed3c5444b64051)},
- {FIELD_LITERAL(0x00831fc1340af342,0x00c9645669466d35,0x007692b4cc5a080f,0x009fd4a47ac9259f,0x001eeddf7d45928b,0x003c0446fc45f28b,0x002c0713aa3e2507,0x0095706935f0f41e)},
- }}, {{
- {FIELD_LITERAL(0x00766ae4190ec6d8,0x0065768cabc71380,0x00b902598416cdc2,0x00380021ad38df52,0x008f0b89d6551134,0x004254d4cc62c5a5,0x000d79f4484b9b94,0x00b516732ae3c50e)},
- {FIELD_LITERAL(0x001fb73475c45509,0x00d2b2e5ea43345a,0x00cb3c3842077bd1,0x0029f90ad820946e,0x007c11b2380778aa,0x009e54ece62c1704,0x004bc60c41ca01c3,0x004525679a5a0b03)},
- {FIELD_LITERAL(0x00c64fbddbed87b3,0x0040601d11731faa,0x009c22475b6f9d67,0x0024b79dae875f15,0x00616fed3f02c3b0,0x0000cf39f6af2d3b,0x00c46bac0aa9a688,0x00ab23e2800da204)},
- }}, {{
- {FIELD_LITERAL(0x000b3a37617632b0,0x00597199fe1cfb6c,0x0042a7ccdfeafdd6,0x004cc9f15ebcea17,0x00f436e596a6b4a4,0x00168861142df0d8,0x000753edfec26af5,0x000c495d7e388116)},
- {FIELD_LITERAL(0x0017085f4a346148,0x00c7cf7a37f62272,0x001776e129bc5c30,0x009955134c9eef2a,0x001ba5bdf1df07be,0x00ec39497103a55c,0x006578354fda6cfb,0x005f02719d4f15ee)},
- {FIELD_LITERAL(0x0052b9d9b5d9655d,0x00d4ec7ba1b461c3,0x00f95df4974f280b,0x003d8e5ca11aeb51,0x00d4981eb5a70b26,0x000af9a4f6659f29,0x004598c846faeb43,0x0049d9a183a47670)},
- }}, {{
- {FIELD_LITERAL(0x000a72d23dcb3f1f,0x00a3737f84011727,0x00f870c0fbbf4a47,0x00a7aadd04b5c9ca,0x000c7715c67bd072,0x00015a136afcd74e,0x0080d5caea499634,0x0026b448ec7514b7)},
- {FIELD_LITERAL(0x00b60167d9e7d065,0x00e60ba0d07381e8,0x003a4f17b725c2d4,0x006c19fe176b64fa,0x003b57b31af86ccb,0x0021047c286180fd,0x00bdc8fb00c6dbb6,0x00fe4a9f4bab4f3f)},
- {FIELD_LITERAL(0x0088ffc3a16111f7,0x009155e4245d0bc8,0x00851d68220572d5,0x00557ace1e514d29,0x0031d7c339d91022,0x00101d0ae2eaceea,0x00246ab3f837b66a,0x00d5216d381ff530)},
- }}, {{
- {FIELD_LITERAL(0x0057e7ea35f36dae,0x00f47d7ad15de22e,0x00d757ea4b105115,0x008311457d579d7e,0x00b49b75b1edd4eb,0x0081c7ff742fd63a,0x00ddda3187433df6,0x00475727d55f9c66)},
- {FIELD_LITERAL(0x00a6295218dc136a,0x00563b3af0e9c012,0x00d3753b0145db1b,0x004550389c043dc1,0x00ea94ae27401bdf,0x002b0b949f2b7956,0x00c63f780ad8e23c,0x00e591c47d6bab15)},
- {FIELD_LITERAL(0x00416c582b058eb6,0x004107da5b2cc695,0x00b3cd2556aeec64,0x00c0b418267e57a1,0x001799293579bd2e,0x0046ed44590e4d07,0x001d7459b3630a1e,0x00c6afba8b6696aa)},
- }}, {{
- {FIELD_LITERAL(0x008d6009b26da3f8,0x00898e88ca06b1ca,0x00edb22b2ed7fe62,0x00fbc93516aabe80,0x008b4b470c42ce0d,0x00e0032ba7d0dcbb,0x00d76da3a956ecc8,0x007f20fe74e3852a)},
- {FIELD_LITERAL(0x002419222c607674,0x00a7f23af89188b3,0x00ad127284e73d1c,0x008bba582fae1c51,0x00fc6aa7ca9ecab1,0x003df5319eb6c2ba,0x002a05af8a8b199a,0x004bf8354558407c)},
- {FIELD_LITERAL(0x00ce7d4a30f0fcbf,0x00d02c272629f03d,0x0048c001f7400bc2,0x002c21368011958d,0x0098a550391e96b5,0x002d80b66390f379,0x001fa878760cc785,0x001adfce54b613d5)},
- }}, {{
- {FIELD_LITERAL(0x001ed4dc71fa2523,0x005d0bff19bf9b5c,0x00c3801cee065a64,0x001ed0b504323fbf,0x0003ab9fdcbbc593,0x00df82070178b8d2,0x00a2bcaa9c251f85,0x00c628a3674bd02e)},
- {FIELD_LITERAL(0x006b7a0674f9f8de,0x00a742414e5c7cff,0x0041cbf3c6e13221,0x00e3a64fd207af24,0x0087c05f15fbe8d1,0x004c50936d9e8a33,0x001306ec21042b6d,0x00a4f4137d1141c2)},
- {FIELD_LITERAL(0x0009e6fb921568b0,0x00b3c60120219118,0x002a6c3460dd503a,0x009db1ef11654b54,0x0063e4bf0be79601,0x00670d34bb2592b9,0x00dcee2f6c4130ce,0x00b2682e88e77f54)},
- }}, {{
- {FIELD_LITERAL(0x000d5b4b3da135ab,0x00838f3e5064d81d,0x00d44eb50f6d94ed,0x0008931ab502ac6d,0x00debe01ca3d3586,0x0025c206775f0641,0x005ad4b6ae912763,0x007e2c318ad8f247)},
- {FIELD_LITERAL(0x00ddbe0750dd1add,0x004b3c7b885844b8,0x00363e7ecf12f1ae,0x0062e953e6438f9d,0x0023cc73b076afe9,0x00b09fa083b4da32,0x00c7c3d2456c541d,0x005b591ec6b694d4)},
- {FIELD_LITERAL(0x0028656e19d62fcf,0x0052a4af03df148d,0x00122765ddd14e42,0x00f2252904f67157,0x004741965b636f3a,0x006441d296132cb9,0x005e2106f956a5b7,0x00247029592d335c)},
- }}, {{
- {FIELD_LITERAL(0x003fe038eb92f894,0x000e6da1b72e8e32,0x003a1411bfcbe0fa,0x00b55d473164a9e4,0x00b9a775ac2df48d,0x0002ddf350659e21,0x00a279a69eb19cb3,0x00f844eab25cba44)},
- {FIELD_LITERAL(0x00c41d1f9c1f1ac1,0x007b2df4e9f19146,0x00b469355fd5ba7a,0x00b5e1965afc852a,0x00388d5f1e2d8217,0x0022079e4c09ae93,0x0014268acd4ef518,0x00c1dd8d9640464c)},
- {FIELD_LITERAL(0x0038526adeed0c55,0x00dd68c607e3fe85,0x00f746ddd48a5d57,0x0042f2952b963b7c,0x001cbbd6876d5ec2,0x005e341470bca5c2,0x00871d41e085f413,0x00e53ab098f45732)},
- }}, {{
- {FIELD_LITERAL(0x004d51124797c831,0x008f5ae3750347ad,0x0070ced94c1a0c8e,0x00f6db2043898e64,0x000d00c9a5750cd0,0x000741ec59bad712,0x003c9d11aab37b7f,0x00a67ba169807714)},
- {FIELD_LITERAL(0x00adb2c1566e8b8f,0x0096c68a35771a9a,0x00869933356f334a,0x00ba9c93459f5962,0x009ec73fb6e8ca4b,0x003c3802c27202e1,0x0031f5b733e0c008,0x00f9058c19611fa9)},
- {FIELD_LITERAL(0x00238f01814a3421,0x00c325a44b6cce28,0x002136f97aeb0e73,0x000cac8268a4afe2,0x0022fd218da471b3,0x009dcd8dfff8def9,0x00cb9f8181d999bb,0x00143ae56edea349)},
- }}, {{
- {FIELD_LITERAL(0x0000623bf87622c5,0x00a1966fdd069496,0x00c315b7b812f9fc,0x00bdf5efcd128b97,0x001d464f532e3e16,0x003cd94f081bfd7e,0x00ed9dae12ce4009,0x002756f5736eee70)},
- {FIELD_LITERAL(0x00a5187e6ee7341b,0x00e6d52e82d83b6e,0x00df3c41323094a7,0x00b3324f444e9de9,0x00689eb21a35bfe5,0x00f16363becd548d,0x00e187cc98e7f60f,0x00127d9062f0ccab)},
- {FIELD_LITERAL(0x004ad71b31c29e40,0x00a5fcace12fae29,0x004425b5597280ed,0x00e7ef5d716c3346,0x0010b53ada410ac8,0x0092310226060c9b,0x0091c26128729c7e,0x0088b42900f8ec3b)},
- }}, {{
- {FIELD_LITERAL(0x00f1e26e9762d4a8,0x00d9d74082183414,0x00ffec9bd57a0282,0x000919e128fd497a,0x00ab7ae7d00fe5f8,0x0054dc442851ff68,0x00c9ebeb3b861687,0x00507f7cab8b698f)},
- {FIELD_LITERAL(0x00c13c5aae3ae341,0x009c6c9ed98373e7,0x00098f26864577a8,0x0015b886e9488b45,0x0037692c42aadba5,0x00b83170b8e7791c,0x001670952ece1b44,0x00fd932a39276da2)},
- {FIELD_LITERAL(0x0081a3259bef3398,0x005480fff416107b,0x00ce4f607d21be98,0x003ffc084b41df9b,0x0043d0bb100502d1,0x00ec35f575ba3261,0x00ca18f677300ef3,0x00e8bb0a827d8548)},
- }}, {{
- {FIELD_LITERAL(0x00df76b3328ada72,0x002e20621604a7c2,0x00f910638a105b09,0x00ef4724d96ef2cd,0x00377d83d6b8a2f7,0x00b4f48805ade324,0x001cd5da8b152018,0x0045af671a20ca7f)},
- {FIELD_LITERAL(0x009ae3b93a56c404,0x004a410b7a456699,0x00023a619355e6b2,0x009cdc7297387257,0x0055b94d4ae70d04,0x002cbd607f65b005,0x003208b489697166,0x00ea2aa058867370)},
- {FIELD_LITERAL(0x00f29d2598ee3f32,0x00b4ac5385d82adc,0x007633eaf04df19b,0x00aa2d3d77ceab01,0x004a2302fcbb778a,0x00927f225d5afa34,0x004a8e9d5047f237,0x008224ae9dbce530)},
- }}, {{
- {FIELD_LITERAL(0x001cf640859b02f8,0x00758d1d5d5ce427,0x00763c784ef4604c,0x005fa81aee205270,0x00ac537bfdfc44cb,0x004b919bd342d670,0x00238508d9bf4b7a,0x00154888795644f3)},
- {FIELD_LITERAL(0x00c845923c084294,0x00072419a201bc25,0x0045f408b5f8e669,0x00e9d6a186b74dfe,0x00e19108c68fa075,0x0017b91d874177b7,0x002f0ca2c7912c5a,0x009400aa385a90a2)},
- {FIELD_LITERAL(0x0071110b01482184,0x00cfed0044f2bef8,0x0034f2901cf4662e,0x003b4ae2a67f9834,0x00cca9b96fe94810,0x00522507ae77abd0,0x00bac7422721e73e,0x0066622b0f3a62b0)},
- }}, {{
- {FIELD_LITERAL(0x00f8ac5cf4705b6a,0x00867d82dcb457e3,0x007e13ab2ccc2ce9,0x009ee9a018d3930e,0x008370f8ecb42df8,0x002d9f019add263e,0x003302385b92d196,0x00a15654536e2c0c)},
- {FIELD_LITERAL(0x0026ef1614e160af,0x00c023f9edfc9c76,0x00cff090da5f57ba,0x0076db7a66643ae9,0x0019462f8c646999,0x008fec00b3854b22,0x00d55041692a0a1c,0x0065db894215ca00)},
- {FIELD_LITERAL(0x00a925036e0a451c,0x002a0390c36b6cc1,0x00f27020d90894f4,0x008d90d52cbd3d7f,0x00e1d0137392f3b8,0x00f017c158b51a8f,0x00cac313d3ed7dbc,0x00b99a81e3eb42d3)},
- }}, {{
- {FIELD_LITERAL(0x00b54850275fe626,0x0053a3fd1ec71140,0x00e3d2d7dbe096fa,0x00e4ac7b595cce4c,0x0077bad449c0a494,0x00b7c98814afd5b3,0x0057226f58486cf9,0x00b1557154f0cc57)},
- {FIELD_LITERAL(0x008cc9cd236315c0,0x0031d9c5b39fda54,0x00a5713ef37e1171,0x00293d5ae2886325,0x00c4aba3e05015e1,0x0003f35ef78e4fc6,0x0039d6bd3ac1527b,0x0019d7c3afb77106)},
- {FIELD_LITERAL(0x007b162931a985af,0x00ad40a2e0daa713,0x006df27c4009f118,0x00503e9f4e2e8bec,0x00751a77c82c182d,0x000298937769245b,0x00ffb1e8fabf9ee5,0x0008334706e09abe)},
- }}, {{
- {FIELD_LITERAL(0x00dbca4e98a7dcd9,0x00ee29cfc78bde99,0x00e4a3b6995f52e9,0x0045d70189ae8096,0x00fd2a8a3b9b0d1b,0x00af1793b107d8e1,0x00dbf92cbe4afa20,0x00da60f798e3681d)},
- {FIELD_LITERAL(0x004246bfcecc627a,0x004ba431246c03a4,0x00bd1d101872d497,0x003b73d3f185ee16,0x001feb2e2678c0e3,0x00ff13c5a89dec76,0x00ed06042e771d8f,0x00a4fd2a897a83dd)},
- {FIELD_LITERAL(0x009a4a3be50d6597,0x00de3165fc5a1096,0x004f3f56e345b0c7,0x00f7bf721d5ab8bc,0x004313e47b098c50,0x00e4c7d5c0e1adbb,0x002e3e3db365051e,0x00a480c2cd6a96fb)},
- }}, {{
- {FIELD_LITERAL(0x00417fa30a7119ed,0x00af257758419751,0x00d358a487b463d4,0x0089703cc720b00d,0x00ce56314ff7f271,0x0064db171ade62c1,0x00640b36d4a22fed,0x00424eb88696d23f)},
- {FIELD_LITERAL(0x004ede34af2813f3,0x00d4a8e11c9e8216,0x004796d5041de8a5,0x00c4c6b4d21cc987,0x00e8a433ee07fa1e,0x0055720b5abcc5a1,0x008873ea9c74b080,0x005b3fec1ab65d48)},
- {FIELD_LITERAL(0x0047e5277db70ec5,0x000a096c66db7d6b,0x00b4164cc1730159,0x004a9f783fe720fe,0x00a8177b94449dbc,0x0095a24ff49a599f,0x0069c1c578250cbc,0x00452019213debf4)},
- }}, {{
- {FIELD_LITERAL(0x0021ce99e09ebda3,0x00fcbd9f91875ad0,0x009bbf6b7b7a0b5f,0x00388886a69b1940,0x00926a56d0f81f12,0x00e12903c3358d46,0x005dfce4e8e1ce9d,0x0044cfa94e2f7e23)},
- {FIELD_LITERAL(0x001bd59c09e982ea,0x00f72daeb937b289,0x0018b76dca908e0e,0x00edb498512384ad,0x00ce0243b6cc9538,0x00f96ff690cb4e70,0x007c77bf9f673c8d,0x005bf704c088a528)},
- {FIELD_LITERAL(0x0093d4628dcb33be,0x0095263d51d42582,0x0049b3222458fe06,0x00e7fce73b653a7f,0x003ca2ebce60b369,0x00c5de239a32bea4,0x0063b8b3d71fb6bf,0x0039aeeb78a1a839)},
- }}, {{
- {FIELD_LITERAL(0x007dc52da400336c,0x001fded1e15b9457,0x00902e00f5568e3a,0x00219bef40456d2d,0x005684161fb3dbc9,0x004a4e9be49a76ea,0x006e685ae88b78ff,0x0021c42f13042d3c)},
- {FIELD_LITERAL(0x00fb22bb5fd3ce50,0x0017b48aada7ae54,0x00fd5c44ad19a536,0x000ccc4e4e55e45c,0x00fd637d45b4c3f5,0x0038914e023c37cf,0x00ac1881d6a8d898,0x00611ed8d3d943a8)},
- {FIELD_LITERAL(0x0056e2259d113d2b,0x00594819b284ec16,0x00c7bf794bb36696,0x00721ee75097cdc6,0x00f71be9047a2892,0x00df6ba142564edf,0x0069580b7a184e8d,0x00f056e38fca0fee)},
- }}, {{
- {FIELD_LITERAL(0x009df98566a18c6d,0x00cf3a200968f219,0x0044ba60da6d9086,0x00dbc9c0e344da03,0x000f9401c4466855,0x00d46a57c5b0a8d1,0x00875a635d7ac7c6,0x00ef4a933b7e0ae6)},
- {FIELD_LITERAL(0x005e8694077a1535,0x008bef75f71c8f1d,0x000a7c1316423511,0x00906e1d70604320,0x003fc46c1a2ffbd6,0x00d1d5022e68f360,0x002515fba37bbf46,0x00ca16234e023b44)},
- {FIELD_LITERAL(0x00787c99561f4690,0x00a857a8c1561f27,0x00a10df9223c09fe,0x00b98a9562e3b154,0x004330b8744c3ed2,0x00e06812807ec5c4,0x00e4cf6a7db9f1e3,0x00d95b089f132a34)},
- }}, {{
- {FIELD_LITERAL(0x002922b39ca33eec,0x0090d12a5f3ab194,0x00ab60c02fb5f8ed,0x00188d292abba1cf,0x00e10edec9698f6e,0x0069a4d9934133c8,0x0024aac40e6d3d06,0x001702c2177661b0)},
- {FIELD_LITERAL(0x00139078397030bd,0x000e3c447e859a00,0x0064a5b334c82393,0x00b8aabeb7358093,0x00020778bb9ae73b,0x0032ee94c7892a18,0x008215253cb41bda,0x005e2797593517ae)},
- {FIELD_LITERAL(0x0083765a5f855d4a,0x0051b6d1351b8ee2,0x00116de548b0f7bb,0x0087bd88703affa0,0x0095b2cc34d7fdd2,0x0084cd81b53f0bc8,0x008562fc995350ed,0x00a39abb193651e3)},
- }}, {{
- {FIELD_LITERAL(0x0019e23f0474b114,0x00eb94c2ad3b437e,0x006ddb34683b75ac,0x00391f9209b564c6,0x00083b3bb3bff7aa,0x00eedcd0f6dceefc,0x00b50817f794fe01,0x0036474deaaa75c9)},
- {FIELD_LITERAL(0x0091868594265aa2,0x00797accae98ca6d,0x0008d8c5f0f8a184,0x00d1f4f1c2b2fe6e,0x0036783dfb48a006,0x008c165120503527,0x0025fd780058ce9b,0x0068beb007be7d27)},
- {FIELD_LITERAL(0x00d0ff88aa7c90c2,0x00b2c60dacf53394,0x0094a7284d9666d6,0x00bed9022ce7a19d,0x00c51553f0cd7682,0x00c3fb870b124992,0x008d0bc539956c9b,0x00fc8cf258bb8885)},
- }}, {{
- {FIELD_LITERAL(0x003667bf998406f8,0x0000115c43a12975,0x001e662f3b20e8fd,0x0019ffa534cb24eb,0x00016be0dc8efb45,0x00ff76a8b26243f5,0x00ae20d241a541e3,0x0069bd6af13cd430)},
- {FIELD_LITERAL(0x0045fdc16487cda3,0x00b2d8e844cf2ed7,0x00612c50e88c1607,0x00a08aabc66c1672,0x006031fdcbb24d97,0x001b639525744b93,0x004409d62639ab17,0x00a1853d0347ab1d)},
- {FIELD_LITERAL(0x0075a1a56ebf5c21,0x00a3e72be9ac53ed,0x00efcde1629170c2,0x0004225fe91ef535,0x0088049fc73dfda7,0x004abc74857e1288,0x0024e2434657317c,0x00d98cb3d3e5543c)},
- }}, {{
- {FIELD_LITERAL(0x00b4b53eab6bdb19,0x009b22d8b43711d0,0x00d948b9d961785d,0x00cb167b6f279ead,0x00191de3a678e1c9,0x00d9dd9511095c2e,0x00f284324cd43067,0x00ed74fa535151dd)},
- {FIELD_LITERAL(0x007e32c049b5c477,0x009d2bfdbd9bcfd8,0x00636e93045938c6,0x007fde4af7687298,0x0046a5184fafa5d3,0x0079b1e7f13a359b,0x00875adf1fb927d6,0x00333e21c61bcad2)},
- {FIELD_LITERAL(0x00048014f73d8b8d,0x0075684aa0966388,0x0092be7df06dc47c,0x0097cebcd0f5568a,0x005a7004d9c4c6a9,0x00b0ecbb659924c7,0x00d90332dd492a7c,0x0057fc14df11493d)},
- }}, {{
- {FIELD_LITERAL(0x0008ed8ea0ad95be,0x0041d324b9709645,0x00e25412257a19b4,0x0058df9f3423d8d2,0x00a9ab20def71304,0x009ae0dbf8ac4a81,0x00c9565977e4392a,0x003c9269444baf55)},
- {FIELD_LITERAL(0x007df6cbb926830b,0x00d336058ae37865,0x007af47dac696423,0x0048d3011ec64ac8,0x006b87666e40049f,0x0036a2e0e51303d7,0x00ba319bd79dbc55,0x003e2737ecc94f53)},
- {FIELD_LITERAL(0x00d296ff726272d9,0x00f6d097928fcf57,0x00e0e616a55d7013,0x00deaf454ed9eac7,0x0073a56bedef4d92,0x006ccfdf6fc92e19,0x009d1ee1371a7218,0x00ee3c2ee4462d80)},
- }}, {{
- {FIELD_LITERAL(0x00437bce9bccdf9d,0x00e0c8e2f85dc0a3,0x00c91a7073995a19,0x00856ec9fe294559,0x009e4b33394b156e,0x00e245b0dc497e5c,0x006a54e687eeaeff,0x00f1cd1cd00fdb7c)},
- {FIELD_LITERAL(0x008132ae5c5d8cd1,0x00121d68324a1d9f,0x00d6be9dafcb8c76,0x00684d9070edf745,0x00519fbc96d7448e,0x00388182fdc1f27e,0x000235baed41f158,0x00bf6cf6f1a1796a)},
- {FIELD_LITERAL(0x002adc4b4d148219,0x003084ada0d3a90a,0x0046de8aab0f2e4e,0x00452d342a67b5fd,0x00d4b50f01d4de21,0x00db6d9fc0cefb79,0x008c184c86a462cd,0x00e17c83764d42da)},
- }}, {{
- {FIELD_LITERAL(0x007b2743b9a1e01a,0x007847ffd42688c4,0x006c7844d610a316,0x00f0cb8b250aa4b0,0x00a19060143b3ae6,0x0014eb10b77cfd80,0x000170905729dd06,0x00063b5b9cd72477)},
- {FIELD_LITERAL(0x00ce382dc7993d92,0x00021153e938b4c8,0x00096f7567f48f51,0x0058f81ddfe4b0d5,0x00cc379a56b355c7,0x002c760770d3e819,0x00ee22d1d26e5a40,0x00de6d93d5b082d7)},
- {FIELD_LITERAL(0x000a91a42c52e056,0x00185f6b77fce7ea,0x000803c51962f6b5,0x0022528582ba563d,0x0043f8040e9856d6,0x0085a29ec81fb860,0x005f9a611549f5ff,0x00c1f974ecbd4b06)},
- }}, {{
- {FIELD_LITERAL(0x005b64c6fd65ec97,0x00c1fdd7f877bc7f,0x000d9cc6c89f841c,0x005c97b7f1aff9ad,0x0075e3c61475d47e,0x001ecb1ba8153011,0x00fe7f1c8d71d40d,0x003fa9757a229832)},
- {FIELD_LITERAL(0x00ffc5c89d2b0cba,0x00d363d42e3e6fc3,0x0019a1a0118e2e8a,0x00f7baeff48882e1,0x001bd5af28c6b514,0x0055476ca2253cb2,0x00d8eb1977e2ddf3,0x00b173b1adb228a1)},
- {FIELD_LITERAL(0x00f2cb99dd0ad707,0x00e1e08b6859ddd8,0x000008f2d0650bcc,0x00d7ed392f8615c3,0x00976750a94da27f,0x003e83bb0ecb69ba,0x00df8e8d15c14ac6,0x00f9f7174295d9c2)},
- }}, {{
- {FIELD_LITERAL(0x00f11cc8e0e70bcb,0x00e5dc689974e7dd,0x0014e409f9ee5870,0x00826e6689acbd63,0x008a6f4e3d895d88,0x00b26a8da41fd4ad,0x000fb7723f83efd7,0x009c749db0a5f6c3)},
- {FIELD_LITERAL(0x002389319450f9ba,0x003677f31aa1250a,0x0092c3db642f38cb,0x00f8b64c0dfc9773,0x00cd49fe3505b795,0x0068105a4090a510,0x00df0ba2072a8bb6,0x00eb396143afd8be)},
- {FIELD_LITERAL(0x00a0d4ecfb24cdff,0x00ddaf8008ba6479,0x00f0b3e36d4b0f44,0x003734bd3af1f146,0x00b87e2efc75527e,0x00d230df55ddab50,0x002613257ae56c1d,0x00bc0946d135934d)},
- }}, {{
- {FIELD_LITERAL(0x00468711bd994651,0x0033108fa67561bf,0x0089d760192a54b4,0x00adc433de9f1871,0x000467d05f36e050,0x007847e0f0579f7f,0x00a2314ad320052d,0x00b3a93649f0b243)},
- {FIELD_LITERAL(0x0067f8f0c4fe26c9,0x0079c4a3cc8f67b9,0x0082b1e62f23550d,0x00f2d409caefd7f5,0x0080e67dcdb26e81,0x0087ae993ea1f98a,0x00aa108becf61d03,0x001acf11efb608a3)},
- {FIELD_LITERAL(0x008225febbab50d9,0x00f3b605e4dd2083,0x00a32b28189e23d2,0x00d507e5e5eb4c97,0x005a1a84e302821f,0x0006f54c1c5f08c7,0x00a347c8cb2843f0,0x0009f73e9544bfa5)},
- }}, {{
- {FIELD_LITERAL(0x006c59c9ae744185,0x009fc32f1b4282cd,0x004d6348ca59b1ac,0x00105376881be067,0x00af4096013147dc,0x004abfb5a5cb3124,0x000d2a7f8626c354,0x009c6ed568e07431)},
- {FIELD_LITERAL(0x00e828333c297f8b,0x009ef3cf8c3f7e1f,0x00ab45f8fff31cb9,0x00c8b4178cb0b013,0x00d0c50dd3260a3f,0x0097126ac257f5bc,0x0042376cc90c705a,0x001d96fdb4a1071e)},
- {FIELD_LITERAL(0x00542d44d89ee1a8,0x00306642e0442d98,0x0090853872b87338,0x002362cbf22dc044,0x002c222adff663b8,0x0067c924495fcb79,0x000e621d983c977c,0x00df77a9eccb66fb)},
- }}, {{
- {FIELD_LITERAL(0x002809e4bbf1814a,0x00b9e854f9fafb32,0x00d35e67c10f7a67,0x008f1bcb76e748cf,0x004224d9515687d2,0x005ba0b774e620c4,0x00b5e57db5d54119,0x00e15babe5683282)},
- {FIELD_LITERAL(0x00832d02369b482c,0x00cba52ff0d93450,0x003fa9c908d554db,0x008d1e357b54122f,0x00abd91c2dc950c6,0x007eff1df4c0ec69,0x003f6aeb13fb2d31,0x00002d6179fc5b2c)},
- {FIELD_LITERAL(0x0046c9eda81c9c89,0x00b60cb71c8f62fc,0x0022f5a683baa558,0x00f87319fccdf997,0x009ca09b51ce6a22,0x005b12baf4af7d77,0x008a46524a1e33e2,0x00035a77e988be0d)},
- }}, {{
- {FIELD_LITERAL(0x00a7efe46a7dbe2f,0x002f66fd55014fe7,0x006a428afa1ff026,0x0056caaa9604ab72,0x0033f3bcd7fac8ae,0x00ccb1aa01c86764,0x00158d1edf13bf40,0x009848ee76fcf3b4)},
- {FIELD_LITERAL(0x00a9e7730a819691,0x00d9cc73c4992b70,0x00e299bde067de5a,0x008c314eb705192a,0x00e7226f17e8a3cc,0x0029dfd956e65a47,0x0053a8e839073b12,0x006f942b2ab1597e)},
- {FIELD_LITERAL(0x001c3d780ecd5e39,0x0094f247fbdcc5fe,0x00d5c786fd527764,0x00b6f4da74f0db2a,0x0080f1f8badcd5fc,0x00f36a373ad2e23b,0x00f804f9f4343bf2,0x00d1af40ec623982)},
- }}, {{
- {FIELD_LITERAL(0x0082aeace5f1b144,0x00f68b3108cf4dd3,0x00634af01dde3020,0x000beab5df5c2355,0x00e8b790d1b49b0b,0x00e48d15854e36f4,0x0040ab2d95f3db9f,0x002711c4ed9e899a)},
- {FIELD_LITERAL(0x0039343746531ebe,0x00c8509d835d429d,0x00e79eceff6b0018,0x004abfd31e8efce5,0x007bbfaaa1e20210,0x00e3be89c193e179,0x001c420f4c31d585,0x00f414a315bef5ae)},
- {FIELD_LITERAL(0x007c296a24990df8,0x00d5d07525a75588,0x00dd8e113e94b7e7,0x007bbc58febe0cc8,0x0029f51af9bfcad3,0x007e9311ec7ab6f3,0x009a884de1676343,0x0050d5f2dce84be9)},
- }}, {{
- {FIELD_LITERAL(0x005fa020cca2450a,0x00491c29db6416d8,0x0037cefe3f9f9a85,0x003d405230647066,0x0049e835f0fdbe89,0x00feb78ac1a0815c,0x00828e4b32dc9724,0x00db84f2dc8d6fd4)},
- {FIELD_LITERAL(0x0098cddc8b39549a,0x006da37e3b05d22c,0x00ce633cfd4eb3cb,0x00fda288ef526acd,0x0025338878c5d30a,0x00f34438c4e5a1b4,0x00584efea7c310f1,0x0041a551f1b660ad)},
- {FIELD_LITERAL(0x00d7f7a8fbd6437a,0x0062872413bf3753,0x00ad4bbcb43c584b,0x007fe49be601d7e3,0x0077c659789babf4,0x00eb45fcb06a741b,0x005ce244913f9708,0x0088426401736326)},
- }}, {{
- {FIELD_LITERAL(0x007bf562ca768d7c,0x006c1f3a174e387c,0x00f024b447fee939,0x007e7af75f01143f,0x003adb70b4eed89d,0x00e43544021ad79a,0x0091f7f7042011f6,0x0093c1a1ee3a0ddc)},
- {FIELD_LITERAL(0x00a0b68ec1eb72d2,0x002c03235c0d45a0,0x00553627323fe8c5,0x006186e94b17af94,0x00a9906196e29f14,0x0025b3aee6567733,0x007e0dd840080517,0x0018eb5801a4ba93)},
- {FIELD_LITERAL(0x00d7fe7017bf6a40,0x006e3f0624be0c42,0x00ffbba205358245,0x00f9fc2cf8194239,0x008d93b37bf15b4e,0x006ddf2e38be8e95,0x002b6e79bf5fcff9,0x00ab355da425e2de)},
- }}, {{
- {FIELD_LITERAL(0x00938f97e20be973,0x0099141a36aaf306,0x0057b0ca29e545a1,0x0085db571f9fbc13,0x008b333c554b4693,0x0043ab6ef3e241cb,0x0054fb20aa1e5c70,0x00be0ff852760adf)},
- {FIELD_LITERAL(0x003973d8938971d6,0x002aca26fa80c1f5,0x00108af1faa6b513,0x00daae275d7924e6,0x0053634ced721308,0x00d2355fe0bbd443,0x00357612b2d22095,0x00f9bb9dd4136cf3)},
- {FIELD_LITERAL(0x002bff12cf5e03a5,0x001bdb1fa8a19cf8,0x00c91c6793f84d39,0x00f869f1b2eba9af,0x0059bc547dc3236b,0x00d91611d6d38689,0x00e062daaa2c0214,0x00ed3c047cc2bc82)},
- }}, {{
- {FIELD_LITERAL(0x000050d70c32b31a,0x001939d576d437b3,0x00d709e598bf9fe6,0x00a885b34bd2ee9e,0x00dd4b5c08ab1a50,0x0091bebd50b55639,0x00cf79ff64acdbc6,0x006067a39d826336)},
- {FIELD_LITERAL(0x0062dd0fb31be374,0x00fcc96b84c8e727,0x003f64f1375e6ae3,0x0057d9b6dd1af004,0x00d6a167b1103c7b,0x00dd28f3180fb537,0x004ff27ad7167128,0x008934c33461f2ac)},
- {FIELD_LITERAL(0x0065b472b7900043,0x00ba7efd2ff1064b,0x000b67d6c4c3020f,0x0012d28469f4e46d,0x0031c32939703ec7,0x00b49f0bce133066,0x00f7e10416181d47,0x005c90f51867eecc)},
- }}, {{
- {FIELD_LITERAL(0x0051207abd179101,0x00fc2a5c20d9c5da,0x00fb9d5f2701b6df,0x002dd040fdea82b8,0x00f163b0738442ff,0x00d9736bd68855b8,0x00e0d8e93005e61c,0x00df5a40b3988570)},
- {FIELD_LITERAL(0x0006918f5dfce6dc,0x00d4bf1c793c57fb,0x0069a3f649435364,0x00e89a50e5b0cd6e,0x00b9f6a237e973af,0x006d4ed8b104e41d,0x00498946a3924cd2,0x00c136ec5ac9d4f7)},
- {FIELD_LITERAL(0x0011a9c290ac5336,0x002b9a2d4a6a6533,0x009a8a68c445d937,0x00361b27b07e5e5c,0x003c043b1755b974,0x00b7eb66cf1155ee,0x0077af5909eefff2,0x0098f609877cc806)},
- }}, {{
- {FIELD_LITERAL(0x00ab13af436bf8f4,0x000bcf0a0dac8574,0x00d50c864f705045,0x00c40e611debc842,0x0085010489bd5caa,0x007c5050acec026f,0x00f67d943c8da6d1,0x00de1da0278074c6)},
- {FIELD_LITERAL(0x00b373076597455f,0x00e83f1af53ac0f5,0x0041f63c01dc6840,0x0097dea19b0c6f4b,0x007f9d63b4c1572c,0x00e692d492d0f5f0,0x00cbcb392e83b4ad,0x0069c0f39ed9b1a8)},
- {FIELD_LITERAL(0x00861030012707c9,0x009fbbdc7fd4aafb,0x008f591d6b554822,0x00df08a41ea18ade,0x009d7d83e642abea,0x0098c71bda3b78ff,0x0022c89e7021f005,0x0044d29a3fe1e3c4)},
- }}, {{
- {FIELD_LITERAL(0x00e748cd7b5c52f2,0x00ea9df883f89cc3,0x0018970df156b6c7,0x00c5a46c2a33a847,0x00cbde395e32aa09,0x0072474ebb423140,0x00fb00053086a23d,0x001dafcfe22d4e1f)},
- {FIELD_LITERAL(0x00c903ee6d825540,0x00add6c4cf98473e,0x007636efed4227f1,0x00905124ae55e772,0x00e6b38fab12ed53,0x0045e132b863fe55,0x003974662edb366a,0x00b1787052be8208)},
- {FIELD_LITERAL(0x00a614b00d775c7c,0x00d7c78941cc7754,0x00422dd68b5dabc4,0x00a6110f0167d28b,0x00685a309c252886,0x00b439ffd5143660,0x003656e29ee7396f,0x00c7c9b9ed5ad854)},
- }}, {{
- {FIELD_LITERAL(0x0040f7e7c5b37bf2,0x0064e4dc81181bba,0x00a8767ae2a366b6,0x001496b4f90546f2,0x002a28493f860441,0x0021f59513049a3a,0x00852d369a8b7ee3,0x00dd2e7d8b7d30a9)},
- {FIELD_LITERAL(0x00006e34a35d9fbc,0x00eee4e48b2f019a,0x006b344743003a5f,0x00541d514f04a7e3,0x00e81f9ee7647455,0x005e2b916c438f81,0x00116f8137b7eff0,0x009bd3decc7039d1)},
- {FIELD_LITERAL(0x0005d226f434110d,0x00af8288b8ef21d5,0x004a7a52ef181c8c,0x00be0b781b4b06de,0x00e6e3627ded07e1,0x00e43aa342272b8b,0x00e86ab424577d84,0x00fb292c566e35bb)},
- }}, {{
- {FIELD_LITERAL(0x00334f5303ea1222,0x00dfb3dbeb0a5d3e,0x002940d9592335c1,0x00706a7a63e8938a,0x005a533558bc4caf,0x00558e33192022a9,0x00970d9faf74c133,0x002979fcb63493ca)},
- {FIELD_LITERAL(0x00e38abece3c82ab,0x005a51f18a2c7a86,0x009dafa2e86d592e,0x00495a62eb688678,0x00b79df74c0eb212,0x0023e8cc78b75982,0x005998cb91075e13,0x00735aa9ba61bc76)},
- {FIELD_LITERAL(0x00d9f7a82ddbe628,0x00a1fc782889ae0f,0x0071ffda12d14b66,0x0037cf4eca7fb3d5,0x00c80bc242c58808,0x0075bf8c2d08c863,0x008d41f31afc52a7,0x00197962ecf38741)},
- }}, {{
- {FIELD_LITERAL(0x006e9f475cccf2ee,0x00454b9cd506430c,0x00224a4fb79ee479,0x0062e3347ef0b5e2,0x0034fd2a3512232a,0x00b8b3cb0f457046,0x00eb20165daa38ec,0x00128eebc2d9c0f7)},
- {FIELD_LITERAL(0x00bfc5fa1e4ea21f,0x00c21d7b6bb892e6,0x00cf043f3acf0291,0x00c13f2f849b3c90,0x00d1a97ebef10891,0x0061e130a445e7fe,0x0019513fdedbf22b,0x001d60c813bff841)},
- {FIELD_LITERAL(0x0019561c7fcf0213,0x00e3dca6843ebd77,0x0068ea95b9ca920e,0x009bdfb70f253595,0x00c68f59186aa02a,0x005aee1cca1c3039,0x00ab79a8a937a1ce,0x00b9a0e549959e6f)},
- }}, {{
- {FIELD_LITERAL(0x00c79e0b6d97dfbd,0x00917c71fd2bc6e8,0x00db7529ccfb63d8,0x00be5be957f17866,0x00a9e11fdc2cdac1,0x007b91a8e1f44443,0x00a3065e4057d80f,0x004825f5b8d5f6d4)},
- {FIELD_LITERAL(0x003e4964fa8a8fc8,0x00f6a1cdbcf41689,0x00943cb18fe7fda7,0x00606dafbf34440a,0x005d37a86399c789,0x00e79a2a69417403,0x00fe34f7e68b8866,0x0011f448ed2df10e)},
- {FIELD_LITERAL(0x00f1f57efcc1fcc4,0x00513679117de154,0x002e5b5b7c86d8c3,0x009f6486561f9cfb,0x00169e74b0170cf7,0x00900205af4af696,0x006acfddb77853f3,0x00df184c90f31068)},
- }}, {{
- {FIELD_LITERAL(0x00b37396c3320791,0x00fc7b67175c5783,0x00c36d2cd73ecc38,0x0080ebcc0b328fc5,0x0043a5b22b35d35d,0x00466c9f1713c9da,0x0026ad346dcaa8da,0x007c684e701183a6)},
- {FIELD_LITERAL(0x00fd579ffb691713,0x00b76af4f81c412d,0x00f239de96110f82,0x00e965fb437f0306,0x00ca7e9436900921,0x00e487f1325fa24a,0x00633907de476380,0x00721c62ac5b8ea0)},
- {FIELD_LITERAL(0x00c0d54e542eb4f9,0x004ed657171c8dcf,0x00b743a4f7c2a39b,0x00fd9f93ed6cc567,0x00307fae3113e58b,0x0058aa577c93c319,0x00d254556f35b346,0x00491aada2203f0d)},
- }}, {{
- {FIELD_LITERAL(0x00dff3103786ff34,0x000144553b1f20c3,0x0095613baeb930e4,0x00098058275ea5d4,0x007cd1402b046756,0x0074d74e4d58aee3,0x005f93fc343ff69b,0x00873df17296b3b0)},
- {FIELD_LITERAL(0x00c4a1fb48635413,0x00b5dd54423ad59f,0x009ff5d53fd24a88,0x003c98d267fc06a7,0x002db7cb20013641,0x00bd1d6716e191f2,0x006dbc8b29094241,0x0044bbf233dafa2c)},
- {FIELD_LITERAL(0x0055838d41f531e6,0x00bf6a2dd03c81b2,0x005827a061c4839e,0x0000de2cbb36aac3,0x002efa29d9717478,0x00f9e928cc8a77ba,0x00c134b458def9ef,0x00958a182223fc48)},
- }}, {{
- {FIELD_LITERAL(0x000a9ee23c06881f,0x002c727d3d871945,0x00f47d971512d24a,0x00671e816f9ef31a,0x00883af2cfaad673,0x00601f98583d6c9a,0x00b435f5adc79655,0x00ad87b71c04bff2)},
- {FIELD_LITERAL(0x007860d99db787cf,0x00fda8983018f4a8,0x008c8866bac4743c,0x00ef471f84c82a3f,0x00abea5976d3b8e7,0x00714882896cd015,0x00b49fae584ddac5,0x008e33a1a0b69c81)},
- {FIELD_LITERAL(0x007b6ee2c9e8a9ec,0x002455dbbd89d622,0x006490cf4eaab038,0x00d925f6c3081561,0x00153b3047de7382,0x003b421f8bdceb6f,0x00761a4a5049da78,0x00980348c5202433)},
- }}, {{
- {FIELD_LITERAL(0x007f8a43da97dd5c,0x00058539c800fc7b,0x0040f3cf5a28414a,0x00d68dd0d95283d6,0x004adce9da90146e,0x00befa41c7d4f908,0x007603bc2e3c3060,0x00bdf360ab3545db)},
- {FIELD_LITERAL(0x00eebfd4e2312cc3,0x00474b2564e4fc8c,0x003303ef14b1da9b,0x003c93e0e66beb1d,0x0013619b0566925a,0x008817c24d901bf3,0x00b62bd8898d218b,0x0075a7716f1e88a2)},
- {FIELD_LITERAL(0x0009218da1e6890f,0x0026907f5fd02575,0x004dabed5f19d605,0x003abf181870249d,0x00b52fd048cc92c4,0x00b6dd51e415a5c5,0x00d9eb82bd2b4014,0x002c865a43b46b43)},
- }}, {{
- {FIELD_LITERAL(0x0070047189452f4c,0x00f7ad12e1ce78d5,0x00af1ba51ec44a8b,0x005f39f63e667cd6,0x00058eac4648425e,0x00d7fdab42bea03b,0x0028576a5688de15,0x00af973209e77c10)},
- {FIELD_LITERAL(0x00c338b915d8fef0,0x00a893292045c39a,0x0028ab4f2eba6887,0x0060743cb519fd61,0x0006213964093ac0,0x007c0b7a43f6266d,0x008e3557c4fa5bda,0x002da976de7b8d9d)},
- {FIELD_LITERAL(0x0048729f8a8b6dcd,0x00fe23b85cc4d323,0x00e7384d16e4db0e,0x004a423970678942,0x00ec0b763345d4ba,0x00c477b9f99ed721,0x00c29dad3777b230,0x001c517b466f7df6)},
- }}, {{
- {FIELD_LITERAL(0x006366c380f7b574,0x001c7d1f09ff0438,0x003e20a7301f5b22,0x00d3efb1916d28f6,0x0049f4f81060ce83,0x00c69d91ea43ced1,0x002b6f3e5cd269ed,0x005b0fb22ce9ec65)},
- {FIELD_LITERAL(0x00aa2261022d883f,0x00ebcca4548010ac,0x002528512e28a437,0x0070ca7676b66082,0x0084bda170f7c6d3,0x00581b4747c9b8bb,0x005c96a01061c7e2,0x00fb7c4a362b5273)},
- {FIELD_LITERAL(0x00c30020eb512d02,0x0060f288283a4d26,0x00b7ed13becde260,0x0075ebb74220f6e9,0x00701079fcfe8a1f,0x001c28fcdff58938,0x002e4544b8f4df6b,0x0060c5bc4f1a7d73)},
- }}, {{
- {FIELD_LITERAL(0x00ae307cf069f701,0x005859f222dd618b,0x00212d6c46ec0b0d,0x00a0fe4642afb62d,0x00420d8e4a0a8903,0x00a80ff639bdf7b0,0x0019bee1490b5d8e,0x007439e4b9c27a86)},
- {FIELD_LITERAL(0x00a94700032a093f,0x0076e96c225216e7,0x00a63a4316e45f91,0x007d8bbb4645d3b2,0x00340a6ff22793eb,0x006f935d4572aeb7,0x00b1fb69f00afa28,0x009e8f3423161ed3)},
- {FIELD_LITERAL(0x009ef49c6b5ced17,0x00a555e6269e9f0a,0x007e6f1d79ec73b5,0x009ac78695a32ac4,0x0001d77fbbcd5682,0x008cea1fee0aaeed,0x00f42bea82a53462,0x002e46ab96cafcc9)},
- }}, {{
- {FIELD_LITERAL(0x0051cfcc5885377a,0x00dce566cb1803ca,0x00430c7643f2c7d4,0x00dce1a1337bdcc0,0x0010d5bd7283c128,0x003b1b547f9b46fe,0x000f245e37e770ab,0x007b72511f022b37)},
- {FIELD_LITERAL(0x0060db815bc4786c,0x006fab25beedc434,0x00c610d06084797c,0x000c48f08537bec0,0x0031aba51c5b93da,0x007968fa6e01f347,0x0030070da52840c6,0x00c043c225a4837f)},
- {FIELD_LITERAL(0x001bcfd00649ee93,0x006dceb47e2a0fd5,0x00f2cebda0cf8fd0,0x00b6b9d9d1fbdec3,0x00815262e6490611,0x00ef7f5ce3176760,0x00e49cd0c998d58b,0x005fc6cc269ba57c)},
- }}, {{
- {FIELD_LITERAL(0x008940211aa0d633,0x00addae28136571d,0x00d68fdbba20d673,0x003bc6129bc9e21a,0x000346cf184ebe9a,0x0068774d741ebc7f,0x0019d5e9e6966557,0x0003cbd7f981b651)},
- {FIELD_LITERAL(0x004a2902926f8d3f,0x00ad79b42637ab75,0x0088f60b90f2d4e8,0x0030f54ef0e398c4,0x00021dc9bf99681e,0x007ebf66fde74ee3,0x004ade654386e9a4,0x00e7485066be4c27)},
- {FIELD_LITERAL(0x00445f1263983be0,0x004cf371dda45e6a,0x00744a89d5a310e7,0x001f20ce4f904833,0x00e746edebe66e29,0x000912ab1f6c153d,0x00f61d77d9b2444c,0x0001499cd6647610)},
+ {FIELD_LITERAL(0x00cc3b062366f4ccULL, 0x003d6e34e314aa3cULL,
+ 0x00d51c0a7521774dULL, 0x0094e060eec6ab8bULL,
+ 0x00d21291b4d80082ULL, 0x00befed12b55ef1eULL,
+ 0x00c3dd2df5c94518ULL, 0x00e0a7b112b8d4e6ULL)},
+ {FIELD_LITERAL(0x0019eb5608d8723aULL, 0x00d1bab52fb3aedbULL,
+ 0x00270a7311ebc90cULL, 0x0037c12b91be7f13ULL,
+ 0x005be16cd8b5c704ULL, 0x003e181acda888e1ULL,
+ 0x00bc1f00fc3fc6d0ULL, 0x00d3839bfa319e20ULL)},
+ {FIELD_LITERAL(0x003caeb88611909fULL, 0x00ea8b378c4df3d4ULL,
+ 0x00b3295b95a5a19aULL, 0x00a65f97514bdfb5ULL,
+ 0x00b39efba743cab1ULL, 0x0016ba98b862fd2dULL,
+ 0x0001508812ee71d7ULL, 0x000a75740eea114aULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00ebcf0eb649f823ULL, 0x00166d332e98ea03ULL,
+ 0x0059ddf64f5cd5f6ULL, 0x0047763123d9471bULL,
+ 0x00a64065c53ef62fULL, 0x00978e44c480153dULL,
+ 0x000b5b2a0265f194ULL, 0x0046a24b9f32965aULL)},
+ {FIELD_LITERAL(0x00b9eef787034df0ULL, 0x0020bc24de3390cdULL,
+ 0x000022160bae99bbULL, 0x00ae66e886e97946ULL,
+ 0x0048d4bbe02cbb8bULL, 0x0072ba97b34e38d4ULL,
+ 0x00eae7ec8f03e85aULL, 0x005ba92ecf808b2cULL)},
+ {FIELD_LITERAL(0x00c9cfbbe74258fdULL, 0x00843a979ea9eaa7ULL,
+ 0x000cbb4371cfbe90ULL, 0x0059bac8f7f0a628ULL,
+ 0x004b3dff882ff530ULL, 0x0011869df4d90733ULL,
+ 0x00595aa71f4abfc2ULL, 0x0070e2d38990c2e6ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00de2010c0a01733ULL, 0x00c739a612e24297ULL,
+ 0x00a7212643141d7cULL, 0x00f88444f6b67c11ULL,
+ 0x00484b7b16ec28f2ULL, 0x009c1b8856af9c68ULL,
+ 0x00ff4669591fe9d6ULL, 0x0054974be08a32c8ULL)},
+ {FIELD_LITERAL(0x0010de3fd682ceedULL, 0x008c07642d83ca4eULL,
+ 0x0013bb064e00a1ccULL, 0x009411ae27870e11ULL,
+ 0x00ea8e5b4d531223ULL, 0x0032fe7d2aaece2eULL,
+ 0x00d989e243e7bb41ULL, 0x000fe79a508e9b8bULL)},
+ {FIELD_LITERAL(0x005e0426b9bfc5b1ULL, 0x0041a5b1d29ee4faULL,
+ 0x0015b0def7774391ULL, 0x00bc164f1f51af01ULL,
+ 0x00d543b0942797b9ULL, 0x003c129b6398099cULL,
+ 0x002b114c6e5adf18ULL, 0x00b4e630e4018a7bULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00d490afc95f8420ULL, 0x00b096bf50c1d9b9ULL,
+ 0x00799fd707679866ULL, 0x007c74d9334afbeaULL,
+ 0x00efaa8be80ff4edULL, 0x0075c4943bb81694ULL,
+ 0x00c21c2fca161f36ULL, 0x00e77035d492bfeeULL)},
+ {FIELD_LITERAL(0x006658a190dd6661ULL, 0x00e0e9bab38609a6ULL,
+ 0x0028895c802237edULL, 0x006a0229c494f587ULL,
+ 0x002dcde96c9916b7ULL, 0x00d158822de16218ULL,
+ 0x00173b917a06856fULL, 0x00ca78a79ae07326ULL)},
+ {FIELD_LITERAL(0x00e35bfc79caced4ULL, 0x0087238a3e1fe3bbULL,
+ 0x00bcbf0ff4ceff5bULL, 0x00a19c1c94099b91ULL,
+ 0x0071e102b49db976ULL, 0x0059e3d004eada1eULL,
+ 0x008da78afa58a47eULL, 0x00579c8ebf269187ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00a16c2905eee75fULL, 0x009d4bcaea2c7e1dULL,
+ 0x00d3bd79bfad19dfULL, 0x0050da745193342cULL,
+ 0x006abdb8f6b29ab1ULL, 0x00a24fe0a4fef7efULL,
+ 0x0063730da1057dfbULL, 0x00a08c312c8eb108ULL)},
+ {FIELD_LITERAL(0x00b583be005375beULL, 0x00a40c8f8a4e3df4ULL,
+ 0x003fac4a8f5bdbf7ULL, 0x00d4481d872cd718ULL,
+ 0x004dc8749cdbaefeULL, 0x00cce740d5e5c975ULL,
+ 0x000b1c1f4241fd21ULL, 0x00a76de1b4e1cd07ULL)},
+ {FIELD_LITERAL(0x007a076500d30b62ULL, 0x000a6e117b7f090fULL,
+ 0x00c8712ae7eebd9aULL, 0x000fbd6c1d5f6ff7ULL,
+ 0x003a7977246ebf11ULL, 0x00166ed969c6600eULL,
+ 0x00aa42e469c98becULL, 0x00dc58f307cf0666ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x004b491f65a9a28bULL, 0x006a10309e8a55b7ULL,
+ 0x00b67210185187efULL, 0x00cf6497b12d9b8fULL,
+ 0x0085778c56e2b1baULL, 0x0015b4c07a814d85ULL,
+ 0x00686479e62da561ULL, 0x008de5d88f114916ULL)},
+ {FIELD_LITERAL(0x00e37c88d6bba7b1ULL, 0x003e4577e1b8d433ULL,
+ 0x0050d8ea5f510ec0ULL, 0x0042fc9f2da9ef59ULL,
+ 0x003bd074c1141420ULL, 0x00561b8b7b68774eULL,
+ 0x00232e5e5d1013a3ULL, 0x006b7f2cb3d7e73fULL)},
+ {FIELD_LITERAL(0x004bdd0f0b41e6a0ULL, 0x001773057c405d24ULL,
+ 0x006029f99915bd97ULL, 0x006a5ba70a17fe2fULL,
+ 0x0046111977df7e08ULL, 0x004d8124c89fb6b7ULL,
+ 0x00580983b2bb2724ULL, 0x00207bf330d6f3feULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007efdc93972a48bULL, 0x002f5e50e78d5feeULL,
+ 0x0080dc11d61c7fe5ULL, 0x0065aa598707245bULL,
+ 0x009abba2300641beULL, 0x000c68787656543aULL,
+ 0x00ffe0fef2dc0a17ULL, 0x00007ffbd6cb4f3aULL)},
+ {FIELD_LITERAL(0x0036012f2b836efcULL, 0x00458c126d6b5fbcULL,
+ 0x00a34436d719ad1eULL, 0x0097be6167117deaULL,
+ 0x0009c219c879cff3ULL, 0x0065564493e60755ULL,
+ 0x00993ac94a8cdec0ULL, 0x002d4885a4d0dbafULL)},
+ {FIELD_LITERAL(0x00598b60b4c068baULL, 0x00c547a0be7f1afdULL,
+ 0x009582164acf12afULL, 0x00af4acac4fbbe40ULL,
+ 0x005f6ca7c539121aULL, 0x003b6e752ebf9d66ULL,
+ 0x00f08a30d5cac5d4ULL, 0x00e399bb5f97c5a9ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007445a0409c0a66ULL, 0x00a65c369f3829c0ULL,
+ 0x0031d248a4f74826ULL, 0x006817f34defbe8eULL,
+ 0x00649741d95ebf2eULL, 0x00d46466ab16b397ULL,
+ 0x00fdc35703bee414ULL, 0x00343b43334525f8ULL)},
+ {FIELD_LITERAL(0x001796bea93f6401ULL, 0x00090c5a42e85269ULL,
+ 0x00672412ba1252edULL, 0x001201d47b6de7deULL,
+ 0x006877bccfe66497ULL, 0x00b554fd97a4c161ULL,
+ 0x009753f42dbac3cfULL, 0x00e983e3e378270aULL)},
+ {FIELD_LITERAL(0x00ac3eff18849872ULL, 0x00f0eea3bff05690ULL,
+ 0x00a6d72c21dd505dULL, 0x001b832642424169ULL,
+ 0x00a6813017b540e5ULL, 0x00a744bd71b385cdULL,
+ 0x0022a7d089130a7bULL, 0x004edeec9a133486ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00b2d6729196e8a9ULL, 0x0088a9bb2031cef4ULL,
+ 0x00579e7787dc1567ULL, 0x0030f49feb059190ULL,
+ 0x00a0b1d69c7f7d8fULL, 0x0040bdcc6d9d806fULL,
+ 0x00d76c4037edd095ULL, 0x00bbf24376415dd7ULL)},
+ {FIELD_LITERAL(0x00240465ff5a7197ULL, 0x00bb97e76caf27d0ULL,
+ 0x004b4edbf8116d39ULL, 0x001d8586f708cbaaULL,
+ 0x000f8ee8ff8e4a50ULL, 0x00dde5a1945dd622ULL,
+ 0x00e6fc1c0957e07cULL, 0x0041c9cdabfd88a0ULL)},
+ {FIELD_LITERAL(0x005344b0bf5b548cULL, 0x002957d0b705cc99ULL,
+ 0x00f586a70390553dULL, 0x0075b3229f583cc3ULL,
+ 0x00a1aa78227490e4ULL, 0x001bf09cf7957717ULL,
+ 0x00cf6bf344325f52ULL, 0x0065bd1c23ca3ecfULL)},
+ }}, {{
+ {FIELD_LITERAL(0x009bff3b3239363cULL, 0x00e17368796ef7c0ULL,
+ 0x00528b0fe0971f3aULL, 0x0008014fc8d4a095ULL,
+ 0x00d09f2e8a521ec4ULL, 0x006713ab5dde5987ULL,
+ 0x0003015758e0dbb1ULL, 0x00215999f1ba212dULL)},
+ {FIELD_LITERAL(0x002c88e93527da0eULL, 0x0077c78f3456aad5ULL,
+ 0x0071087a0a389d1cULL, 0x00934dac1fb96dbdULL,
+ 0x008470e801162697ULL, 0x005bc2196cd4ad49ULL,
+ 0x00e535601d5087c3ULL, 0x00769888700f497fULL)},
+ {FIELD_LITERAL(0x00da7a4b557298adULL, 0x0019d2589ea5df76ULL,
+ 0x00ef3e38be0c6497ULL, 0x00a9644e1312609aULL,
+ 0x004592f61b2558daULL, 0x0082c1df510d7e46ULL,
+ 0x0042809a535c0023ULL, 0x00215bcb5afd7757ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x002b9df55a1a4213ULL, 0x00dcfc3b464a26beULL,
+ 0x00c4f9e07a8144d5ULL, 0x00c8e0617a92b602ULL,
+ 0x008e3c93accafae0ULL, 0x00bf1bcb95b2ca60ULL,
+ 0x004ce2426a613bf3ULL, 0x00266cac58e40921ULL)},
+ {FIELD_LITERAL(0x008456d5db76e8f0ULL, 0x0032ca9cab2ce163ULL,
+ 0x0059f2b8bf91abcfULL, 0x0063c2a021712788ULL,
+ 0x00f86155af22f72dULL, 0x00db98b2a6c005a0ULL,
+ 0x00ac6e416a693ac4ULL, 0x007a93572af53226ULL)},
+ {FIELD_LITERAL(0x0087767520f0de22ULL, 0x0091f64012279fb5ULL,
+ 0x001050f1f0644999ULL, 0x004f097a2477ad3cULL,
+ 0x006b37913a9947bdULL, 0x001a3d78645af241ULL,
+ 0x0057832bbb3008a7ULL, 0x002c1d902b80dc20ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001a6002bf178877ULL, 0x009bce168aa5af50ULL,
+ 0x005fc318ff04a7f5ULL, 0x0052818f55c36461ULL,
+ 0x008768f5d4b24afbULL, 0x0037ffbae7b69c85ULL,
+ 0x0018195a4b61edc0ULL, 0x001e12ea088434b2ULL)},
+ {FIELD_LITERAL(0x0047d3f804e7ab07ULL, 0x00a809ab5f905260ULL,
+ 0x00b3ffc7cdaf306dULL, 0x00746e8ec2d6e509ULL,
+ 0x00d0dade8887a645ULL, 0x00acceeebde0dd37ULL,
+ 0x009bc2579054686bULL, 0x0023804f97f1c2bfULL)},
+ {FIELD_LITERAL(0x0043e2e2e50b80d7ULL, 0x00143aafe4427e0fULL,
+ 0x005594aaecab855bULL, 0x008b12ccaaecbc01ULL,
+ 0x002deeb091082bc3ULL, 0x009cca4be2ae7514ULL,
+ 0x00142b96e696d047ULL, 0x00ad2a2b1c05256aULL)},
+ }}, {{
+ {FIELD_LITERAL(0x003914f2f144b78bULL, 0x007a95dd8bee6f68ULL,
+ 0x00c7f4384d61c8e6ULL, 0x004e51eb60f1bdb2ULL,
+ 0x00f64be7aa4621d8ULL, 0x006797bfec2f0ac0ULL,
+ 0x007d17aab3c75900ULL, 0x001893e73cac8bc5ULL)},
+ {FIELD_LITERAL(0x00140360b768665bULL, 0x00b68aca4967f977ULL,
+ 0x0001089b66195ae4ULL, 0x00fe71122185e725ULL,
+ 0x000bca2618d49637ULL, 0x00a54f0557d7e98aULL,
+ 0x00cdcd2f91d6f417ULL, 0x00ab8c13741fd793ULL)},
+ {FIELD_LITERAL(0x00725ee6b1e549e0ULL, 0x007124a0769777faULL,
+ 0x000b68fdad07ae42ULL, 0x0085b909cd4952dfULL,
+ 0x0092d2e3c81606f4ULL, 0x009f22f6cac099a0ULL,
+ 0x00f59da57f2799a8ULL, 0x00f06c090122f777ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00ce0bed0a3532bcULL, 0x001a5048a22df16bULL,
+ 0x00e31db4cbad8bf1ULL, 0x00e89292120cf00eULL,
+ 0x007d1dd1a9b00034ULL, 0x00e2a9041ff8f680ULL,
+ 0x006a4c837ae596e7ULL, 0x00713af1068070b3ULL)},
+ {FIELD_LITERAL(0x00c4fe64ce66d04bULL, 0x00b095d52e09b3d7ULL,
+ 0x00758bbecb1a3a8eULL, 0x00f35cce8d0650c0ULL,
+ 0x002b878aa5984473ULL, 0x0062e0a3b7544ddcULL,
+ 0x00b25b290ed116feULL, 0x007b0f6abe0bebf2ULL)},
+ {FIELD_LITERAL(0x0081d4e3addae0a8ULL, 0x003410c836c7ffccULL,
+ 0x00c8129ad89e4314ULL, 0x000e3d5a23922dcdULL,
+ 0x00d91e46f29c31f3ULL, 0x006c728cde8c5947ULL,
+ 0x002bc655ba2566c0ULL, 0x002ca94721533108ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0051e4b3f764d8a9ULL, 0x0019792d46e904a0ULL,
+ 0x00853bc13dbc8227ULL, 0x000840208179f12dULL,
+ 0x0068243474879235ULL, 0x0013856fbfe374d0ULL,
+ 0x00bda12fe8676424ULL, 0x00bbb43635926eb2ULL)},
+ {FIELD_LITERAL(0x0012cdc880a93982ULL, 0x003c495b21cd1b58ULL,
+ 0x00b7e5c93f22a26eULL, 0x0044aa82dfb99458ULL,
+ 0x009ba092cdffe9c0ULL, 0x00a14b3ab2083b73ULL,
+ 0x000271c2f70e1c4bULL, 0x00eea9cac0f66eb8ULL)},
+ {FIELD_LITERAL(0x001a1847c4ac5480ULL, 0x00b1b412935bb03aULL,
+ 0x00f74285983bf2b2ULL, 0x00624138b5b5d0f1ULL,
+ 0x008820c0b03d38bfULL, 0x00b94e50a18c1572ULL,
+ 0x0060f6934841798fULL, 0x00c52f5d66d6ebe2ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00da23d59f9bcea6ULL, 0x00e0f27007a06a4bULL,
+ 0x00128b5b43a6758cULL, 0x000cf50190fa8b56ULL,
+ 0x00fc877aba2b2d72ULL, 0x00623bef52edf53fULL,
+ 0x00e6af6b819669e2ULL, 0x00e314dc34fcaa4fULL)},
+ {FIELD_LITERAL(0x0066e5eddd164d1eULL, 0x00418a7c6fe28238ULL,
+ 0x0002e2f37e962c25ULL, 0x00f01f56b5975306ULL,
+ 0x0048842fa503875cULL, 0x0057b0e968078143ULL,
+ 0x00ff683024f3d134ULL, 0x0082ae28fcad12e4ULL)},
+ {FIELD_LITERAL(0x0011ddfd21260e42ULL, 0x00d05b0319a76892ULL,
+ 0x00183ea4368e9b8fULL, 0x00b0815662affc96ULL,
+ 0x00b466a5e7ce7c88ULL, 0x00db93b07506e6eeULL,
+ 0x0033885f82f62401ULL, 0x0086f9090ec9b419ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00d95d1c5fcb435aULL, 0x0016d1ed6b5086f9ULL,
+ 0x00792aa0b7e54d71ULL, 0x0067b65715f1925dULL,
+ 0x00a219755ec6176bULL, 0x00bc3f026b12c28fULL,
+ 0x00700c897ffeb93eULL, 0x0089b83f6ec50b46ULL)},
+ {FIELD_LITERAL(0x003c97e6384da36eULL, 0x00423d53eac81a09ULL,
+ 0x00b70d68f3cdce35ULL, 0x00ee7959b354b92cULL,
+ 0x00f4e9718819c8caULL, 0x009349f12acbffe9ULL,
+ 0x005aee7b62cb7da6ULL, 0x00d97764154ffc86ULL)},
+ {FIELD_LITERAL(0x00526324babb46dcULL, 0x002ee99b38d7bf9eULL,
+ 0x007ea51794706ef4ULL, 0x00abeb04da6e3c39ULL,
+ 0x006b457c1d281060ULL, 0x00fe243e9a66c793ULL,
+ 0x00378de0fb6c6ee4ULL, 0x003e4194b9c3cb93ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00fed3cd80ca2292ULL, 0x0015b043a73ca613ULL,
+ 0x000a9fd7bf9be227ULL, 0x003b5e03de2db983ULL,
+ 0x005af72d46904ef7ULL, 0x00c0f1b5c49faa99ULL,
+ 0x00dc86fc3bd305e1ULL, 0x00c92f08c1cb1797ULL)},
+ {FIELD_LITERAL(0x0079680ce111ed3bULL, 0x001a1ed82806122cULL,
+ 0x000c2e7466d15df3ULL, 0x002c407f6f7150fdULL,
+ 0x00c5e7c96b1b0ce3ULL, 0x009aa44626863ff9ULL,
+ 0x00887b8b5b80be42ULL, 0x00b6023cec964825ULL)},
+ {FIELD_LITERAL(0x00e4a8e1048970c8ULL, 0x0062887b7830a302ULL,
+ 0x00bcf1c8cd81402bULL, 0x0056dbb81a68f5beULL,
+ 0x0014eced83f12452ULL, 0x00139e1a510150dfULL,
+ 0x00bb81140a82d1a3ULL, 0x000febcc1aaf1aa7ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00a7527958238159ULL, 0x0013ec9537a84cd6ULL,
+ 0x001d7fee7d562525ULL, 0x00b9eefa6191d5e5ULL,
+ 0x00dbc97db70bcb8aULL, 0x00481affc7a4d395ULL,
+ 0x006f73d3e70c31bbULL, 0x00183f324ed96a61ULL)},
+ {FIELD_LITERAL(0x0039dd7ce7fc6860ULL, 0x00d64f6425653da1ULL,
+ 0x003e037c7f57d0afULL, 0x0063477a06e2bcf2ULL,
+ 0x001727dbb7ac67e6ULL, 0x0049589f5efafe2eULL,
+ 0x00fc0fef2e813d54ULL, 0x008baa5d087fb50dULL)},
+ {FIELD_LITERAL(0x0024fb59d9b457c7ULL, 0x00a7d4e060223e4cULL,
+ 0x00c118d1b555fd80ULL, 0x0082e216c732f22aULL,
+ 0x00cd2a2993089504ULL, 0x003638e836a3e13dULL,
+ 0x000d855ee89b4729ULL, 0x008ec5b7d4810c91ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001bf51f7d65cdfdULL, 0x00d14cdafa16a97dULL,
+ 0x002c38e60fcd10e7ULL, 0x00a27446e393efbdULL,
+ 0x000b5d8946a71fddULL, 0x0063df2cde128f2fULL,
+ 0x006c8679569b1888ULL, 0x0059ffc4925d732dULL)},
+ {FIELD_LITERAL(0x00ece96f95f2b66fULL, 0x00ece7952813a27bULL,
+ 0x0026fc36592e489eULL, 0x007157d1a2de0f66ULL,
+ 0x00759dc111d86ddfULL, 0x0012881e5780bb0fULL,
+ 0x00c8ccc83ad29496ULL, 0x0012b9bd1929eb71ULL)},
+ {FIELD_LITERAL(0x000fa15a20da5df0ULL, 0x00349ddb1a46cd31ULL,
+ 0x002c512ad1d8e726ULL, 0x00047611f669318dULL,
+ 0x009e68fba591e17eULL, 0x004320dffa803906ULL,
+ 0x00a640874951a3d3ULL, 0x00b6353478baa24fULL)},
+ }}, {{
+ {FIELD_LITERAL(0x009696510000d333ULL, 0x00ec2f788bc04826ULL,
+ 0x000e4d02b1f67ba5ULL, 0x00659aa8dace08b6ULL,
+ 0x00d7a38a3a3ae533ULL, 0x008856defa8c746bULL,
+ 0x004d7a4402d3da1aULL, 0x00ea82e06229260fULL)},
+ {FIELD_LITERAL(0x006a15bb20f75c0cULL, 0x0079a144027a5d0cULL,
+ 0x00d19116ce0b4d70ULL, 0x0059b83bcb0b268eULL,
+ 0x005f58f63f16c127ULL, 0x0079958318ee2c37ULL,
+ 0x00defbb063d07f82ULL, 0x00f1f0b931d2d446ULL)},
+ {FIELD_LITERAL(0x00cb5e4c3c35d422ULL, 0x008df885ca43577fULL,
+ 0x00fa50b16ca3e471ULL, 0x005a0e58e17488c8ULL,
+ 0x00b2ceccd6d34d19ULL, 0x00f01d5d235e36e9ULL,
+ 0x00db2e7e4be6ca44ULL, 0x00260ab77f35fccdULL)},
+ }}, {{
+ {FIELD_LITERAL(0x006f6fd9baac61d5ULL, 0x002a7710a020a895ULL,
+ 0x009de0db7fc03d4dULL, 0x00cdedcb1875f40bULL,
+ 0x00050caf9b6b1e22ULL, 0x005e3a6654456ab0ULL,
+ 0x00775fdf8c4423d4ULL, 0x0028701ea5738b5dULL)},
+ {FIELD_LITERAL(0x009ffd90abfeae96ULL, 0x00cba3c2b624a516ULL,
+ 0x005ef08bcee46c91ULL, 0x00e6fde30afb6185ULL,
+ 0x00f0b4db4f818ce4ULL, 0x006c54f45d2127f5ULL,
+ 0x00040125035854c7ULL, 0x00372658a3287e13ULL)},
+ {FIELD_LITERAL(0x00d7070fb1beb2abULL, 0x0078fc845a93896bULL,
+ 0x006894a4b2f224a6ULL, 0x005bdd8192b9dbdeULL,
+ 0x00b38839874b3a9eULL, 0x00f93618b04b7a57ULL,
+ 0x003e3ec75fd2c67eULL, 0x00bf5e6bfc29494aULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00f19224ebba2aa5ULL, 0x0074f89d358e694dULL,
+ 0x00eea486597135adULL, 0x0081579a4555c7e1ULL,
+ 0x0010b9b872930a9dULL, 0x00f002e87a30ecc0ULL,
+ 0x009b9d66b6de56e2ULL, 0x00a3c4f45e8004ebULL)},
+ {FIELD_LITERAL(0x0045e8dda9400888ULL, 0x002ff12e5fc05db7ULL,
+ 0x00a7098d54afe69cULL, 0x00cdbe846a500585ULL,
+ 0x00879c1593ca1882ULL, 0x003f7a7fea76c8b0ULL,
+ 0x002cd73dd0c8e0a1ULL, 0x00645d6ce96f51feULL)},
+ {FIELD_LITERAL(0x002b7e83e123d6d6ULL, 0x00398346f7419c80ULL,
+ 0x0042922e55940163ULL, 0x005e7fc5601886a3ULL,
+ 0x00e88f2cee1d3103ULL, 0x00e7fab135f2e377ULL,
+ 0x00b059984dbf0dedULL, 0x0009ce080faa5bb8ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0085e78af7758979ULL, 0x00275a4ee1631a3aULL,
+ 0x00d26bc0ed78b683ULL, 0x004f8355ea21064fULL,
+ 0x00d618e1a32696e5ULL, 0x008d8d7b150e5680ULL,
+ 0x00a74cd854b278d2ULL, 0x001dd62702203ea0ULL)},
+ {FIELD_LITERAL(0x00f89335c2a59286ULL, 0x00a0f5c905d55141ULL,
+ 0x00b41fb836ee9382ULL, 0x00e235d51730ca43ULL,
+ 0x00a5cb37b5c0a69aULL, 0x009b966ffe136c45ULL,
+ 0x00cb2ea10bf80ed1ULL, 0x00fb2b370b40dc35ULL)},
+ {FIELD_LITERAL(0x00d687d16d4ee8baULL, 0x0071520bdd069dffULL,
+ 0x00de85c60d32355dULL, 0x0087d2e3565102f4ULL,
+ 0x00cde391b8dfc9aaULL, 0x00e18d69efdfefe5ULL,
+ 0x004a9d0591954e91ULL, 0x00fa36dd8b50eee5ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x002e788749a865f7ULL, 0x006e4dc3116861eaULL,
+ 0x009f1428c37276e6ULL, 0x00e7d2e0fc1e1226ULL,
+ 0x003aeebc6b6c45f6ULL, 0x0071a8073bf500c9ULL,
+ 0x004b22ad986b530cULL, 0x00f439e63c0d79d4ULL)},
+ {FIELD_LITERAL(0x006bc3d53011f470ULL, 0x00032d6e692b83e8ULL,
+ 0x00059722f497cd0bULL, 0x0009b4e6f0c497ccULL,
+ 0x0058a804b7cce6c0ULL, 0x002b71d3302bbd5dULL,
+ 0x00e2f82a36765fceULL, 0x008dded99524c703ULL)},
+ {FIELD_LITERAL(0x004d058953747d64ULL, 0x00701940fe79aa6fULL,
+ 0x00a620ac71c760bfULL, 0x009532b611158b75ULL,
+ 0x00547ed7f466f300ULL, 0x003cb5ab53a8401aULL,
+ 0x00c7763168ce3120ULL, 0x007e48e33e4b9ab2ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001b2fc57bf3c738ULL, 0x006a3f918993fb80ULL,
+ 0x0026f7a14fdec288ULL, 0x0075a2cdccef08dbULL,
+ 0x00d3ecbc9eecdbf1ULL, 0x0048c40f06e5bf7fULL,
+ 0x00d63e423009896bULL, 0x000598bc99c056a8ULL)},
+ {FIELD_LITERAL(0x002f194eaafa46dcULL, 0x008e38f57fe87613ULL,
+ 0x00dc8e5ae25f4ab2ULL, 0x000a17809575e6bdULL,
+ 0x00d3ec7923ba366aULL, 0x003a7e72e0ad75e3ULL,
+ 0x0010024b88436e0aULL, 0x00ed3c5444b64051ULL)},
+ {FIELD_LITERAL(0x00831fc1340af342ULL, 0x00c9645669466d35ULL,
+ 0x007692b4cc5a080fULL, 0x009fd4a47ac9259fULL,
+ 0x001eeddf7d45928bULL, 0x003c0446fc45f28bULL,
+ 0x002c0713aa3e2507ULL, 0x0095706935f0f41eULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00766ae4190ec6d8ULL, 0x0065768cabc71380ULL,
+ 0x00b902598416cdc2ULL, 0x00380021ad38df52ULL,
+ 0x008f0b89d6551134ULL, 0x004254d4cc62c5a5ULL,
+ 0x000d79f4484b9b94ULL, 0x00b516732ae3c50eULL)},
+ {FIELD_LITERAL(0x001fb73475c45509ULL, 0x00d2b2e5ea43345aULL,
+ 0x00cb3c3842077bd1ULL, 0x0029f90ad820946eULL,
+ 0x007c11b2380778aaULL, 0x009e54ece62c1704ULL,
+ 0x004bc60c41ca01c3ULL, 0x004525679a5a0b03ULL)},
+ {FIELD_LITERAL(0x00c64fbddbed87b3ULL, 0x0040601d11731faaULL,
+ 0x009c22475b6f9d67ULL, 0x0024b79dae875f15ULL,
+ 0x00616fed3f02c3b0ULL, 0x0000cf39f6af2d3bULL,
+ 0x00c46bac0aa9a688ULL, 0x00ab23e2800da204ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000b3a37617632b0ULL, 0x00597199fe1cfb6cULL,
+ 0x0042a7ccdfeafdd6ULL, 0x004cc9f15ebcea17ULL,
+ 0x00f436e596a6b4a4ULL, 0x00168861142df0d8ULL,
+ 0x000753edfec26af5ULL, 0x000c495d7e388116ULL)},
+ {FIELD_LITERAL(0x0017085f4a346148ULL, 0x00c7cf7a37f62272ULL,
+ 0x001776e129bc5c30ULL, 0x009955134c9eef2aULL,
+ 0x001ba5bdf1df07beULL, 0x00ec39497103a55cULL,
+ 0x006578354fda6cfbULL, 0x005f02719d4f15eeULL)},
+ {FIELD_LITERAL(0x0052b9d9b5d9655dULL, 0x00d4ec7ba1b461c3ULL,
+ 0x00f95df4974f280bULL, 0x003d8e5ca11aeb51ULL,
+ 0x00d4981eb5a70b26ULL, 0x000af9a4f6659f29ULL,
+ 0x004598c846faeb43ULL, 0x0049d9a183a47670ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000a72d23dcb3f1fULL, 0x00a3737f84011727ULL,
+ 0x00f870c0fbbf4a47ULL, 0x00a7aadd04b5c9caULL,
+ 0x000c7715c67bd072ULL, 0x00015a136afcd74eULL,
+ 0x0080d5caea499634ULL, 0x0026b448ec7514b7ULL)},
+ {FIELD_LITERAL(0x00b60167d9e7d065ULL, 0x00e60ba0d07381e8ULL,
+ 0x003a4f17b725c2d4ULL, 0x006c19fe176b64faULL,
+ 0x003b57b31af86ccbULL, 0x0021047c286180fdULL,
+ 0x00bdc8fb00c6dbb6ULL, 0x00fe4a9f4bab4f3fULL)},
+ {FIELD_LITERAL(0x0088ffc3a16111f7ULL, 0x009155e4245d0bc8ULL,
+ 0x00851d68220572d5ULL, 0x00557ace1e514d29ULL,
+ 0x0031d7c339d91022ULL, 0x00101d0ae2eaceeaULL,
+ 0x00246ab3f837b66aULL, 0x00d5216d381ff530ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0057e7ea35f36daeULL, 0x00f47d7ad15de22eULL,
+ 0x00d757ea4b105115ULL, 0x008311457d579d7eULL,
+ 0x00b49b75b1edd4ebULL, 0x0081c7ff742fd63aULL,
+ 0x00ddda3187433df6ULL, 0x00475727d55f9c66ULL)},
+ {FIELD_LITERAL(0x00a6295218dc136aULL, 0x00563b3af0e9c012ULL,
+ 0x00d3753b0145db1bULL, 0x004550389c043dc1ULL,
+ 0x00ea94ae27401bdfULL, 0x002b0b949f2b7956ULL,
+ 0x00c63f780ad8e23cULL, 0x00e591c47d6bab15ULL)},
+ {FIELD_LITERAL(0x00416c582b058eb6ULL, 0x004107da5b2cc695ULL,
+ 0x00b3cd2556aeec64ULL, 0x00c0b418267e57a1ULL,
+ 0x001799293579bd2eULL, 0x0046ed44590e4d07ULL,
+ 0x001d7459b3630a1eULL, 0x00c6afba8b6696aaULL)},
+ }}, {{
+ {FIELD_LITERAL(0x008d6009b26da3f8ULL, 0x00898e88ca06b1caULL,
+ 0x00edb22b2ed7fe62ULL, 0x00fbc93516aabe80ULL,
+ 0x008b4b470c42ce0dULL, 0x00e0032ba7d0dcbbULL,
+ 0x00d76da3a956ecc8ULL, 0x007f20fe74e3852aULL)},
+ {FIELD_LITERAL(0x002419222c607674ULL, 0x00a7f23af89188b3ULL,
+ 0x00ad127284e73d1cULL, 0x008bba582fae1c51ULL,
+ 0x00fc6aa7ca9ecab1ULL, 0x003df5319eb6c2baULL,
+ 0x002a05af8a8b199aULL, 0x004bf8354558407cULL)},
+ {FIELD_LITERAL(0x00ce7d4a30f0fcbfULL, 0x00d02c272629f03dULL,
+ 0x0048c001f7400bc2ULL, 0x002c21368011958dULL,
+ 0x0098a550391e96b5ULL, 0x002d80b66390f379ULL,
+ 0x001fa878760cc785ULL, 0x001adfce54b613d5ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001ed4dc71fa2523ULL, 0x005d0bff19bf9b5cULL,
+ 0x00c3801cee065a64ULL, 0x001ed0b504323fbfULL,
+ 0x0003ab9fdcbbc593ULL, 0x00df82070178b8d2ULL,
+ 0x00a2bcaa9c251f85ULL, 0x00c628a3674bd02eULL)},
+ {FIELD_LITERAL(0x006b7a0674f9f8deULL, 0x00a742414e5c7cffULL,
+ 0x0041cbf3c6e13221ULL, 0x00e3a64fd207af24ULL,
+ 0x0087c05f15fbe8d1ULL, 0x004c50936d9e8a33ULL,
+ 0x001306ec21042b6dULL, 0x00a4f4137d1141c2ULL)},
+ {FIELD_LITERAL(0x0009e6fb921568b0ULL, 0x00b3c60120219118ULL,
+ 0x002a6c3460dd503aULL, 0x009db1ef11654b54ULL,
+ 0x0063e4bf0be79601ULL, 0x00670d34bb2592b9ULL,
+ 0x00dcee2f6c4130ceULL, 0x00b2682e88e77f54ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000d5b4b3da135abULL, 0x00838f3e5064d81dULL,
+ 0x00d44eb50f6d94edULL, 0x0008931ab502ac6dULL,
+ 0x00debe01ca3d3586ULL, 0x0025c206775f0641ULL,
+ 0x005ad4b6ae912763ULL, 0x007e2c318ad8f247ULL)},
+ {FIELD_LITERAL(0x00ddbe0750dd1addULL, 0x004b3c7b885844b8ULL,
+ 0x00363e7ecf12f1aeULL, 0x0062e953e6438f9dULL,
+ 0x0023cc73b076afe9ULL, 0x00b09fa083b4da32ULL,
+ 0x00c7c3d2456c541dULL, 0x005b591ec6b694d4ULL)},
+ {FIELD_LITERAL(0x0028656e19d62fcfULL, 0x0052a4af03df148dULL,
+ 0x00122765ddd14e42ULL, 0x00f2252904f67157ULL,
+ 0x004741965b636f3aULL, 0x006441d296132cb9ULL,
+ 0x005e2106f956a5b7ULL, 0x00247029592d335cULL)},
+ }}, {{
+ {FIELD_LITERAL(0x003fe038eb92f894ULL, 0x000e6da1b72e8e32ULL,
+ 0x003a1411bfcbe0faULL, 0x00b55d473164a9e4ULL,
+ 0x00b9a775ac2df48dULL, 0x0002ddf350659e21ULL,
+ 0x00a279a69eb19cb3ULL, 0x00f844eab25cba44ULL)},
+ {FIELD_LITERAL(0x00c41d1f9c1f1ac1ULL, 0x007b2df4e9f19146ULL,
+ 0x00b469355fd5ba7aULL, 0x00b5e1965afc852aULL,
+ 0x00388d5f1e2d8217ULL, 0x0022079e4c09ae93ULL,
+ 0x0014268acd4ef518ULL, 0x00c1dd8d9640464cULL)},
+ {FIELD_LITERAL(0x0038526adeed0c55ULL, 0x00dd68c607e3fe85ULL,
+ 0x00f746ddd48a5d57ULL, 0x0042f2952b963b7cULL,
+ 0x001cbbd6876d5ec2ULL, 0x005e341470bca5c2ULL,
+ 0x00871d41e085f413ULL, 0x00e53ab098f45732ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x004d51124797c831ULL, 0x008f5ae3750347adULL,
+ 0x0070ced94c1a0c8eULL, 0x00f6db2043898e64ULL,
+ 0x000d00c9a5750cd0ULL, 0x000741ec59bad712ULL,
+ 0x003c9d11aab37b7fULL, 0x00a67ba169807714ULL)},
+ {FIELD_LITERAL(0x00adb2c1566e8b8fULL, 0x0096c68a35771a9aULL,
+ 0x00869933356f334aULL, 0x00ba9c93459f5962ULL,
+ 0x009ec73fb6e8ca4bULL, 0x003c3802c27202e1ULL,
+ 0x0031f5b733e0c008ULL, 0x00f9058c19611fa9ULL)},
+ {FIELD_LITERAL(0x00238f01814a3421ULL, 0x00c325a44b6cce28ULL,
+ 0x002136f97aeb0e73ULL, 0x000cac8268a4afe2ULL,
+ 0x0022fd218da471b3ULL, 0x009dcd8dfff8def9ULL,
+ 0x00cb9f8181d999bbULL, 0x00143ae56edea349ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0000623bf87622c5ULL, 0x00a1966fdd069496ULL,
+ 0x00c315b7b812f9fcULL, 0x00bdf5efcd128b97ULL,
+ 0x001d464f532e3e16ULL, 0x003cd94f081bfd7eULL,
+ 0x00ed9dae12ce4009ULL, 0x002756f5736eee70ULL)},
+ {FIELD_LITERAL(0x00a5187e6ee7341bULL, 0x00e6d52e82d83b6eULL,
+ 0x00df3c41323094a7ULL, 0x00b3324f444e9de9ULL,
+ 0x00689eb21a35bfe5ULL, 0x00f16363becd548dULL,
+ 0x00e187cc98e7f60fULL, 0x00127d9062f0ccabULL)},
+ {FIELD_LITERAL(0x004ad71b31c29e40ULL, 0x00a5fcace12fae29ULL,
+ 0x004425b5597280edULL, 0x00e7ef5d716c3346ULL,
+ 0x0010b53ada410ac8ULL, 0x0092310226060c9bULL,
+ 0x0091c26128729c7eULL, 0x0088b42900f8ec3bULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00f1e26e9762d4a8ULL, 0x00d9d74082183414ULL,
+ 0x00ffec9bd57a0282ULL, 0x000919e128fd497aULL,
+ 0x00ab7ae7d00fe5f8ULL, 0x0054dc442851ff68ULL,
+ 0x00c9ebeb3b861687ULL, 0x00507f7cab8b698fULL)},
+ {FIELD_LITERAL(0x00c13c5aae3ae341ULL, 0x009c6c9ed98373e7ULL,
+ 0x00098f26864577a8ULL, 0x0015b886e9488b45ULL,
+ 0x0037692c42aadba5ULL, 0x00b83170b8e7791cULL,
+ 0x001670952ece1b44ULL, 0x00fd932a39276da2ULL)},
+ {FIELD_LITERAL(0x0081a3259bef3398ULL, 0x005480fff416107bULL,
+ 0x00ce4f607d21be98ULL, 0x003ffc084b41df9bULL,
+ 0x0043d0bb100502d1ULL, 0x00ec35f575ba3261ULL,
+ 0x00ca18f677300ef3ULL, 0x00e8bb0a827d8548ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00df76b3328ada72ULL, 0x002e20621604a7c2ULL,
+ 0x00f910638a105b09ULL, 0x00ef4724d96ef2cdULL,
+ 0x00377d83d6b8a2f7ULL, 0x00b4f48805ade324ULL,
+ 0x001cd5da8b152018ULL, 0x0045af671a20ca7fULL)},
+ {FIELD_LITERAL(0x009ae3b93a56c404ULL, 0x004a410b7a456699ULL,
+ 0x00023a619355e6b2ULL, 0x009cdc7297387257ULL,
+ 0x0055b94d4ae70d04ULL, 0x002cbd607f65b005ULL,
+ 0x003208b489697166ULL, 0x00ea2aa058867370ULL)},
+ {FIELD_LITERAL(0x00f29d2598ee3f32ULL, 0x00b4ac5385d82adcULL,
+ 0x007633eaf04df19bULL, 0x00aa2d3d77ceab01ULL,
+ 0x004a2302fcbb778aULL, 0x00927f225d5afa34ULL,
+ 0x004a8e9d5047f237ULL, 0x008224ae9dbce530ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x001cf640859b02f8ULL, 0x00758d1d5d5ce427ULL,
+ 0x00763c784ef4604cULL, 0x005fa81aee205270ULL,
+ 0x00ac537bfdfc44cbULL, 0x004b919bd342d670ULL,
+ 0x00238508d9bf4b7aULL, 0x00154888795644f3ULL)},
+ {FIELD_LITERAL(0x00c845923c084294ULL, 0x00072419a201bc25ULL,
+ 0x0045f408b5f8e669ULL, 0x00e9d6a186b74dfeULL,
+ 0x00e19108c68fa075ULL, 0x0017b91d874177b7ULL,
+ 0x002f0ca2c7912c5aULL, 0x009400aa385a90a2ULL)},
+ {FIELD_LITERAL(0x0071110b01482184ULL, 0x00cfed0044f2bef8ULL,
+ 0x0034f2901cf4662eULL, 0x003b4ae2a67f9834ULL,
+ 0x00cca9b96fe94810ULL, 0x00522507ae77abd0ULL,
+ 0x00bac7422721e73eULL, 0x0066622b0f3a62b0ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00f8ac5cf4705b6aULL, 0x00867d82dcb457e3ULL,
+ 0x007e13ab2ccc2ce9ULL, 0x009ee9a018d3930eULL,
+ 0x008370f8ecb42df8ULL, 0x002d9f019add263eULL,
+ 0x003302385b92d196ULL, 0x00a15654536e2c0cULL)},
+ {FIELD_LITERAL(0x0026ef1614e160afULL, 0x00c023f9edfc9c76ULL,
+ 0x00cff090da5f57baULL, 0x0076db7a66643ae9ULL,
+ 0x0019462f8c646999ULL, 0x008fec00b3854b22ULL,
+ 0x00d55041692a0a1cULL, 0x0065db894215ca00ULL)},
+ {FIELD_LITERAL(0x00a925036e0a451cULL, 0x002a0390c36b6cc1ULL,
+ 0x00f27020d90894f4ULL, 0x008d90d52cbd3d7fULL,
+ 0x00e1d0137392f3b8ULL, 0x00f017c158b51a8fULL,
+ 0x00cac313d3ed7dbcULL, 0x00b99a81e3eb42d3ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00b54850275fe626ULL, 0x0053a3fd1ec71140ULL,
+ 0x00e3d2d7dbe096faULL, 0x00e4ac7b595cce4cULL,
+ 0x0077bad449c0a494ULL, 0x00b7c98814afd5b3ULL,
+ 0x0057226f58486cf9ULL, 0x00b1557154f0cc57ULL)},
+ {FIELD_LITERAL(0x008cc9cd236315c0ULL, 0x0031d9c5b39fda54ULL,
+ 0x00a5713ef37e1171ULL, 0x00293d5ae2886325ULL,
+ 0x00c4aba3e05015e1ULL, 0x0003f35ef78e4fc6ULL,
+ 0x0039d6bd3ac1527bULL, 0x0019d7c3afb77106ULL)},
+ {FIELD_LITERAL(0x007b162931a985afULL, 0x00ad40a2e0daa713ULL,
+ 0x006df27c4009f118ULL, 0x00503e9f4e2e8becULL,
+ 0x00751a77c82c182dULL, 0x000298937769245bULL,
+ 0x00ffb1e8fabf9ee5ULL, 0x0008334706e09abeULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00dbca4e98a7dcd9ULL, 0x00ee29cfc78bde99ULL,
+ 0x00e4a3b6995f52e9ULL, 0x0045d70189ae8096ULL,
+ 0x00fd2a8a3b9b0d1bULL, 0x00af1793b107d8e1ULL,
+ 0x00dbf92cbe4afa20ULL, 0x00da60f798e3681dULL)},
+ {FIELD_LITERAL(0x004246bfcecc627aULL, 0x004ba431246c03a4ULL,
+ 0x00bd1d101872d497ULL, 0x003b73d3f185ee16ULL,
+ 0x001feb2e2678c0e3ULL, 0x00ff13c5a89dec76ULL,
+ 0x00ed06042e771d8fULL, 0x00a4fd2a897a83ddULL)},
+ {FIELD_LITERAL(0x009a4a3be50d6597ULL, 0x00de3165fc5a1096ULL,
+ 0x004f3f56e345b0c7ULL, 0x00f7bf721d5ab8bcULL,
+ 0x004313e47b098c50ULL, 0x00e4c7d5c0e1adbbULL,
+ 0x002e3e3db365051eULL, 0x00a480c2cd6a96fbULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00417fa30a7119edULL, 0x00af257758419751ULL,
+ 0x00d358a487b463d4ULL, 0x0089703cc720b00dULL,
+ 0x00ce56314ff7f271ULL, 0x0064db171ade62c1ULL,
+ 0x00640b36d4a22fedULL, 0x00424eb88696d23fULL)},
+ {FIELD_LITERAL(0x004ede34af2813f3ULL, 0x00d4a8e11c9e8216ULL,
+ 0x004796d5041de8a5ULL, 0x00c4c6b4d21cc987ULL,
+ 0x00e8a433ee07fa1eULL, 0x0055720b5abcc5a1ULL,
+ 0x008873ea9c74b080ULL, 0x005b3fec1ab65d48ULL)},
+ {FIELD_LITERAL(0x0047e5277db70ec5ULL, 0x000a096c66db7d6bULL,
+ 0x00b4164cc1730159ULL, 0x004a9f783fe720feULL,
+ 0x00a8177b94449dbcULL, 0x0095a24ff49a599fULL,
+ 0x0069c1c578250cbcULL, 0x00452019213debf4ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0021ce99e09ebda3ULL, 0x00fcbd9f91875ad0ULL,
+ 0x009bbf6b7b7a0b5fULL, 0x00388886a69b1940ULL,
+ 0x00926a56d0f81f12ULL, 0x00e12903c3358d46ULL,
+ 0x005dfce4e8e1ce9dULL, 0x0044cfa94e2f7e23ULL)},
+ {FIELD_LITERAL(0x001bd59c09e982eaULL, 0x00f72daeb937b289ULL,
+ 0x0018b76dca908e0eULL, 0x00edb498512384adULL,
+ 0x00ce0243b6cc9538ULL, 0x00f96ff690cb4e70ULL,
+ 0x007c77bf9f673c8dULL, 0x005bf704c088a528ULL)},
+ {FIELD_LITERAL(0x0093d4628dcb33beULL, 0x0095263d51d42582ULL,
+ 0x0049b3222458fe06ULL, 0x00e7fce73b653a7fULL,
+ 0x003ca2ebce60b369ULL, 0x00c5de239a32bea4ULL,
+ 0x0063b8b3d71fb6bfULL, 0x0039aeeb78a1a839ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007dc52da400336cULL, 0x001fded1e15b9457ULL,
+ 0x00902e00f5568e3aULL, 0x00219bef40456d2dULL,
+ 0x005684161fb3dbc9ULL, 0x004a4e9be49a76eaULL,
+ 0x006e685ae88b78ffULL, 0x0021c42f13042d3cULL)},
+ {FIELD_LITERAL(0x00fb22bb5fd3ce50ULL, 0x0017b48aada7ae54ULL,
+ 0x00fd5c44ad19a536ULL, 0x000ccc4e4e55e45cULL,
+ 0x00fd637d45b4c3f5ULL, 0x0038914e023c37cfULL,
+ 0x00ac1881d6a8d898ULL, 0x00611ed8d3d943a8ULL)},
+ {FIELD_LITERAL(0x0056e2259d113d2bULL, 0x00594819b284ec16ULL,
+ 0x00c7bf794bb36696ULL, 0x00721ee75097cdc6ULL,
+ 0x00f71be9047a2892ULL, 0x00df6ba142564edfULL,
+ 0x0069580b7a184e8dULL, 0x00f056e38fca0feeULL)},
+ }}, {{
+ {FIELD_LITERAL(0x009df98566a18c6dULL, 0x00cf3a200968f219ULL,
+ 0x0044ba60da6d9086ULL, 0x00dbc9c0e344da03ULL,
+ 0x000f9401c4466855ULL, 0x00d46a57c5b0a8d1ULL,
+ 0x00875a635d7ac7c6ULL, 0x00ef4a933b7e0ae6ULL)},
+ {FIELD_LITERAL(0x005e8694077a1535ULL, 0x008bef75f71c8f1dULL,
+ 0x000a7c1316423511ULL, 0x00906e1d70604320ULL,
+ 0x003fc46c1a2ffbd6ULL, 0x00d1d5022e68f360ULL,
+ 0x002515fba37bbf46ULL, 0x00ca16234e023b44ULL)},
+ {FIELD_LITERAL(0x00787c99561f4690ULL, 0x00a857a8c1561f27ULL,
+ 0x00a10df9223c09feULL, 0x00b98a9562e3b154ULL,
+ 0x004330b8744c3ed2ULL, 0x00e06812807ec5c4ULL,
+ 0x00e4cf6a7db9f1e3ULL, 0x00d95b089f132a34ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x002922b39ca33eecULL, 0x0090d12a5f3ab194ULL,
+ 0x00ab60c02fb5f8edULL, 0x00188d292abba1cfULL,
+ 0x00e10edec9698f6eULL, 0x0069a4d9934133c8ULL,
+ 0x0024aac40e6d3d06ULL, 0x001702c2177661b0ULL)},
+ {FIELD_LITERAL(0x00139078397030bdULL, 0x000e3c447e859a00ULL,
+ 0x0064a5b334c82393ULL, 0x00b8aabeb7358093ULL,
+ 0x00020778bb9ae73bULL, 0x0032ee94c7892a18ULL,
+ 0x008215253cb41bdaULL, 0x005e2797593517aeULL)},
+ {FIELD_LITERAL(0x0083765a5f855d4aULL, 0x0051b6d1351b8ee2ULL,
+ 0x00116de548b0f7bbULL, 0x0087bd88703affa0ULL,
+ 0x0095b2cc34d7fdd2ULL, 0x0084cd81b53f0bc8ULL,
+ 0x008562fc995350edULL, 0x00a39abb193651e3ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0019e23f0474b114ULL, 0x00eb94c2ad3b437eULL,
+ 0x006ddb34683b75acULL, 0x00391f9209b564c6ULL,
+ 0x00083b3bb3bff7aaULL, 0x00eedcd0f6dceefcULL,
+ 0x00b50817f794fe01ULL, 0x0036474deaaa75c9ULL)},
+ {FIELD_LITERAL(0x0091868594265aa2ULL, 0x00797accae98ca6dULL,
+ 0x0008d8c5f0f8a184ULL, 0x00d1f4f1c2b2fe6eULL,
+ 0x0036783dfb48a006ULL, 0x008c165120503527ULL,
+ 0x0025fd780058ce9bULL, 0x0068beb007be7d27ULL)},
+ {FIELD_LITERAL(0x00d0ff88aa7c90c2ULL, 0x00b2c60dacf53394ULL,
+ 0x0094a7284d9666d6ULL, 0x00bed9022ce7a19dULL,
+ 0x00c51553f0cd7682ULL, 0x00c3fb870b124992ULL,
+ 0x008d0bc539956c9bULL, 0x00fc8cf258bb8885ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x003667bf998406f8ULL, 0x0000115c43a12975ULL,
+ 0x001e662f3b20e8fdULL, 0x0019ffa534cb24ebULL,
+ 0x00016be0dc8efb45ULL, 0x00ff76a8b26243f5ULL,
+ 0x00ae20d241a541e3ULL, 0x0069bd6af13cd430ULL)},
+ {FIELD_LITERAL(0x0045fdc16487cda3ULL, 0x00b2d8e844cf2ed7ULL,
+ 0x00612c50e88c1607ULL, 0x00a08aabc66c1672ULL,
+ 0x006031fdcbb24d97ULL, 0x001b639525744b93ULL,
+ 0x004409d62639ab17ULL, 0x00a1853d0347ab1dULL)},
+ {FIELD_LITERAL(0x0075a1a56ebf5c21ULL, 0x00a3e72be9ac53edULL,
+ 0x00efcde1629170c2ULL, 0x0004225fe91ef535ULL,
+ 0x0088049fc73dfda7ULL, 0x004abc74857e1288ULL,
+ 0x0024e2434657317cULL, 0x00d98cb3d3e5543cULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00b4b53eab6bdb19ULL, 0x009b22d8b43711d0ULL,
+ 0x00d948b9d961785dULL, 0x00cb167b6f279eadULL,
+ 0x00191de3a678e1c9ULL, 0x00d9dd9511095c2eULL,
+ 0x00f284324cd43067ULL, 0x00ed74fa535151ddULL)},
+ {FIELD_LITERAL(0x007e32c049b5c477ULL, 0x009d2bfdbd9bcfd8ULL,
+ 0x00636e93045938c6ULL, 0x007fde4af7687298ULL,
+ 0x0046a5184fafa5d3ULL, 0x0079b1e7f13a359bULL,
+ 0x00875adf1fb927d6ULL, 0x00333e21c61bcad2ULL)},
+ {FIELD_LITERAL(0x00048014f73d8b8dULL, 0x0075684aa0966388ULL,
+ 0x0092be7df06dc47cULL, 0x0097cebcd0f5568aULL,
+ 0x005a7004d9c4c6a9ULL, 0x00b0ecbb659924c7ULL,
+ 0x00d90332dd492a7cULL, 0x0057fc14df11493dULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0008ed8ea0ad95beULL, 0x0041d324b9709645ULL,
+ 0x00e25412257a19b4ULL, 0x0058df9f3423d8d2ULL,
+ 0x00a9ab20def71304ULL, 0x009ae0dbf8ac4a81ULL,
+ 0x00c9565977e4392aULL, 0x003c9269444baf55ULL)},
+ {FIELD_LITERAL(0x007df6cbb926830bULL, 0x00d336058ae37865ULL,
+ 0x007af47dac696423ULL, 0x0048d3011ec64ac8ULL,
+ 0x006b87666e40049fULL, 0x0036a2e0e51303d7ULL,
+ 0x00ba319bd79dbc55ULL, 0x003e2737ecc94f53ULL)},
+ {FIELD_LITERAL(0x00d296ff726272d9ULL, 0x00f6d097928fcf57ULL,
+ 0x00e0e616a55d7013ULL, 0x00deaf454ed9eac7ULL,
+ 0x0073a56bedef4d92ULL, 0x006ccfdf6fc92e19ULL,
+ 0x009d1ee1371a7218ULL, 0x00ee3c2ee4462d80ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00437bce9bccdf9dULL, 0x00e0c8e2f85dc0a3ULL,
+ 0x00c91a7073995a19ULL, 0x00856ec9fe294559ULL,
+ 0x009e4b33394b156eULL, 0x00e245b0dc497e5cULL,
+ 0x006a54e687eeaeffULL, 0x00f1cd1cd00fdb7cULL)},
+ {FIELD_LITERAL(0x008132ae5c5d8cd1ULL, 0x00121d68324a1d9fULL,
+ 0x00d6be9dafcb8c76ULL, 0x00684d9070edf745ULL,
+ 0x00519fbc96d7448eULL, 0x00388182fdc1f27eULL,
+ 0x000235baed41f158ULL, 0x00bf6cf6f1a1796aULL)},
+ {FIELD_LITERAL(0x002adc4b4d148219ULL, 0x003084ada0d3a90aULL,
+ 0x0046de8aab0f2e4eULL, 0x00452d342a67b5fdULL,
+ 0x00d4b50f01d4de21ULL, 0x00db6d9fc0cefb79ULL,
+ 0x008c184c86a462cdULL, 0x00e17c83764d42daULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007b2743b9a1e01aULL, 0x007847ffd42688c4ULL,
+ 0x006c7844d610a316ULL, 0x00f0cb8b250aa4b0ULL,
+ 0x00a19060143b3ae6ULL, 0x0014eb10b77cfd80ULL,
+ 0x000170905729dd06ULL, 0x00063b5b9cd72477ULL)},
+ {FIELD_LITERAL(0x00ce382dc7993d92ULL, 0x00021153e938b4c8ULL,
+ 0x00096f7567f48f51ULL, 0x0058f81ddfe4b0d5ULL,
+ 0x00cc379a56b355c7ULL, 0x002c760770d3e819ULL,
+ 0x00ee22d1d26e5a40ULL, 0x00de6d93d5b082d7ULL)},
+ {FIELD_LITERAL(0x000a91a42c52e056ULL, 0x00185f6b77fce7eaULL,
+ 0x000803c51962f6b5ULL, 0x0022528582ba563dULL,
+ 0x0043f8040e9856d6ULL, 0x0085a29ec81fb860ULL,
+ 0x005f9a611549f5ffULL, 0x00c1f974ecbd4b06ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x005b64c6fd65ec97ULL, 0x00c1fdd7f877bc7fULL,
+ 0x000d9cc6c89f841cULL, 0x005c97b7f1aff9adULL,
+ 0x0075e3c61475d47eULL, 0x001ecb1ba8153011ULL,
+ 0x00fe7f1c8d71d40dULL, 0x003fa9757a229832ULL)},
+ {FIELD_LITERAL(0x00ffc5c89d2b0cbaULL, 0x00d363d42e3e6fc3ULL,
+ 0x0019a1a0118e2e8aULL, 0x00f7baeff48882e1ULL,
+ 0x001bd5af28c6b514ULL, 0x0055476ca2253cb2ULL,
+ 0x00d8eb1977e2ddf3ULL, 0x00b173b1adb228a1ULL)},
+ {FIELD_LITERAL(0x00f2cb99dd0ad707ULL, 0x00e1e08b6859ddd8ULL,
+ 0x000008f2d0650bccULL, 0x00d7ed392f8615c3ULL,
+ 0x00976750a94da27fULL, 0x003e83bb0ecb69baULL,
+ 0x00df8e8d15c14ac6ULL, 0x00f9f7174295d9c2ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00f11cc8e0e70bcbULL, 0x00e5dc689974e7ddULL,
+ 0x0014e409f9ee5870ULL, 0x00826e6689acbd63ULL,
+ 0x008a6f4e3d895d88ULL, 0x00b26a8da41fd4adULL,
+ 0x000fb7723f83efd7ULL, 0x009c749db0a5f6c3ULL)},
+ {FIELD_LITERAL(0x002389319450f9baULL, 0x003677f31aa1250aULL,
+ 0x0092c3db642f38cbULL, 0x00f8b64c0dfc9773ULL,
+ 0x00cd49fe3505b795ULL, 0x0068105a4090a510ULL,
+ 0x00df0ba2072a8bb6ULL, 0x00eb396143afd8beULL)},
+ {FIELD_LITERAL(0x00a0d4ecfb24cdffULL, 0x00ddaf8008ba6479ULL,
+ 0x00f0b3e36d4b0f44ULL, 0x003734bd3af1f146ULL,
+ 0x00b87e2efc75527eULL, 0x00d230df55ddab50ULL,
+ 0x002613257ae56c1dULL, 0x00bc0946d135934dULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00468711bd994651ULL, 0x0033108fa67561bfULL,
+ 0x0089d760192a54b4ULL, 0x00adc433de9f1871ULL,
+ 0x000467d05f36e050ULL, 0x007847e0f0579f7fULL,
+ 0x00a2314ad320052dULL, 0x00b3a93649f0b243ULL)},
+ {FIELD_LITERAL(0x0067f8f0c4fe26c9ULL, 0x0079c4a3cc8f67b9ULL,
+ 0x0082b1e62f23550dULL, 0x00f2d409caefd7f5ULL,
+ 0x0080e67dcdb26e81ULL, 0x0087ae993ea1f98aULL,
+ 0x00aa108becf61d03ULL, 0x001acf11efb608a3ULL)},
+ {FIELD_LITERAL(0x008225febbab50d9ULL, 0x00f3b605e4dd2083ULL,
+ 0x00a32b28189e23d2ULL, 0x00d507e5e5eb4c97ULL,
+ 0x005a1a84e302821fULL, 0x0006f54c1c5f08c7ULL,
+ 0x00a347c8cb2843f0ULL, 0x0009f73e9544bfa5ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x006c59c9ae744185ULL, 0x009fc32f1b4282cdULL,
+ 0x004d6348ca59b1acULL, 0x00105376881be067ULL,
+ 0x00af4096013147dcULL, 0x004abfb5a5cb3124ULL,
+ 0x000d2a7f8626c354ULL, 0x009c6ed568e07431ULL)},
+ {FIELD_LITERAL(0x00e828333c297f8bULL, 0x009ef3cf8c3f7e1fULL,
+ 0x00ab45f8fff31cb9ULL, 0x00c8b4178cb0b013ULL,
+ 0x00d0c50dd3260a3fULL, 0x0097126ac257f5bcULL,
+ 0x0042376cc90c705aULL, 0x001d96fdb4a1071eULL)},
+ {FIELD_LITERAL(0x00542d44d89ee1a8ULL, 0x00306642e0442d98ULL,
+ 0x0090853872b87338ULL, 0x002362cbf22dc044ULL,
+ 0x002c222adff663b8ULL, 0x0067c924495fcb79ULL,
+ 0x000e621d983c977cULL, 0x00df77a9eccb66fbULL)},
+ }}, {{
+ {FIELD_LITERAL(0x002809e4bbf1814aULL, 0x00b9e854f9fafb32ULL,
+ 0x00d35e67c10f7a67ULL, 0x008f1bcb76e748cfULL,
+ 0x004224d9515687d2ULL, 0x005ba0b774e620c4ULL,
+ 0x00b5e57db5d54119ULL, 0x00e15babe5683282ULL)},
+ {FIELD_LITERAL(0x00832d02369b482cULL, 0x00cba52ff0d93450ULL,
+ 0x003fa9c908d554dbULL, 0x008d1e357b54122fULL,
+ 0x00abd91c2dc950c6ULL, 0x007eff1df4c0ec69ULL,
+ 0x003f6aeb13fb2d31ULL, 0x00002d6179fc5b2cULL)},
+ {FIELD_LITERAL(0x0046c9eda81c9c89ULL, 0x00b60cb71c8f62fcULL,
+ 0x0022f5a683baa558ULL, 0x00f87319fccdf997ULL,
+ 0x009ca09b51ce6a22ULL, 0x005b12baf4af7d77ULL,
+ 0x008a46524a1e33e2ULL, 0x00035a77e988be0dULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00a7efe46a7dbe2fULL, 0x002f66fd55014fe7ULL,
+ 0x006a428afa1ff026ULL, 0x0056caaa9604ab72ULL,
+ 0x0033f3bcd7fac8aeULL, 0x00ccb1aa01c86764ULL,
+ 0x00158d1edf13bf40ULL, 0x009848ee76fcf3b4ULL)},
+ {FIELD_LITERAL(0x00a9e7730a819691ULL, 0x00d9cc73c4992b70ULL,
+ 0x00e299bde067de5aULL, 0x008c314eb705192aULL,
+ 0x00e7226f17e8a3ccULL, 0x0029dfd956e65a47ULL,
+ 0x0053a8e839073b12ULL, 0x006f942b2ab1597eULL)},
+ {FIELD_LITERAL(0x001c3d780ecd5e39ULL, 0x0094f247fbdcc5feULL,
+ 0x00d5c786fd527764ULL, 0x00b6f4da74f0db2aULL,
+ 0x0080f1f8badcd5fcULL, 0x00f36a373ad2e23bULL,
+ 0x00f804f9f4343bf2ULL, 0x00d1af40ec623982ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0082aeace5f1b144ULL, 0x00f68b3108cf4dd3ULL,
+ 0x00634af01dde3020ULL, 0x000beab5df5c2355ULL,
+ 0x00e8b790d1b49b0bULL, 0x00e48d15854e36f4ULL,
+ 0x0040ab2d95f3db9fULL, 0x002711c4ed9e899aULL)},
+ {FIELD_LITERAL(0x0039343746531ebeULL, 0x00c8509d835d429dULL,
+ 0x00e79eceff6b0018ULL, 0x004abfd31e8efce5ULL,
+ 0x007bbfaaa1e20210ULL, 0x00e3be89c193e179ULL,
+ 0x001c420f4c31d585ULL, 0x00f414a315bef5aeULL)},
+ {FIELD_LITERAL(0x007c296a24990df8ULL, 0x00d5d07525a75588ULL,
+ 0x00dd8e113e94b7e7ULL, 0x007bbc58febe0cc8ULL,
+ 0x0029f51af9bfcad3ULL, 0x007e9311ec7ab6f3ULL,
+ 0x009a884de1676343ULL, 0x0050d5f2dce84be9ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x005fa020cca2450aULL, 0x00491c29db6416d8ULL,
+ 0x0037cefe3f9f9a85ULL, 0x003d405230647066ULL,
+ 0x0049e835f0fdbe89ULL, 0x00feb78ac1a0815cULL,
+ 0x00828e4b32dc9724ULL, 0x00db84f2dc8d6fd4ULL)},
+ {FIELD_LITERAL(0x0098cddc8b39549aULL, 0x006da37e3b05d22cULL,
+ 0x00ce633cfd4eb3cbULL, 0x00fda288ef526acdULL,
+ 0x0025338878c5d30aULL, 0x00f34438c4e5a1b4ULL,
+ 0x00584efea7c310f1ULL, 0x0041a551f1b660adULL)},
+ {FIELD_LITERAL(0x00d7f7a8fbd6437aULL, 0x0062872413bf3753ULL,
+ 0x00ad4bbcb43c584bULL, 0x007fe49be601d7e3ULL,
+ 0x0077c659789babf4ULL, 0x00eb45fcb06a741bULL,
+ 0x005ce244913f9708ULL, 0x0088426401736326ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007bf562ca768d7cULL, 0x006c1f3a174e387cULL,
+ 0x00f024b447fee939ULL, 0x007e7af75f01143fULL,
+ 0x003adb70b4eed89dULL, 0x00e43544021ad79aULL,
+ 0x0091f7f7042011f6ULL, 0x0093c1a1ee3a0ddcULL)},
+ {FIELD_LITERAL(0x00a0b68ec1eb72d2ULL, 0x002c03235c0d45a0ULL,
+ 0x00553627323fe8c5ULL, 0x006186e94b17af94ULL,
+ 0x00a9906196e29f14ULL, 0x0025b3aee6567733ULL,
+ 0x007e0dd840080517ULL, 0x0018eb5801a4ba93ULL)},
+ {FIELD_LITERAL(0x00d7fe7017bf6a40ULL, 0x006e3f0624be0c42ULL,
+ 0x00ffbba205358245ULL, 0x00f9fc2cf8194239ULL,
+ 0x008d93b37bf15b4eULL, 0x006ddf2e38be8e95ULL,
+ 0x002b6e79bf5fcff9ULL, 0x00ab355da425e2deULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00938f97e20be973ULL, 0x0099141a36aaf306ULL,
+ 0x0057b0ca29e545a1ULL, 0x0085db571f9fbc13ULL,
+ 0x008b333c554b4693ULL, 0x0043ab6ef3e241cbULL,
+ 0x0054fb20aa1e5c70ULL, 0x00be0ff852760adfULL)},
+ {FIELD_LITERAL(0x003973d8938971d6ULL, 0x002aca26fa80c1f5ULL,
+ 0x00108af1faa6b513ULL, 0x00daae275d7924e6ULL,
+ 0x0053634ced721308ULL, 0x00d2355fe0bbd443ULL,
+ 0x00357612b2d22095ULL, 0x00f9bb9dd4136cf3ULL)},
+ {FIELD_LITERAL(0x002bff12cf5e03a5ULL, 0x001bdb1fa8a19cf8ULL,
+ 0x00c91c6793f84d39ULL, 0x00f869f1b2eba9afULL,
+ 0x0059bc547dc3236bULL, 0x00d91611d6d38689ULL,
+ 0x00e062daaa2c0214ULL, 0x00ed3c047cc2bc82ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000050d70c32b31aULL, 0x001939d576d437b3ULL,
+ 0x00d709e598bf9fe6ULL, 0x00a885b34bd2ee9eULL,
+ 0x00dd4b5c08ab1a50ULL, 0x0091bebd50b55639ULL,
+ 0x00cf79ff64acdbc6ULL, 0x006067a39d826336ULL)},
+ {FIELD_LITERAL(0x0062dd0fb31be374ULL, 0x00fcc96b84c8e727ULL,
+ 0x003f64f1375e6ae3ULL, 0x0057d9b6dd1af004ULL,
+ 0x00d6a167b1103c7bULL, 0x00dd28f3180fb537ULL,
+ 0x004ff27ad7167128ULL, 0x008934c33461f2acULL)},
+ {FIELD_LITERAL(0x0065b472b7900043ULL, 0x00ba7efd2ff1064bULL,
+ 0x000b67d6c4c3020fULL, 0x0012d28469f4e46dULL,
+ 0x0031c32939703ec7ULL, 0x00b49f0bce133066ULL,
+ 0x00f7e10416181d47ULL, 0x005c90f51867eeccULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0051207abd179101ULL, 0x00fc2a5c20d9c5daULL,
+ 0x00fb9d5f2701b6dfULL, 0x002dd040fdea82b8ULL,
+ 0x00f163b0738442ffULL, 0x00d9736bd68855b8ULL,
+ 0x00e0d8e93005e61cULL, 0x00df5a40b3988570ULL)},
+ {FIELD_LITERAL(0x0006918f5dfce6dcULL, 0x00d4bf1c793c57fbULL,
+ 0x0069a3f649435364ULL, 0x00e89a50e5b0cd6eULL,
+ 0x00b9f6a237e973afULL, 0x006d4ed8b104e41dULL,
+ 0x00498946a3924cd2ULL, 0x00c136ec5ac9d4f7ULL)},
+ {FIELD_LITERAL(0x0011a9c290ac5336ULL, 0x002b9a2d4a6a6533ULL,
+ 0x009a8a68c445d937ULL, 0x00361b27b07e5e5cULL,
+ 0x003c043b1755b974ULL, 0x00b7eb66cf1155eeULL,
+ 0x0077af5909eefff2ULL, 0x0098f609877cc806ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00ab13af436bf8f4ULL, 0x000bcf0a0dac8574ULL,
+ 0x00d50c864f705045ULL, 0x00c40e611debc842ULL,
+ 0x0085010489bd5caaULL, 0x007c5050acec026fULL,
+ 0x00f67d943c8da6d1ULL, 0x00de1da0278074c6ULL)},
+ {FIELD_LITERAL(0x00b373076597455fULL, 0x00e83f1af53ac0f5ULL,
+ 0x0041f63c01dc6840ULL, 0x0097dea19b0c6f4bULL,
+ 0x007f9d63b4c1572cULL, 0x00e692d492d0f5f0ULL,
+ 0x00cbcb392e83b4adULL, 0x0069c0f39ed9b1a8ULL)},
+ {FIELD_LITERAL(0x00861030012707c9ULL, 0x009fbbdc7fd4aafbULL,
+ 0x008f591d6b554822ULL, 0x00df08a41ea18adeULL,
+ 0x009d7d83e642abeaULL, 0x0098c71bda3b78ffULL,
+ 0x0022c89e7021f005ULL, 0x0044d29a3fe1e3c4ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00e748cd7b5c52f2ULL, 0x00ea9df883f89cc3ULL,
+ 0x0018970df156b6c7ULL, 0x00c5a46c2a33a847ULL,
+ 0x00cbde395e32aa09ULL, 0x0072474ebb423140ULL,
+ 0x00fb00053086a23dULL, 0x001dafcfe22d4e1fULL)},
+ {FIELD_LITERAL(0x00c903ee6d825540ULL, 0x00add6c4cf98473eULL,
+ 0x007636efed4227f1ULL, 0x00905124ae55e772ULL,
+ 0x00e6b38fab12ed53ULL, 0x0045e132b863fe55ULL,
+ 0x003974662edb366aULL, 0x00b1787052be8208ULL)},
+ {FIELD_LITERAL(0x00a614b00d775c7cULL, 0x00d7c78941cc7754ULL,
+ 0x00422dd68b5dabc4ULL, 0x00a6110f0167d28bULL,
+ 0x00685a309c252886ULL, 0x00b439ffd5143660ULL,
+ 0x003656e29ee7396fULL, 0x00c7c9b9ed5ad854ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0040f7e7c5b37bf2ULL, 0x0064e4dc81181bbaULL,
+ 0x00a8767ae2a366b6ULL, 0x001496b4f90546f2ULL,
+ 0x002a28493f860441ULL, 0x0021f59513049a3aULL,
+ 0x00852d369a8b7ee3ULL, 0x00dd2e7d8b7d30a9ULL)},
+ {FIELD_LITERAL(0x00006e34a35d9fbcULL, 0x00eee4e48b2f019aULL,
+ 0x006b344743003a5fULL, 0x00541d514f04a7e3ULL,
+ 0x00e81f9ee7647455ULL, 0x005e2b916c438f81ULL,
+ 0x00116f8137b7eff0ULL, 0x009bd3decc7039d1ULL)},
+ {FIELD_LITERAL(0x0005d226f434110dULL, 0x00af8288b8ef21d5ULL,
+ 0x004a7a52ef181c8cULL, 0x00be0b781b4b06deULL,
+ 0x00e6e3627ded07e1ULL, 0x00e43aa342272b8bULL,
+ 0x00e86ab424577d84ULL, 0x00fb292c566e35bbULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00334f5303ea1222ULL, 0x00dfb3dbeb0a5d3eULL,
+ 0x002940d9592335c1ULL, 0x00706a7a63e8938aULL,
+ 0x005a533558bc4cafULL, 0x00558e33192022a9ULL,
+ 0x00970d9faf74c133ULL, 0x002979fcb63493caULL)},
+ {FIELD_LITERAL(0x00e38abece3c82abULL, 0x005a51f18a2c7a86ULL,
+ 0x009dafa2e86d592eULL, 0x00495a62eb688678ULL,
+ 0x00b79df74c0eb212ULL, 0x0023e8cc78b75982ULL,
+ 0x005998cb91075e13ULL, 0x00735aa9ba61bc76ULL)},
+ {FIELD_LITERAL(0x00d9f7a82ddbe628ULL, 0x00a1fc782889ae0fULL,
+ 0x0071ffda12d14b66ULL, 0x0037cf4eca7fb3d5ULL,
+ 0x00c80bc242c58808ULL, 0x0075bf8c2d08c863ULL,
+ 0x008d41f31afc52a7ULL, 0x00197962ecf38741ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x006e9f475cccf2eeULL, 0x00454b9cd506430cULL,
+ 0x00224a4fb79ee479ULL, 0x0062e3347ef0b5e2ULL,
+ 0x0034fd2a3512232aULL, 0x00b8b3cb0f457046ULL,
+ 0x00eb20165daa38ecULL, 0x00128eebc2d9c0f7ULL)},
+ {FIELD_LITERAL(0x00bfc5fa1e4ea21fULL, 0x00c21d7b6bb892e6ULL,
+ 0x00cf043f3acf0291ULL, 0x00c13f2f849b3c90ULL,
+ 0x00d1a97ebef10891ULL, 0x0061e130a445e7feULL,
+ 0x0019513fdedbf22bULL, 0x001d60c813bff841ULL)},
+ {FIELD_LITERAL(0x0019561c7fcf0213ULL, 0x00e3dca6843ebd77ULL,
+ 0x0068ea95b9ca920eULL, 0x009bdfb70f253595ULL,
+ 0x00c68f59186aa02aULL, 0x005aee1cca1c3039ULL,
+ 0x00ab79a8a937a1ceULL, 0x00b9a0e549959e6fULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00c79e0b6d97dfbdULL, 0x00917c71fd2bc6e8ULL,
+ 0x00db7529ccfb63d8ULL, 0x00be5be957f17866ULL,
+ 0x00a9e11fdc2cdac1ULL, 0x007b91a8e1f44443ULL,
+ 0x00a3065e4057d80fULL, 0x004825f5b8d5f6d4ULL)},
+ {FIELD_LITERAL(0x003e4964fa8a8fc8ULL, 0x00f6a1cdbcf41689ULL,
+ 0x00943cb18fe7fda7ULL, 0x00606dafbf34440aULL,
+ 0x005d37a86399c789ULL, 0x00e79a2a69417403ULL,
+ 0x00fe34f7e68b8866ULL, 0x0011f448ed2df10eULL)},
+ {FIELD_LITERAL(0x00f1f57efcc1fcc4ULL, 0x00513679117de154ULL,
+ 0x002e5b5b7c86d8c3ULL, 0x009f6486561f9cfbULL,
+ 0x00169e74b0170cf7ULL, 0x00900205af4af696ULL,
+ 0x006acfddb77853f3ULL, 0x00df184c90f31068ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00b37396c3320791ULL, 0x00fc7b67175c5783ULL,
+ 0x00c36d2cd73ecc38ULL, 0x0080ebcc0b328fc5ULL,
+ 0x0043a5b22b35d35dULL, 0x00466c9f1713c9daULL,
+ 0x0026ad346dcaa8daULL, 0x007c684e701183a6ULL)},
+ {FIELD_LITERAL(0x00fd579ffb691713ULL, 0x00b76af4f81c412dULL,
+ 0x00f239de96110f82ULL, 0x00e965fb437f0306ULL,
+ 0x00ca7e9436900921ULL, 0x00e487f1325fa24aULL,
+ 0x00633907de476380ULL, 0x00721c62ac5b8ea0ULL)},
+ {FIELD_LITERAL(0x00c0d54e542eb4f9ULL, 0x004ed657171c8dcfULL,
+ 0x00b743a4f7c2a39bULL, 0x00fd9f93ed6cc567ULL,
+ 0x00307fae3113e58bULL, 0x0058aa577c93c319ULL,
+ 0x00d254556f35b346ULL, 0x00491aada2203f0dULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00dff3103786ff34ULL, 0x000144553b1f20c3ULL,
+ 0x0095613baeb930e4ULL, 0x00098058275ea5d4ULL,
+ 0x007cd1402b046756ULL, 0x0074d74e4d58aee3ULL,
+ 0x005f93fc343ff69bULL, 0x00873df17296b3b0ULL)},
+ {FIELD_LITERAL(0x00c4a1fb48635413ULL, 0x00b5dd54423ad59fULL,
+ 0x009ff5d53fd24a88ULL, 0x003c98d267fc06a7ULL,
+ 0x002db7cb20013641ULL, 0x00bd1d6716e191f2ULL,
+ 0x006dbc8b29094241ULL, 0x0044bbf233dafa2cULL)},
+ {FIELD_LITERAL(0x0055838d41f531e6ULL, 0x00bf6a2dd03c81b2ULL,
+ 0x005827a061c4839eULL, 0x0000de2cbb36aac3ULL,
+ 0x002efa29d9717478ULL, 0x00f9e928cc8a77baULL,
+ 0x00c134b458def9efULL, 0x00958a182223fc48ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x000a9ee23c06881fULL, 0x002c727d3d871945ULL,
+ 0x00f47d971512d24aULL, 0x00671e816f9ef31aULL,
+ 0x00883af2cfaad673ULL, 0x00601f98583d6c9aULL,
+ 0x00b435f5adc79655ULL, 0x00ad87b71c04bff2ULL)},
+ {FIELD_LITERAL(0x007860d99db787cfULL, 0x00fda8983018f4a8ULL,
+ 0x008c8866bac4743cULL, 0x00ef471f84c82a3fULL,
+ 0x00abea5976d3b8e7ULL, 0x00714882896cd015ULL,
+ 0x00b49fae584ddac5ULL, 0x008e33a1a0b69c81ULL)},
+ {FIELD_LITERAL(0x007b6ee2c9e8a9ecULL, 0x002455dbbd89d622ULL,
+ 0x006490cf4eaab038ULL, 0x00d925f6c3081561ULL,
+ 0x00153b3047de7382ULL, 0x003b421f8bdceb6fULL,
+ 0x00761a4a5049da78ULL, 0x00980348c5202433ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x007f8a43da97dd5cULL, 0x00058539c800fc7bULL,
+ 0x0040f3cf5a28414aULL, 0x00d68dd0d95283d6ULL,
+ 0x004adce9da90146eULL, 0x00befa41c7d4f908ULL,
+ 0x007603bc2e3c3060ULL, 0x00bdf360ab3545dbULL)},
+ {FIELD_LITERAL(0x00eebfd4e2312cc3ULL, 0x00474b2564e4fc8cULL,
+ 0x003303ef14b1da9bULL, 0x003c93e0e66beb1dULL,
+ 0x0013619b0566925aULL, 0x008817c24d901bf3ULL,
+ 0x00b62bd8898d218bULL, 0x0075a7716f1e88a2ULL)},
+ {FIELD_LITERAL(0x0009218da1e6890fULL, 0x0026907f5fd02575ULL,
+ 0x004dabed5f19d605ULL, 0x003abf181870249dULL,
+ 0x00b52fd048cc92c4ULL, 0x00b6dd51e415a5c5ULL,
+ 0x00d9eb82bd2b4014ULL, 0x002c865a43b46b43ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0070047189452f4cULL, 0x00f7ad12e1ce78d5ULL,
+ 0x00af1ba51ec44a8bULL, 0x005f39f63e667cd6ULL,
+ 0x00058eac4648425eULL, 0x00d7fdab42bea03bULL,
+ 0x0028576a5688de15ULL, 0x00af973209e77c10ULL)},
+ {FIELD_LITERAL(0x00c338b915d8fef0ULL, 0x00a893292045c39aULL,
+ 0x0028ab4f2eba6887ULL, 0x0060743cb519fd61ULL,
+ 0x0006213964093ac0ULL, 0x007c0b7a43f6266dULL,
+ 0x008e3557c4fa5bdaULL, 0x002da976de7b8d9dULL)},
+ {FIELD_LITERAL(0x0048729f8a8b6dcdULL, 0x00fe23b85cc4d323ULL,
+ 0x00e7384d16e4db0eULL, 0x004a423970678942ULL,
+ 0x00ec0b763345d4baULL, 0x00c477b9f99ed721ULL,
+ 0x00c29dad3777b230ULL, 0x001c517b466f7df6ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x006366c380f7b574ULL, 0x001c7d1f09ff0438ULL,
+ 0x003e20a7301f5b22ULL, 0x00d3efb1916d28f6ULL,
+ 0x0049f4f81060ce83ULL, 0x00c69d91ea43ced1ULL,
+ 0x002b6f3e5cd269edULL, 0x005b0fb22ce9ec65ULL)},
+ {FIELD_LITERAL(0x00aa2261022d883fULL, 0x00ebcca4548010acULL,
+ 0x002528512e28a437ULL, 0x0070ca7676b66082ULL,
+ 0x0084bda170f7c6d3ULL, 0x00581b4747c9b8bbULL,
+ 0x005c96a01061c7e2ULL, 0x00fb7c4a362b5273ULL)},
+ {FIELD_LITERAL(0x00c30020eb512d02ULL, 0x0060f288283a4d26ULL,
+ 0x00b7ed13becde260ULL, 0x0075ebb74220f6e9ULL,
+ 0x00701079fcfe8a1fULL, 0x001c28fcdff58938ULL,
+ 0x002e4544b8f4df6bULL, 0x0060c5bc4f1a7d73ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x00ae307cf069f701ULL, 0x005859f222dd618bULL,
+ 0x00212d6c46ec0b0dULL, 0x00a0fe4642afb62dULL,
+ 0x00420d8e4a0a8903ULL, 0x00a80ff639bdf7b0ULL,
+ 0x0019bee1490b5d8eULL, 0x007439e4b9c27a86ULL)},
+ {FIELD_LITERAL(0x00a94700032a093fULL, 0x0076e96c225216e7ULL,
+ 0x00a63a4316e45f91ULL, 0x007d8bbb4645d3b2ULL,
+ 0x00340a6ff22793ebULL, 0x006f935d4572aeb7ULL,
+ 0x00b1fb69f00afa28ULL, 0x009e8f3423161ed3ULL)},
+ {FIELD_LITERAL(0x009ef49c6b5ced17ULL, 0x00a555e6269e9f0aULL,
+ 0x007e6f1d79ec73b5ULL, 0x009ac78695a32ac4ULL,
+ 0x0001d77fbbcd5682ULL, 0x008cea1fee0aaeedULL,
+ 0x00f42bea82a53462ULL, 0x002e46ab96cafcc9ULL)},
+ }}, {{
+ {FIELD_LITERAL(0x0051cfcc5885377aULL, 0x00dce566cb1803caULL,
+ 0x00430c7643f2c7d4ULL, 0x00dce1a1337bdcc0ULL,
+ 0x0010d5bd7283c128ULL, 0x003b1b547f9b46feULL,
+ 0x000f245e37e770abULL, 0x007b72511f022b37ULL)},
+ {FIELD_LITERAL(0x0060db815bc4786cULL, 0x006fab25beedc434ULL,
+ 0x00c610d06084797cULL, 0x000c48f08537bec0ULL,
+ 0x0031aba51c5b93daULL, 0x007968fa6e01f347ULL,
+ 0x0030070da52840c6ULL, 0x00c043c225a4837fULL)},
+ {FIELD_LITERAL(0x001bcfd00649ee93ULL, 0x006dceb47e2a0fd5ULL,
+ 0x00f2cebda0cf8fd0ULL, 0x00b6b9d9d1fbdec3ULL,
+ 0x00815262e6490611ULL, 0x00ef7f5ce3176760ULL,
+ 0x00e49cd0c998d58bULL, 0x005fc6cc269ba57cULL)},
+ }}, {{
+ {FIELD_LITERAL(0x008940211aa0d633ULL, 0x00addae28136571dULL,
+ 0x00d68fdbba20d673ULL, 0x003bc6129bc9e21aULL,
+ 0x000346cf184ebe9aULL, 0x0068774d741ebc7fULL,
+ 0x0019d5e9e6966557ULL, 0x0003cbd7f981b651ULL)},
+ {FIELD_LITERAL(0x004a2902926f8d3fULL, 0x00ad79b42637ab75ULL,
+ 0x0088f60b90f2d4e8ULL, 0x0030f54ef0e398c4ULL,
+ 0x00021dc9bf99681eULL, 0x007ebf66fde74ee3ULL,
+ 0x004ade654386e9a4ULL, 0x00e7485066be4c27ULL)},
+ {FIELD_LITERAL(0x00445f1263983be0ULL, 0x004cf371dda45e6aULL,
+ 0x00744a89d5a310e7ULL, 0x001f20ce4f904833ULL,
+ 0x00e746edebe66e29ULL, 0x000912ab1f6c153dULL,
+ 0x00f61d77d9b2444cULL, 0x0001499cd6647610ULL)},
}}
}
};
const struct curve448_precomputed_s *curve448_precomputed_base
= &curve448_precomputed_base_table;
static const niels_t curve448_wnaf_base_table[32] = {
{{
- {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x00e822938a0a0c0c,0x00263a61c9ea9216,0x001204029321b828,0x006a468360983c65,0x0002846f0a782143)},
- {FIELD_LITERAL(0x00303cda6feea532,0x00860f1d5a3850e4,0x00226b9fa4728ccd,0x006822938a0a0c0c,0x00263a61c9ea9215,0x001204029321b828,0x006a468360983c65,0x0082846f0a782143)},
- {FIELD_LITERAL(0x00ef8e22b275198d,0x00b0eb141a0b0e8b,0x001f6789da3cb38c,0x006d2ff8ed39073e,0x00610bdb69a167f3,0x00571f306c9689b4,0x00f557e6f84b2df8,0x002affd38b2c86db)},
+ {FIELD_LITERAL(0x00303cda6feea532ULL, 0x00860f1d5a3850e4ULL,
+ 0x00226b9fa4728ccdULL, 0x00e822938a0a0c0cULL,
+ 0x00263a61c9ea9216ULL, 0x001204029321b828ULL,
+ 0x006a468360983c65ULL, 0x0002846f0a782143ULL)},
+ {FIELD_LITERAL(0x00303cda6feea532ULL, 0x00860f1d5a3850e4ULL,
+ 0x00226b9fa4728ccdULL, 0x006822938a0a0c0cULL,
+ 0x00263a61c9ea9215ULL, 0x001204029321b828ULL,
+ 0x006a468360983c65ULL, 0x0082846f0a782143ULL)},
+ {FIELD_LITERAL(0x00ef8e22b275198dULL, 0x00b0eb141a0b0e8bULL,
+ 0x001f6789da3cb38cULL, 0x006d2ff8ed39073eULL,
+ 0x00610bdb69a167f3ULL, 0x00571f306c9689b4ULL,
+ 0x00f557e6f84b2df8ULL, 0x002affd38b2c86dbULL)},
}}, {{
- {FIELD_LITERAL(0x00cea0fc8d2e88b5,0x00821612d69f1862,0x0074c283b3e67522,0x005a195ba05a876d,0x000cddfe557feea4,0x008046c795bcc5e5,0x00540969f4d6e119,0x00d27f96d6b143d5)},
- {FIELD_LITERAL(0x000c3b1019d474e8,0x00e19533e4952284,0x00cc9810ba7c920a,0x00f103d2785945ac,0x00bfa5696cc69b34,0x00a8d3d51e9ca839,0x005623cb459586b9,0x00eae7ce1cd52e9e)},
- {FIELD_LITERAL(0x0005a178751dd7d8,0x002cc3844c69c42f,0x00acbfe5efe10539,0x009c20f43431a65a,0x008435d96374a7b3,0x009ee57566877bd3,0x0044691725ed4757,0x001e87bb2fe2c6b2)},
+ {FIELD_LITERAL(0x00cea0fc8d2e88b5ULL, 0x00821612d69f1862ULL,
+ 0x0074c283b3e67522ULL, 0x005a195ba05a876dULL,
+ 0x000cddfe557feea4ULL, 0x008046c795bcc5e5ULL,
+ 0x00540969f4d6e119ULL, 0x00d27f96d6b143d5ULL)},
+ {FIELD_LITERAL(0x000c3b1019d474e8ULL, 0x00e19533e4952284ULL,
+ 0x00cc9810ba7c920aULL, 0x00f103d2785945acULL,
+ 0x00bfa5696cc69b34ULL, 0x00a8d3d51e9ca839ULL,
+ 0x005623cb459586b9ULL, 0x00eae7ce1cd52e9eULL)},
+ {FIELD_LITERAL(0x0005a178751dd7d8ULL, 0x002cc3844c69c42fULL,
+ 0x00acbfe5efe10539ULL, 0x009c20f43431a65aULL,
+ 0x008435d96374a7b3ULL, 0x009ee57566877bd3ULL,
+ 0x0044691725ed4757ULL, 0x001e87bb2fe2c6b2ULL)},
}}, {{
- {FIELD_LITERAL(0x000cedc4debf7a04,0x002ffa45000470ac,0x002e9f9678201915,0x0017da1208c4fe72,0x007d558cc7d656cb,0x0037a827287cf289,0x00142472d3441819,0x009c21f166cf8dd1)},
- {FIELD_LITERAL(0x003ef83af164b2f2,0x000949a5a0525d0d,0x00f4498186cac051,0x00e77ac09ef126d2,0x0073ae0b2c9296e9,0x001c163f6922e3ed,0x0062946159321bea,0x00cfb79b22990b39)},
- {FIELD_LITERAL(0x00b001431ca9e654,0x002d7e5eabcc9a3a,0x0052e8114c2f6747,0x0079ac4f94487f92,0x00bffd919b5d749c,0x00261f92ad15e620,0x00718397b7a97895,0x00c1443e6ebbc0c4)},
+ {FIELD_LITERAL(0x000cedc4debf7a04ULL, 0x002ffa45000470acULL,
+ 0x002e9f9678201915ULL, 0x0017da1208c4fe72ULL,
+ 0x007d558cc7d656cbULL, 0x0037a827287cf289ULL,
+ 0x00142472d3441819ULL, 0x009c21f166cf8dd1ULL)},
+ {FIELD_LITERAL(0x003ef83af164b2f2ULL, 0x000949a5a0525d0dULL,
+ 0x00f4498186cac051ULL, 0x00e77ac09ef126d2ULL,
+ 0x0073ae0b2c9296e9ULL, 0x001c163f6922e3edULL,
+ 0x0062946159321beaULL, 0x00cfb79b22990b39ULL)},
+ {FIELD_LITERAL(0x00b001431ca9e654ULL, 0x002d7e5eabcc9a3aULL,
+ 0x0052e8114c2f6747ULL, 0x0079ac4f94487f92ULL,
+ 0x00bffd919b5d749cULL, 0x00261f92ad15e620ULL,
+ 0x00718397b7a97895ULL, 0x00c1443e6ebbc0c4ULL)},
}}, {{
- {FIELD_LITERAL(0x00eacd90c1e0a049,0x008977935b149fbe,0x0004cb9ba11c93dc,0x009fbd5b3470844d,0x004bc18c9bfc22cf,0x0057679a991839f3,0x00ef15b76fb4092e,0x0074a5173a225041)},
- {FIELD_LITERAL(0x003f5f9d7ec4777b,0x00ab2e733c919c94,0x001bb6c035245ae5,0x00a325a49a883630,0x0033e9a9ea3cea2f,0x00e442a1eaa0e844,0x00b2116d5b0e71b8,0x00c16abed6d64047)},
- {FIELD_LITERAL(0x00c560b5ed051165,0x001945adc5d65094,0x00e221865710f910,0x00cc12bc9e9b8ceb,0x004faa9518914e35,0x0017476d89d42f6d,0x00b8f637c8fa1c8b,0x0088c7d2790864b8)},
+ {FIELD_LITERAL(0x00eacd90c1e0a049ULL, 0x008977935b149fbeULL,
+ 0x0004cb9ba11c93dcULL, 0x009fbd5b3470844dULL,
+ 0x004bc18c9bfc22cfULL, 0x0057679a991839f3ULL,
+ 0x00ef15b76fb4092eULL, 0x0074a5173a225041ULL)},
+ {FIELD_LITERAL(0x003f5f9d7ec4777bULL, 0x00ab2e733c919c94ULL,
+ 0x001bb6c035245ae5ULL, 0x00a325a49a883630ULL,
+ 0x0033e9a9ea3cea2fULL, 0x00e442a1eaa0e844ULL,
+ 0x00b2116d5b0e71b8ULL, 0x00c16abed6d64047ULL)},
+ {FIELD_LITERAL(0x00c560b5ed051165ULL, 0x001945adc5d65094ULL,
+ 0x00e221865710f910ULL, 0x00cc12bc9e9b8cebULL,
+ 0x004faa9518914e35ULL, 0x0017476d89d42f6dULL,
+ 0x00b8f637c8fa1c8bULL, 0x0088c7d2790864b8ULL)},
}}, {{
- {FIELD_LITERAL(0x00ef7eafc1c69be6,0x0085d3855778fbea,0x002c8d5b450cb6f5,0x004e77de5e1e7fec,0x0047c057893abded,0x001b430b85d51e16,0x00965c7b45640c3c,0x00487b2bb1162b97)},
- {FIELD_LITERAL(0x0099c73a311beec2,0x00a3eff38d8912ad,0x002efa9d1d7e8972,0x00f717ae1e14d126,0x002833f795850c8b,0x0066c12ad71486bd,0x00ae9889da4820eb,0x00d6044309555c08)},
- {FIELD_LITERAL(0x004b1c5283d15e41,0x00669d8ea308ff75,0x0004390233f762a1,0x00e1d67b83cb6cec,0x003eebaa964c78b1,0x006b0aff965eb664,0x00b313d4470bdc37,0x008814ffcb3cb9d8)},
+ {FIELD_LITERAL(0x00ef7eafc1c69be6ULL, 0x0085d3855778fbeaULL,
+ 0x002c8d5b450cb6f5ULL, 0x004e77de5e1e7fecULL,
+ 0x0047c057893abdedULL, 0x001b430b85d51e16ULL,
+ 0x00965c7b45640c3cULL, 0x00487b2bb1162b97ULL)},
+ {FIELD_LITERAL(0x0099c73a311beec2ULL, 0x00a3eff38d8912adULL,
+ 0x002efa9d1d7e8972ULL, 0x00f717ae1e14d126ULL,
+ 0x002833f795850c8bULL, 0x0066c12ad71486bdULL,
+ 0x00ae9889da4820ebULL, 0x00d6044309555c08ULL)},
+ {FIELD_LITERAL(0x004b1c5283d15e41ULL, 0x00669d8ea308ff75ULL,
+ 0x0004390233f762a1ULL, 0x00e1d67b83cb6cecULL,
+ 0x003eebaa964c78b1ULL, 0x006b0aff965eb664ULL,
+ 0x00b313d4470bdc37ULL, 0x008814ffcb3cb9d8ULL)},
}}, {{
- {FIELD_LITERAL(0x009724b8ce68db70,0x007678b5ed006f3d,0x00bdf4b89c0abd73,0x00299748e04c7c6d,0x00ddd86492c3c977,0x00c5a7febfa30a99,0x00ed84715b4b02bb,0x00319568adf70486)},
- {FIELD_LITERAL(0x0070ff2d864de5bb,0x005a37eeb637ee95,0x0033741c258de160,0x00e6ca5cb1988f46,0x001ceabd92a24661,0x0030957bd500fe40,0x001c3362afe912c5,0x005187889f678bd2)},
- {FIELD_LITERAL(0x0086835fc62bbdc7,0x009c3516ca4910a1,0x00956c71f8d00783,0x0095c78fcf63235f,0x00fc7ff6ba05c222,0x00cdd8b3f8d74a52,0x00ac5ae16de8256e,0x00e9d4be8ed48624)},
+ {FIELD_LITERAL(0x009724b8ce68db70ULL, 0x007678b5ed006f3dULL,
+ 0x00bdf4b89c0abd73ULL, 0x00299748e04c7c6dULL,
+ 0x00ddd86492c3c977ULL, 0x00c5a7febfa30a99ULL,
+ 0x00ed84715b4b02bbULL, 0x00319568adf70486ULL)},
+ {FIELD_LITERAL(0x0070ff2d864de5bbULL, 0x005a37eeb637ee95ULL,
+ 0x0033741c258de160ULL, 0x00e6ca5cb1988f46ULL,
+ 0x001ceabd92a24661ULL, 0x0030957bd500fe40ULL,
+ 0x001c3362afe912c5ULL, 0x005187889f678bd2ULL)},
+ {FIELD_LITERAL(0x0086835fc62bbdc7ULL, 0x009c3516ca4910a1ULL,
+ 0x00956c71f8d00783ULL, 0x0095c78fcf63235fULL,
+ 0x00fc7ff6ba05c222ULL, 0x00cdd8b3f8d74a52ULL,
+ 0x00ac5ae16de8256eULL, 0x00e9d4be8ed48624ULL)},
}}, {{
- {FIELD_LITERAL(0x00c0ce11405df2d8,0x004e3f37b293d7b6,0x002410172e1ac6db,0x00b8dbff4bf8143d,0x003a7b409d56eb66,0x003e0f6a0dfef9af,0x0081c4e4d3645be1,0x00ce76076b127623)},
- {FIELD_LITERAL(0x00f6ee0f98974239,0x0042d89af07d3a4f,0x00846b7fe84346b5,0x006a21fc6a8d39a1,0x00ac8bc2541ff2d9,0x006d4e2a77732732,0x009a39b694cc3f2f,0x0085c0aa2a404c8f)},
- {FIELD_LITERAL(0x00b261101a218548,0x00c1cae96424277b,0x00869da0a77dd268,0x00bc0b09f8ec83ea,0x00d61027f8e82ba9,0x00aa4c85999dce67,0x00eac3132b9f3fe1,0x00fb9b0cf1c695d2)},
+ {FIELD_LITERAL(0x00c0ce11405df2d8ULL, 0x004e3f37b293d7b6ULL,
+ 0x002410172e1ac6dbULL, 0x00b8dbff4bf8143dULL,
+ 0x003a7b409d56eb66ULL, 0x003e0f6a0dfef9afULL,
+ 0x0081c4e4d3645be1ULL, 0x00ce76076b127623ULL)},
+ {FIELD_LITERAL(0x00f6ee0f98974239ULL, 0x0042d89af07d3a4fULL,
+ 0x00846b7fe84346b5ULL, 0x006a21fc6a8d39a1ULL,
+ 0x00ac8bc2541ff2d9ULL, 0x006d4e2a77732732ULL,
+ 0x009a39b694cc3f2fULL, 0x0085c0aa2a404c8fULL)},
+ {FIELD_LITERAL(0x00b261101a218548ULL, 0x00c1cae96424277bULL,
+ 0x00869da0a77dd268ULL, 0x00bc0b09f8ec83eaULL,
+ 0x00d61027f8e82ba9ULL, 0x00aa4c85999dce67ULL,
+ 0x00eac3132b9f3fe1ULL, 0x00fb9b0cf1c695d2ULL)},
}}, {{
- {FIELD_LITERAL(0x0043079295512f0d,0x0046a009861758e0,0x003ee2842a807378,0x0034cc9d1298e4fa,0x009744eb4d31b3ee,0x00afacec96650cd0,0x00ac891b313761ae,0x00e864d6d26e708a)},
- {FIELD_LITERAL(0x00a84d7c8a23b491,0x0088e19aa868b27f,0x0005986d43e78ce9,0x00f28012f0606d28,0x0017ded7e10249b3,0x005ed4084b23af9b,0x00b9b0a940564472,0x00ad9056cceeb1f4)},
- {FIELD_LITERAL(0x00db91b357fe755e,0x00a1aa544b15359c,0x00af4931a0195574,0x007686124fe11aef,0x00d1ead3c7b9ef7e,0x00aaf5fc580f8c15,0x00e727be147ee1ec,0x003c61c1e1577b86)},
+ {FIELD_LITERAL(0x0043079295512f0dULL, 0x0046a009861758e0ULL,
+ 0x003ee2842a807378ULL, 0x0034cc9d1298e4faULL,
+ 0x009744eb4d31b3eeULL, 0x00afacec96650cd0ULL,
+ 0x00ac891b313761aeULL, 0x00e864d6d26e708aULL)},
+ {FIELD_LITERAL(0x00a84d7c8a23b491ULL, 0x0088e19aa868b27fULL,
+ 0x0005986d43e78ce9ULL, 0x00f28012f0606d28ULL,
+ 0x0017ded7e10249b3ULL, 0x005ed4084b23af9bULL,
+ 0x00b9b0a940564472ULL, 0x00ad9056cceeb1f4ULL)},
+ {FIELD_LITERAL(0x00db91b357fe755eULL, 0x00a1aa544b15359cULL,
+ 0x00af4931a0195574ULL, 0x007686124fe11aefULL,
+ 0x00d1ead3c7b9ef7eULL, 0x00aaf5fc580f8c15ULL,
+ 0x00e727be147ee1ecULL, 0x003c61c1e1577b86ULL)},
}}, {{
- {FIELD_LITERAL(0x009d3fca983220cf,0x00cd11acbc853dc4,0x0017590409d27f1d,0x00d2176698082802,0x00fa01251b2838c8,0x00dd297a0d9b51c6,0x00d76c92c045820a,0x00534bc7c46c9033)},
- {FIELD_LITERAL(0x0080ed9bc9b07338,0x00fceac7745d2652,0x008a9d55f5f2cc69,0x0096ce72df301ac5,0x00f53232e7974d87,0x0071728c7ae73947,0x0090507602570778,0x00cb81cfd883b1b2)},
- {FIELD_LITERAL(0x005011aadea373da,0x003a8578ec896034,0x00f20a6535fa6d71,0x005152d31e5a87cf,0x002bac1c8e68ca31,0x00b0e323db4c1381,0x00f1d596b7d5ae25,0x00eae458097cb4e0)},
+ {FIELD_LITERAL(0x009d3fca983220cfULL, 0x00cd11acbc853dc4ULL,
+ 0x0017590409d27f1dULL, 0x00d2176698082802ULL,
+ 0x00fa01251b2838c8ULL, 0x00dd297a0d9b51c6ULL,
+ 0x00d76c92c045820aULL, 0x00534bc7c46c9033ULL)},
+ {FIELD_LITERAL(0x0080ed9bc9b07338ULL, 0x00fceac7745d2652ULL,
+ 0x008a9d55f5f2cc69ULL, 0x0096ce72df301ac5ULL,
+ 0x00f53232e7974d87ULL, 0x0071728c7ae73947ULL,
+ 0x0090507602570778ULL, 0x00cb81cfd883b1b2ULL)},
+ {FIELD_LITERAL(0x005011aadea373daULL, 0x003a8578ec896034ULL,
+ 0x00f20a6535fa6d71ULL, 0x005152d31e5a87cfULL,
+ 0x002bac1c8e68ca31ULL, 0x00b0e323db4c1381ULL,
+ 0x00f1d596b7d5ae25ULL, 0x00eae458097cb4e0ULL)},
}}, {{
- {FIELD_LITERAL(0x00920ac80f9b0d21,0x00f80f7f73401246,0x0086d37849b557d6,0x0002bd4b317b752e,0x00b26463993a42bb,0x002070422a73b129,0x00341acaa0380cb3,0x00541914dd66a1b2)},
- {FIELD_LITERAL(0x00c1513cd66abe8c,0x000139e01118944d,0x0064abbcb8080bbb,0x00b3b08202473142,0x00c629ef25da2403,0x00f0aec3310d9b7f,0x0050b2227472d8cd,0x00f6c8a922d41fb4)},
- {FIELD_LITERAL(0x001075ccf26b7b1f,0x00bb6bb213170433,0x00e9491ad262da79,0x009ef4f48d2d384c,0x008992770766f09d,0x001584396b6b1101,0x00af3f8676c9feef,0x0024603c40269118)},
+ {FIELD_LITERAL(0x00920ac80f9b0d21ULL, 0x00f80f7f73401246ULL,
+ 0x0086d37849b557d6ULL, 0x0002bd4b317b752eULL,
+ 0x00b26463993a42bbULL, 0x002070422a73b129ULL,
+ 0x00341acaa0380cb3ULL, 0x00541914dd66a1b2ULL)},
+ {FIELD_LITERAL(0x00c1513cd66abe8cULL, 0x000139e01118944dULL,
+ 0x0064abbcb8080bbbULL, 0x00b3b08202473142ULL,
+ 0x00c629ef25da2403ULL, 0x00f0aec3310d9b7fULL,
+ 0x0050b2227472d8cdULL, 0x00f6c8a922d41fb4ULL)},
+ {FIELD_LITERAL(0x001075ccf26b7b1fULL, 0x00bb6bb213170433ULL,
+ 0x00e9491ad262da79ULL, 0x009ef4f48d2d384cULL,
+ 0x008992770766f09dULL, 0x001584396b6b1101ULL,
+ 0x00af3f8676c9feefULL, 0x0024603c40269118ULL)},
}}, {{
- {FIELD_LITERAL(0x009dd7b31319527c,0x001e7ac948d873a9,0x00fa54b46ef9673a,0x0066efb8d5b02fe6,0x00754b1d3928aeae,0x0004262ac72a6f6b,0x0079b7d49a6eb026,0x003126a753540102)},
- {FIELD_LITERAL(0x009666e24f693947,0x00f714311269d45f,0x0010ffac1d0c851c,0x0066e80c37363497,0x00f1f4ad010c60b0,0x0015c87408470ff7,0x00651d5e9c7766a4,0x008138819d7116de)},
- {FIELD_LITERAL(0x003934b11c57253b,0x00ef308edf21f46e,0x00e54e99c7a16198,0x0080d57135764e63,0x00751c27b946bc24,0x00dd389ce4e9e129,0x00a1a2bfd1cd84dc,0x002fae73e5149b32)},
+ {FIELD_LITERAL(0x009dd7b31319527cULL, 0x001e7ac948d873a9ULL,
+ 0x00fa54b46ef9673aULL, 0x0066efb8d5b02fe6ULL,
+ 0x00754b1d3928aeaeULL, 0x0004262ac72a6f6bULL,
+ 0x0079b7d49a6eb026ULL, 0x003126a753540102ULL)},
+ {FIELD_LITERAL(0x009666e24f693947ULL, 0x00f714311269d45fULL,
+ 0x0010ffac1d0c851cULL, 0x0066e80c37363497ULL,
+ 0x00f1f4ad010c60b0ULL, 0x0015c87408470ff7ULL,
+ 0x00651d5e9c7766a4ULL, 0x008138819d7116deULL)},
+ {FIELD_LITERAL(0x003934b11c57253bULL, 0x00ef308edf21f46eULL,
+ 0x00e54e99c7a16198ULL, 0x0080d57135764e63ULL,
+ 0x00751c27b946bc24ULL, 0x00dd389ce4e9e129ULL,
+ 0x00a1a2bfd1cd84dcULL, 0x002fae73e5149b32ULL)},
}}, {{
- {FIELD_LITERAL(0x00911657dffb4cdd,0x00c100b7cc553d06,0x00449d075ec467cc,0x007062100bc64e70,0x0043cf86f7bd21e7,0x00f401dc4b797dea,0x005224afb2f62e65,0x00d1ede3fb5a42be)},
- {FIELD_LITERAL(0x00f2ba36a41aa144,0x00a0c22d946ee18f,0x008aae8ef9a14f99,0x00eef4d79b19bb36,0x008e75ce3d27b1fc,0x00a65daa03b29a27,0x00d9cc83684eb145,0x009e1ed80cc2ed74)},
- {FIELD_LITERAL(0x00bed953d1997988,0x00b93ed175a24128,0x00871c5963fb6365,0x00ca2df20014a787,0x00f5d9c1d0b34322,0x00f6f5942818db0a,0x004cc091f49c9906,0x00e8a188a60bff9f)},
+ {FIELD_LITERAL(0x00911657dffb4cddULL, 0x00c100b7cc553d06ULL,
+ 0x00449d075ec467ccULL, 0x007062100bc64e70ULL,
+ 0x0043cf86f7bd21e7ULL, 0x00f401dc4b797deaULL,
+ 0x005224afb2f62e65ULL, 0x00d1ede3fb5a42beULL)},
+ {FIELD_LITERAL(0x00f2ba36a41aa144ULL, 0x00a0c22d946ee18fULL,
+ 0x008aae8ef9a14f99ULL, 0x00eef4d79b19bb36ULL,
+ 0x008e75ce3d27b1fcULL, 0x00a65daa03b29a27ULL,
+ 0x00d9cc83684eb145ULL, 0x009e1ed80cc2ed74ULL)},
+ {FIELD_LITERAL(0x00bed953d1997988ULL, 0x00b93ed175a24128ULL,
+ 0x00871c5963fb6365ULL, 0x00ca2df20014a787ULL,
+ 0x00f5d9c1d0b34322ULL, 0x00f6f5942818db0aULL,
+ 0x004cc091f49c9906ULL, 0x00e8a188a60bff9fULL)},
}}, {{
- {FIELD_LITERAL(0x0032c7762032fae8,0x00e4087232e0bc21,0x00f767344b6e8d85,0x00bbf369b76c2aa2,0x008a1f46c6e1570c,0x001368cd9780369f,0x007359a39d079430,0x0003646512921434)},
- {FIELD_LITERAL(0x007c4b47ca7c73e7,0x005396221039734b,0x008b64ddf0e45d7e,0x00bfad5af285e6c2,0x008ec711c5b1a1a8,0x00cf663301237f98,0x00917ee3f1655126,0x004152f337efedd8)},
- {FIELD_LITERAL(0x0007c7edc9305daa,0x000a6664f273701c,0x00f6e78795e200b1,0x005d05b9ecd2473e,0x0014f5f17c865786,0x00c7fd2d166fa995,0x004939a2d8eb80e0,0x002244ba0942c199)},
+ {FIELD_LITERAL(0x0032c7762032fae8ULL, 0x00e4087232e0bc21ULL,
+ 0x00f767344b6e8d85ULL, 0x00bbf369b76c2aa2ULL,
+ 0x008a1f46c6e1570cULL, 0x001368cd9780369fULL,
+ 0x007359a39d079430ULL, 0x0003646512921434ULL)},
+ {FIELD_LITERAL(0x007c4b47ca7c73e7ULL, 0x005396221039734bULL,
+ 0x008b64ddf0e45d7eULL, 0x00bfad5af285e6c2ULL,
+ 0x008ec711c5b1a1a8ULL, 0x00cf663301237f98ULL,
+ 0x00917ee3f1655126ULL, 0x004152f337efedd8ULL)},
+ {FIELD_LITERAL(0x0007c7edc9305daaULL, 0x000a6664f273701cULL,
+ 0x00f6e78795e200b1ULL, 0x005d05b9ecd2473eULL,
+ 0x0014f5f17c865786ULL, 0x00c7fd2d166fa995ULL,
+ 0x004939a2d8eb80e0ULL, 0x002244ba0942c199ULL)},
}}, {{
- {FIELD_LITERAL(0x00321e767f0262cf,0x002e57d776caf68e,0x00bf2c94814f0437,0x00c339196acd622f,0x001db4cce71e2770,0x001ded5ddba6eee2,0x0078608ab1554c8d,0x00067fe0ab76365b)},
- {FIELD_LITERAL(0x00f09758e11e3985,0x00169efdbd64fad3,0x00e8889b7d6dacd6,0x0035cdd58ea88209,0x00bcda47586d7f49,0x003cdddcb2879088,0x0016da70187e954b,0x009556ea2e92aacd)},
- {FIELD_LITERAL(0x008cab16bd1ff897,0x00b389972cdf753f,0x00ea8ed1e46dfdc0,0x004fe7ef94c589f4,0x002b8ae9b805ecf3,0x0025c08d892874a5,0x0023938e98d44c4c,0x00f759134cabf69c)},
+ {FIELD_LITERAL(0x00321e767f0262cfULL, 0x002e57d776caf68eULL,
+ 0x00bf2c94814f0437ULL, 0x00c339196acd622fULL,
+ 0x001db4cce71e2770ULL, 0x001ded5ddba6eee2ULL,
+ 0x0078608ab1554c8dULL, 0x00067fe0ab76365bULL)},
+ {FIELD_LITERAL(0x00f09758e11e3985ULL, 0x00169efdbd64fad3ULL,
+ 0x00e8889b7d6dacd6ULL, 0x0035cdd58ea88209ULL,
+ 0x00bcda47586d7f49ULL, 0x003cdddcb2879088ULL,
+ 0x0016da70187e954bULL, 0x009556ea2e92aacdULL)},
+ {FIELD_LITERAL(0x008cab16bd1ff897ULL, 0x00b389972cdf753fULL,
+ 0x00ea8ed1e46dfdc0ULL, 0x004fe7ef94c589f4ULL,
+ 0x002b8ae9b805ecf3ULL, 0x0025c08d892874a5ULL,
+ 0x0023938e98d44c4cULL, 0x00f759134cabf69cULL)},
}}, {{
- {FIELD_LITERAL(0x006c2a84678e4b3b,0x007a194aacd1868f,0x00ed0225af424761,0x00da0a6f293c64b8,0x001062ac5c6a7a18,0x0030f5775a8aeef4,0x0002acaad76b7af0,0x00410b8fd63a579f)},
- {FIELD_LITERAL(0x001ec59db3d9590e,0x001e9e3f1c3f182d,0x0045a9c3ec2cab14,0x0008198572aeb673,0x00773b74068bd167,0x0012535eaa395434,0x0044dba9e3bbb74a,0x002fba4d3c74bd0e)},
- {FIELD_LITERAL(0x0042bf08fe66922c,0x003318b8fbb49e8c,0x00d75946004aa14c,0x00f601586b42bf1c,0x00c74cf1d912fe66,0x00abcb36974b30ad,0x007eb78720c9d2b8,0x009f54ab7bd4df85)},
+ {FIELD_LITERAL(0x006c2a84678e4b3bULL, 0x007a194aacd1868fULL,
+ 0x00ed0225af424761ULL, 0x00da0a6f293c64b8ULL,
+ 0x001062ac5c6a7a18ULL, 0x0030f5775a8aeef4ULL,
+ 0x0002acaad76b7af0ULL, 0x00410b8fd63a579fULL)},
+ {FIELD_LITERAL(0x001ec59db3d9590eULL, 0x001e9e3f1c3f182dULL,
+ 0x0045a9c3ec2cab14ULL, 0x0008198572aeb673ULL,
+ 0x00773b74068bd167ULL, 0x0012535eaa395434ULL,
+ 0x0044dba9e3bbb74aULL, 0x002fba4d3c74bd0eULL)},
+ {FIELD_LITERAL(0x0042bf08fe66922cULL, 0x003318b8fbb49e8cULL,
+ 0x00d75946004aa14cULL, 0x00f601586b42bf1cULL,
+ 0x00c74cf1d912fe66ULL, 0x00abcb36974b30adULL,
+ 0x007eb78720c9d2b8ULL, 0x009f54ab7bd4df85ULL)},
}}, {{
- {FIELD_LITERAL(0x00db9fc948f73826,0x00fa8b3746ed8ee9,0x00132cb65aafbeb2,0x00c36ff3fe7925b8,0x00837daed353d2fe,0x00ec661be0667cf4,0x005beb8ed2e90204,0x00d77dd69e564967)},
- {FIELD_LITERAL(0x0042e6268b861751,0x0008dd0469500c16,0x00b51b57c338a3fd,0x00cc4497d85cff6b,0x002f13d6b57c34a4,0x0083652eaf301105,0x00cc344294cc93a8,0x0060f4d02810e270)},
- {FIELD_LITERAL(0x00a8954363cd518b,0x00ad171124bccb7b,0x0065f46a4adaae00,0x001b1a5b2a96e500,0x0043fe24f8233285,0x0066996d8ae1f2c3,0x00c530f3264169f9,0x00c0f92d07cf6a57)},
+ {FIELD_LITERAL(0x00db9fc948f73826ULL, 0x00fa8b3746ed8ee9ULL,
+ 0x00132cb65aafbeb2ULL, 0x00c36ff3fe7925b8ULL,
+ 0x00837daed353d2feULL, 0x00ec661be0667cf4ULL,
+ 0x005beb8ed2e90204ULL, 0x00d77dd69e564967ULL)},
+ {FIELD_LITERAL(0x0042e6268b861751ULL, 0x0008dd0469500c16ULL,
+ 0x00b51b57c338a3fdULL, 0x00cc4497d85cff6bULL,
+ 0x002f13d6b57c34a4ULL, 0x0083652eaf301105ULL,
+ 0x00cc344294cc93a8ULL, 0x0060f4d02810e270ULL)},
+ {FIELD_LITERAL(0x00a8954363cd518bULL, 0x00ad171124bccb7bULL,
+ 0x0065f46a4adaae00ULL, 0x001b1a5b2a96e500ULL,
+ 0x0043fe24f8233285ULL, 0x0066996d8ae1f2c3ULL,
+ 0x00c530f3264169f9ULL, 0x00c0f92d07cf6a57ULL)},
}}, {{
- {FIELD_LITERAL(0x0036a55c6815d943,0x008c8d1def993db3,0x002e0e1e8ff7318f,0x00d883a4b92db00a,0x002f5e781ae33906,0x001a72adb235c06d,0x00f2e59e736e9caa,0x001a4b58e3031914)},
- {FIELD_LITERAL(0x00d73bfae5e00844,0x00bf459766fb5f52,0x0061b4f5a5313cde,0x004392d4c3b95514,0x000d3551b1077523,0x0000998840ee5d71,0x006de6e340448b7b,0x00251aa504875d6e)},
- {FIELD_LITERAL(0x003bf343427ac342,0x00adc0a78642b8c5,0x0003b893175a8314,0x0061a34ade5703bc,0x00ea3ea8bb71d632,0x00be0df9a1f198c2,0x0046dd8e7c1635fb,0x00f1523fdd25d5e5)},
+ {FIELD_LITERAL(0x0036a55c6815d943ULL, 0x008c8d1def993db3ULL,
+ 0x002e0e1e8ff7318fULL, 0x00d883a4b92db00aULL,
+ 0x002f5e781ae33906ULL, 0x001a72adb235c06dULL,
+ 0x00f2e59e736e9caaULL, 0x001a4b58e3031914ULL)},
+ {FIELD_LITERAL(0x00d73bfae5e00844ULL, 0x00bf459766fb5f52ULL,
+ 0x0061b4f5a5313cdeULL, 0x004392d4c3b95514ULL,
+ 0x000d3551b1077523ULL, 0x0000998840ee5d71ULL,
+ 0x006de6e340448b7bULL, 0x00251aa504875d6eULL)},
+ {FIELD_LITERAL(0x003bf343427ac342ULL, 0x00adc0a78642b8c5ULL,
+ 0x0003b893175a8314ULL, 0x0061a34ade5703bcULL,
+ 0x00ea3ea8bb71d632ULL, 0x00be0df9a1f198c2ULL,
+ 0x0046dd8e7c1635fbULL, 0x00f1523fdd25d5e5ULL)},
}}, {{
- {FIELD_LITERAL(0x00633f63fc9dd406,0x00e713ff80e04a43,0x0060c6e970f2d621,0x00a57cd7f0df1891,0x00f2406a550650bb,0x00b064290efdc684,0x001eab0144d17916,0x00cd15f863c293ab)},
- {FIELD_LITERAL(0x0029cec55273f70d,0x007044ee275c6340,0x0040f637a93015e2,0x00338bb78db5aae9,0x001491b2a6132147,0x00a125d6cfe6bde3,0x005f7ac561ba8669,0x001d5eaea3fbaacf)},
- {FIELD_LITERAL(0x00054e9635e3be31,0x000e43f31e2872be,0x00d05b1c9e339841,0x006fac50bd81fd98,0x00cdc7852eaebb09,0x004ff519b061991b,0x009099e8107d4c85,0x00273e24c36a4a61)},
+ {FIELD_LITERAL(0x00633f63fc9dd406ULL, 0x00e713ff80e04a43ULL,
+ 0x0060c6e970f2d621ULL, 0x00a57cd7f0df1891ULL,
+ 0x00f2406a550650bbULL, 0x00b064290efdc684ULL,
+ 0x001eab0144d17916ULL, 0x00cd15f863c293abULL)},
+ {FIELD_LITERAL(0x0029cec55273f70dULL, 0x007044ee275c6340ULL,
+ 0x0040f637a93015e2ULL, 0x00338bb78db5aae9ULL,
+ 0x001491b2a6132147ULL, 0x00a125d6cfe6bde3ULL,
+ 0x005f7ac561ba8669ULL, 0x001d5eaea3fbaacfULL)},
+ {FIELD_LITERAL(0x00054e9635e3be31ULL, 0x000e43f31e2872beULL,
+ 0x00d05b1c9e339841ULL, 0x006fac50bd81fd98ULL,
+ 0x00cdc7852eaebb09ULL, 0x004ff519b061991bULL,
+ 0x009099e8107d4c85ULL, 0x00273e24c36a4a61ULL)},
}}, {{
- {FIELD_LITERAL(0x00070b4441ef2c46,0x00efa5b02801a109,0x00bf0b8c3ee64adf,0x008a67e0b3452e98,0x001916b1f2fa7a74,0x00d781a78ff6cdc3,0x008682ce57e5c919,0x00cc1109dd210da3)},
- {FIELD_LITERAL(0x00cae8aaff388663,0x005e983a35dda1c7,0x007ab1030d8e37f4,0x00e48940f5d032fe,0x006a36f9ef30b331,0x009be6f03958c757,0x0086231ceba91400,0x008bd0f7b823e7aa)},
- {FIELD_LITERAL(0x00cf881ebef5a45a,0x004ebea78e7c6f2c,0x0090da9209cf26a0,0x00de2b2e4c775b84,0x0071d6031c3c15ae,0x00d9e927ef177d70,0x00894ee8c23896fd,0x00e3b3b401e41aad)},
+ {FIELD_LITERAL(0x00070b4441ef2c46ULL, 0x00efa5b02801a109ULL,
+ 0x00bf0b8c3ee64adfULL, 0x008a67e0b3452e98ULL,
+ 0x001916b1f2fa7a74ULL, 0x00d781a78ff6cdc3ULL,
+ 0x008682ce57e5c919ULL, 0x00cc1109dd210da3ULL)},
+ {FIELD_LITERAL(0x00cae8aaff388663ULL, 0x005e983a35dda1c7ULL,
+ 0x007ab1030d8e37f4ULL, 0x00e48940f5d032feULL,
+ 0x006a36f9ef30b331ULL, 0x009be6f03958c757ULL,
+ 0x0086231ceba91400ULL, 0x008bd0f7b823e7aaULL)},
+ {FIELD_LITERAL(0x00cf881ebef5a45aULL, 0x004ebea78e7c6f2cULL,
+ 0x0090da9209cf26a0ULL, 0x00de2b2e4c775b84ULL,
+ 0x0071d6031c3c15aeULL, 0x00d9e927ef177d70ULL,
+ 0x00894ee8c23896fdULL, 0x00e3b3b401e41aadULL)},
}}, {{
- {FIELD_LITERAL(0x00204fef26864170,0x00819269c5dee0f8,0x00bfb4713ec97966,0x0026339a6f34df78,0x001f26e64c761dc2,0x00effe3af313cb60,0x00e17b70138f601b,0x00f16e1ccd9ede5e)},
- {FIELD_LITERAL(0x005d9a8353fdb2db,0x0055cc2048c698f0,0x00f6c4ac89657218,0x00525034d73faeb2,0x00435776fbda3c7d,0x0070ea5312323cbc,0x007a105d44d069fb,0x006dbc8d6dc786aa)},
- {FIELD_LITERAL(0x0017cff19cd394ec,0x00fef7b810922587,0x00e6483970dff548,0x00ddf36ad6874264,0x00e61778523fcce2,0x0093a66c0c93b24a,0x00fd367114db7f86,0x007652d7ddce26dd)},
+ {FIELD_LITERAL(0x00204fef26864170ULL, 0x00819269c5dee0f8ULL,
+ 0x00bfb4713ec97966ULL, 0x0026339a6f34df78ULL,
+ 0x001f26e64c761dc2ULL, 0x00effe3af313cb60ULL,
+ 0x00e17b70138f601bULL, 0x00f16e1ccd9ede5eULL)},
+ {FIELD_LITERAL(0x005d9a8353fdb2dbULL, 0x0055cc2048c698f0ULL,
+ 0x00f6c4ac89657218ULL, 0x00525034d73faeb2ULL,
+ 0x00435776fbda3c7dULL, 0x0070ea5312323cbcULL,
+ 0x007a105d44d069fbULL, 0x006dbc8d6dc786aaULL)},
+ {FIELD_LITERAL(0x0017cff19cd394ecULL, 0x00fef7b810922587ULL,
+ 0x00e6483970dff548ULL, 0x00ddf36ad6874264ULL,
+ 0x00e61778523fcce2ULL, 0x0093a66c0c93b24aULL,
+ 0x00fd367114db7f86ULL, 0x007652d7ddce26ddULL)},
}}, {{
- {FIELD_LITERAL(0x00d92ced7ba12843,0x00aea9c7771e86e7,0x0046639693354f7b,0x00a628dbb6a80c47,0x003a0b0507372953,0x00421113ab45c0d9,0x00e545f08362ab7a,0x0028ce087b4d6d96)},
- {FIELD_LITERAL(0x00a67ee7cf9f99eb,0x005713b275f2ff68,0x00f1d536a841513d,0x00823b59b024712e,0x009c46b9d0d38cec,0x00cdb1595aa2d7d4,0x008375b3423d9af8,0x000ab0b516d978f7)},
- {FIELD_LITERAL(0x00428dcb3c510b0f,0x00585607ea24bb4e,0x003736bf1603687a,0x00c47e568c4fe3c7,0x003cd00282848605,0x0043a487c3b91939,0x004ffc04e1095a06,0x00a4c989a3d4b918)},
+ {FIELD_LITERAL(0x00d92ced7ba12843ULL, 0x00aea9c7771e86e7ULL,
+ 0x0046639693354f7bULL, 0x00a628dbb6a80c47ULL,
+ 0x003a0b0507372953ULL, 0x00421113ab45c0d9ULL,
+ 0x00e545f08362ab7aULL, 0x0028ce087b4d6d96ULL)},
+ {FIELD_LITERAL(0x00a67ee7cf9f99ebULL, 0x005713b275f2ff68ULL,
+ 0x00f1d536a841513dULL, 0x00823b59b024712eULL,
+ 0x009c46b9d0d38cecULL, 0x00cdb1595aa2d7d4ULL,
+ 0x008375b3423d9af8ULL, 0x000ab0b516d978f7ULL)},
+ {FIELD_LITERAL(0x00428dcb3c510b0fULL, 0x00585607ea24bb4eULL,
+ 0x003736bf1603687aULL, 0x00c47e568c4fe3c7ULL,
+ 0x003cd00282848605ULL, 0x0043a487c3b91939ULL,
+ 0x004ffc04e1095a06ULL, 0x00a4c989a3d4b918ULL)},
}}, {{
- {FIELD_LITERAL(0x00a8778d0e429f7a,0x004c02b059105a68,0x0016653b609da3ff,0x00d5107bd1a12d27,0x00b4708f9a771cab,0x00bb63b662033f69,0x0072f322240e7215,0x0019445b59c69222)},
- {FIELD_LITERAL(0x00cf4f6069a658e6,0x0053ca52859436a6,0x0064b994d7e3e117,0x00cb469b9a07f534,0x00cfb68f399e9d47,0x00f0dcb8dac1c6e7,0x00f2ab67f538b3a5,0x0055544f178ab975)},
- {FIELD_LITERAL(0x0099b7a2685d538c,0x00e2f1897b7c0018,0x003adac8ce48dae3,0x00089276d5c50c0c,0x00172fca07ad6717,0x00cb1a72f54069e5,0x004ee42f133545b3,0x00785f8651362f16)},
+ {FIELD_LITERAL(0x00a8778d0e429f7aULL, 0x004c02b059105a68ULL,
+ 0x0016653b609da3ffULL, 0x00d5107bd1a12d27ULL,
+ 0x00b4708f9a771cabULL, 0x00bb63b662033f69ULL,
+ 0x0072f322240e7215ULL, 0x0019445b59c69222ULL)},
+ {FIELD_LITERAL(0x00cf4f6069a658e6ULL, 0x0053ca52859436a6ULL,
+ 0x0064b994d7e3e117ULL, 0x00cb469b9a07f534ULL,
+ 0x00cfb68f399e9d47ULL, 0x00f0dcb8dac1c6e7ULL,
+ 0x00f2ab67f538b3a5ULL, 0x0055544f178ab975ULL)},
+ {FIELD_LITERAL(0x0099b7a2685d538cULL, 0x00e2f1897b7c0018ULL,
+ 0x003adac8ce48dae3ULL, 0x00089276d5c50c0cULL,
+ 0x00172fca07ad6717ULL, 0x00cb1a72f54069e5ULL,
+ 0x004ee42f133545b3ULL, 0x00785f8651362f16ULL)},
}}, {{
- {FIELD_LITERAL(0x0049cbac38509e11,0x0015234505d42cdf,0x00794fb0b5840f1c,0x00496437344045a5,0x0031b6d944e4f9b0,0x00b207318ac1f5d8,0x0000c840da7f5c5d,0x00526f373a5c8814)},
- {FIELD_LITERAL(0x002c7b7742d1dfd9,0x002cabeb18623c01,0x00055f5e3e044446,0x006c20f3b4ef54ba,0x00c600141ec6b35f,0x00354f437f1a32a3,0x00bac4624a3520f9,0x00c483f734a90691)},
- {FIELD_LITERAL(0x0053a737d422918d,0x00f7fca1d8758625,0x00c360336dadb04c,0x00f38e3d9158a1b8,0x0069ce3b418e84c6,0x005d1697eca16ead,0x00f8bd6a35ece13d,0x007885dfc2b5afea)},
+ {FIELD_LITERAL(0x0049cbac38509e11ULL, 0x0015234505d42cdfULL,
+ 0x00794fb0b5840f1cULL, 0x00496437344045a5ULL,
+ 0x0031b6d944e4f9b0ULL, 0x00b207318ac1f5d8ULL,
+ 0x0000c840da7f5c5dULL, 0x00526f373a5c8814ULL)},
+ {FIELD_LITERAL(0x002c7b7742d1dfd9ULL, 0x002cabeb18623c01ULL,
+ 0x00055f5e3e044446ULL, 0x006c20f3b4ef54baULL,
+ 0x00c600141ec6b35fULL, 0x00354f437f1a32a3ULL,
+ 0x00bac4624a3520f9ULL, 0x00c483f734a90691ULL)},
+ {FIELD_LITERAL(0x0053a737d422918dULL, 0x00f7fca1d8758625ULL,
+ 0x00c360336dadb04cULL, 0x00f38e3d9158a1b8ULL,
+ 0x0069ce3b418e84c6ULL, 0x005d1697eca16eadULL,
+ 0x00f8bd6a35ece13dULL, 0x007885dfc2b5afeaULL)},
}}, {{
- {FIELD_LITERAL(0x00c3617ae260776c,0x00b20dc3e96922d7,0x00a1a7802246706a,0x00ca6505a5240244,0x002246b62d919782,0x001439102d7aa9b3,0x00e8af1139e6422c,0x00c888d1b52f2b05)},
- {FIELD_LITERAL(0x005b67690ffd41d9,0x005294f28df516f9,0x00a879272412fcb9,0x00098b629a6d1c8d,0x00fabd3c8050865a,0x00cd7e5b0a3879c5,0x00153238210f3423,0x00357cac101e9f42)},
- {FIELD_LITERAL(0x008917b454444fb7,0x00f59247c97e441b,0x00a6200a6815152d,0x0009a4228601d254,0x001c0360559bd374,0x007563362039cb36,0x00bd75b48d74e32b,0x0017f515ac3499e8)},
+ {FIELD_LITERAL(0x00c3617ae260776cULL, 0x00b20dc3e96922d7ULL,
+ 0x00a1a7802246706aULL, 0x00ca6505a5240244ULL,
+ 0x002246b62d919782ULL, 0x001439102d7aa9b3ULL,
+ 0x00e8af1139e6422cULL, 0x00c888d1b52f2b05ULL)},
+ {FIELD_LITERAL(0x005b67690ffd41d9ULL, 0x005294f28df516f9ULL,
+ 0x00a879272412fcb9ULL, 0x00098b629a6d1c8dULL,
+ 0x00fabd3c8050865aULL, 0x00cd7e5b0a3879c5ULL,
+ 0x00153238210f3423ULL, 0x00357cac101e9f42ULL)},
+ {FIELD_LITERAL(0x008917b454444fb7ULL, 0x00f59247c97e441bULL,
+ 0x00a6200a6815152dULL, 0x0009a4228601d254ULL,
+ 0x001c0360559bd374ULL, 0x007563362039cb36ULL,
+ 0x00bd75b48d74e32bULL, 0x0017f515ac3499e8ULL)},
}}, {{
- {FIELD_LITERAL(0x001532a7ffe41c5a,0x00eb1edce358d6bf,0x00ddbacc7b678a7b,0x008a7b70f3c841a3,0x00f1923bf27d3f4c,0x000b2713ed8f7873,0x00aaf67e29047902,0x0044994a70b3976d)},
- {FIELD_LITERAL(0x00d54e802082d42c,0x00a55aa0dce7cc6c,0x006477b96073f146,0x0082efe4ceb43594,0x00a922bcba026845,0x0077f19d1ab75182,0x00c2bb2737846e59,0x0004d7eec791dd33)},
- {FIELD_LITERAL(0x0044588d1a81d680,0x00b0a9097208e4f8,0x00212605350dc57e,0x0028717cd2871123,0x00fb083c100fd979,0x0045a056ce063fdf,0x00a5d604b4dd6a41,0x001dabc08ba4e236)},
+ {FIELD_LITERAL(0x001532a7ffe41c5aULL, 0x00eb1edce358d6bfULL,
+ 0x00ddbacc7b678a7bULL, 0x008a7b70f3c841a3ULL,
+ 0x00f1923bf27d3f4cULL, 0x000b2713ed8f7873ULL,
+ 0x00aaf67e29047902ULL, 0x0044994a70b3976dULL)},
+ {FIELD_LITERAL(0x00d54e802082d42cULL, 0x00a55aa0dce7cc6cULL,
+ 0x006477b96073f146ULL, 0x0082efe4ceb43594ULL,
+ 0x00a922bcba026845ULL, 0x0077f19d1ab75182ULL,
+ 0x00c2bb2737846e59ULL, 0x0004d7eec791dd33ULL)},
+ {FIELD_LITERAL(0x0044588d1a81d680ULL, 0x00b0a9097208e4f8ULL,
+ 0x00212605350dc57eULL, 0x0028717cd2871123ULL,
+ 0x00fb083c100fd979ULL, 0x0045a056ce063fdfULL,
+ 0x00a5d604b4dd6a41ULL, 0x001dabc08ba4e236ULL)},
}}, {{
- {FIELD_LITERAL(0x00c4887198d7a7fa,0x00244f98fb45784a,0x0045911e15a15d01,0x001d323d374c0966,0x00967c3915196562,0x0039373abd2f3c67,0x000d2c5614312423,0x0041cf2215442ce3)},
- {FIELD_LITERAL(0x008ede889ada7f06,0x001611e91de2e135,0x00fdb9a458a471b9,0x00563484e03710d1,0x0031cc81925e3070,0x0062c97b3af80005,0x00fa733eea28edeb,0x00e82457e1ebbc88)},
- {FIELD_LITERAL(0x006a0df5fe9b6f59,0x00a0d4ff46040d92,0x004a7cedb6f93250,0x00d1df8855b8c357,0x00e73a46086fd058,0x0048fb0add6dfe59,0x001e03a28f1b4e3d,0x00a871c993308d76)},
+ {FIELD_LITERAL(0x00c4887198d7a7faULL, 0x00244f98fb45784aULL,
+ 0x0045911e15a15d01ULL, 0x001d323d374c0966ULL,
+ 0x00967c3915196562ULL, 0x0039373abd2f3c67ULL,
+ 0x000d2c5614312423ULL, 0x0041cf2215442ce3ULL)},
+ {FIELD_LITERAL(0x008ede889ada7f06ULL, 0x001611e91de2e135ULL,
+ 0x00fdb9a458a471b9ULL, 0x00563484e03710d1ULL,
+ 0x0031cc81925e3070ULL, 0x0062c97b3af80005ULL,
+ 0x00fa733eea28edebULL, 0x00e82457e1ebbc88ULL)},
+ {FIELD_LITERAL(0x006a0df5fe9b6f59ULL, 0x00a0d4ff46040d92ULL,
+ 0x004a7cedb6f93250ULL, 0x00d1df8855b8c357ULL,
+ 0x00e73a46086fd058ULL, 0x0048fb0add6dfe59ULL,
+ 0x001e03a28f1b4e3dULL, 0x00a871c993308d76ULL)},
}}, {{
- {FIELD_LITERAL(0x0030dbb2d1766ec8,0x00586c0ad138555e,0x00d1a34f9e91c77c,0x0063408ad0e89014,0x00d61231b05f6f5b,0x0009abf569f5fd8a,0x00aec67a110f1c43,0x0031d1a790938dd7)},
- {FIELD_LITERAL(0x006cded841e2a862,0x00198d60af0ab6fb,0x0018f09db809e750,0x004e6ac676016263,0x00eafcd1620969cb,0x002c9784ca34917d,0x0054f00079796de7,0x00d9fab5c5972204)},
- {FIELD_LITERAL(0x004bd0fee2438a83,0x00b571e62b0f83bd,0x0059287d7ce74800,0x00fb3631b645c3f0,0x00a018e977f78494,0x0091e27065c27b12,0x007696c1817165e0,0x008c40be7c45ba3a)},
+ {FIELD_LITERAL(0x0030dbb2d1766ec8ULL, 0x00586c0ad138555eULL,
+ 0x00d1a34f9e91c77cULL, 0x0063408ad0e89014ULL,
+ 0x00d61231b05f6f5bULL, 0x0009abf569f5fd8aULL,
+ 0x00aec67a110f1c43ULL, 0x0031d1a790938dd7ULL)},
+ {FIELD_LITERAL(0x006cded841e2a862ULL, 0x00198d60af0ab6fbULL,
+ 0x0018f09db809e750ULL, 0x004e6ac676016263ULL,
+ 0x00eafcd1620969cbULL, 0x002c9784ca34917dULL,
+ 0x0054f00079796de7ULL, 0x00d9fab5c5972204ULL)},
+ {FIELD_LITERAL(0x004bd0fee2438a83ULL, 0x00b571e62b0f83bdULL,
+ 0x0059287d7ce74800ULL, 0x00fb3631b645c3f0ULL,
+ 0x00a018e977f78494ULL, 0x0091e27065c27b12ULL,
+ 0x007696c1817165e0ULL, 0x008c40be7c45ba3aULL)},
}}, {{
- {FIELD_LITERAL(0x00a0f326327cb684,0x001c7d0f672680ff,0x008c1c81ffb112d1,0x00f8f801674eddc8,0x00e926d5d48c2a9d,0x005bd6d954c6fe9a,0x004c6b24b4e33703,0x00d05eb5c09105cc)},
- {FIELD_LITERAL(0x00d61731caacf2cf,0x002df0c7609e01c5,0x00306172208b1e2b,0x00b413fe4fb2b686,0x00826d360902a221,0x003f8d056e67e7f7,0x0065025b0175e989,0x00369add117865eb)},
- {FIELD_LITERAL(0x00aaf895aec2fa11,0x000f892bc313eb52,0x005b1c794dad050b,0x003f8ec4864cec14,0x00af81058d0b90e5,0x00ebe43e183997bb,0x00a9d610f9f3e615,0x007acd8eec2e88d3)},
+ {FIELD_LITERAL(0x00a0f326327cb684ULL, 0x001c7d0f672680ffULL,
+ 0x008c1c81ffb112d1ULL, 0x00f8f801674eddc8ULL,
+ 0x00e926d5d48c2a9dULL, 0x005bd6d954c6fe9aULL,
+ 0x004c6b24b4e33703ULL, 0x00d05eb5c09105ccULL)},
+ {FIELD_LITERAL(0x00d61731caacf2cfULL, 0x002df0c7609e01c5ULL,
+ 0x00306172208b1e2bULL, 0x00b413fe4fb2b686ULL,
+ 0x00826d360902a221ULL, 0x003f8d056e67e7f7ULL,
+ 0x0065025b0175e989ULL, 0x00369add117865ebULL)},
+ {FIELD_LITERAL(0x00aaf895aec2fa11ULL, 0x000f892bc313eb52ULL,
+ 0x005b1c794dad050bULL, 0x003f8ec4864cec14ULL,
+ 0x00af81058d0b90e5ULL, 0x00ebe43e183997bbULL,
+ 0x00a9d610f9f3e615ULL, 0x007acd8eec2e88d3ULL)},
}}, {{
- {FIELD_LITERAL(0x0049b2fab13812a3,0x00846db32cd60431,0x000177fa578c8d6c,0x00047d0e2ad4bc51,0x00b158ba38d1e588,0x006a45daad79e3f3,0x000997b93cab887b,0x00c47ea42fa23dc3)},
- {FIELD_LITERAL(0x0012b6fef7aeb1ca,0x009412768194b6a7,0x00ff0d351f23ab93,0x007e8a14c1aff71b,0x006c1c0170c512bc,0x0016243ea02ab2e5,0x007bb6865b303f3e,0x0015ce6b29b159f4)},
- {FIELD_LITERAL(0x009961cd02e68108,0x00e2035d3a1d0836,0x005d51f69b5e1a1d,0x004bccb4ea36edcd,0x0069be6a7aeef268,0x0063f4dd9de8d5a7,0x006283783092ca35,0x0075a31af2c35409)},
+ {FIELD_LITERAL(0x0049b2fab13812a3ULL, 0x00846db32cd60431ULL,
+ 0x000177fa578c8d6cULL, 0x00047d0e2ad4bc51ULL,
+ 0x00b158ba38d1e588ULL, 0x006a45daad79e3f3ULL,
+ 0x000997b93cab887bULL, 0x00c47ea42fa23dc3ULL)},
+ {FIELD_LITERAL(0x0012b6fef7aeb1caULL, 0x009412768194b6a7ULL,
+ 0x00ff0d351f23ab93ULL, 0x007e8a14c1aff71bULL,
+ 0x006c1c0170c512bcULL, 0x0016243ea02ab2e5ULL,
+ 0x007bb6865b303f3eULL, 0x0015ce6b29b159f4ULL)},
+ {FIELD_LITERAL(0x009961cd02e68108ULL, 0x00e2035d3a1d0836ULL,
+ 0x005d51f69b5e1a1dULL, 0x004bccb4ea36edcdULL,
+ 0x0069be6a7aeef268ULL, 0x0063f4dd9de8d5a7ULL,
+ 0x006283783092ca35ULL, 0x0075a31af2c35409ULL)},
}}, {{
- {FIELD_LITERAL(0x00c412365162e8cf,0x00012283fb34388a,0x003e6543babf39e2,0x00eead6b3a804978,0x0099c0314e8b326f,0x00e98e0a8d477a4f,0x00d2eb96b127a687,0x00ed8d7df87571bb)},
- {FIELD_LITERAL(0x00777463e308cacf,0x00c8acb93950132d,0x00ebddbf4ca48b2c,0x0026ad7ca0795a0a,0x00f99a3d9a715064,0x000d60bcf9d4dfcc,0x005e65a73a437a06,0x0019d536a8db56c8)},
- {FIELD_LITERAL(0x00192d7dd558d135,0x0027cd6a8323ffa7,0x00239f1a412dc1e7,0x0046b4b3be74fc5c,0x0020c47a2bef5bce,0x00aa17e48f43862b,0x00f7e26c96342e5f,0x0008011c530f39a9)},
+ {FIELD_LITERAL(0x00c412365162e8cfULL, 0x00012283fb34388aULL,
+ 0x003e6543babf39e2ULL, 0x00eead6b3a804978ULL,
+ 0x0099c0314e8b326fULL, 0x00e98e0a8d477a4fULL,
+ 0x00d2eb96b127a687ULL, 0x00ed8d7df87571bbULL)},
+ {FIELD_LITERAL(0x00777463e308cacfULL, 0x00c8acb93950132dULL,
+ 0x00ebddbf4ca48b2cULL, 0x0026ad7ca0795a0aULL,
+ 0x00f99a3d9a715064ULL, 0x000d60bcf9d4dfccULL,
+ 0x005e65a73a437a06ULL, 0x0019d536a8db56c8ULL)},
+ {FIELD_LITERAL(0x00192d7dd558d135ULL, 0x0027cd6a8323ffa7ULL,
+ 0x00239f1a412dc1e7ULL, 0x0046b4b3be74fc5cULL,
+ 0x0020c47a2bef5bceULL, 0x00aa17e48f43862bULL,
+ 0x00f7e26c96342e5fULL, 0x0008011c530f39a9ULL)},
}}, {{
- {FIELD_LITERAL(0x00aad4ac569bf0f1,0x00a67adc90b27740,0x0048551369a5751a,0x0031252584a3306a,0x0084e15df770e6fc,0x00d7bba1c74b5805,0x00a80ef223af1012,0x0089c85ceb843a34)},
- {FIELD_LITERAL(0x00c4545be4a54004,0x0099e11f60357e6c,0x001f3936d19515a6,0x007793df84341a6e,0x0051061886717ffa,0x00e9b0a660b28f85,0x0044ea685892de0d,0x000257d2a1fda9d9)},
- {FIELD_LITERAL(0x007e8b01b24ac8a8,0x006cf3b0b5ca1337,0x00f1607d3e36a570,0x0039b7fab82991a1,0x00231777065840c5,0x00998e5afdd346f9,0x00b7dc3e64acc85f,0x00baacc748013ad6)},
+ {FIELD_LITERAL(0x00aad4ac569bf0f1ULL, 0x00a67adc90b27740ULL,
+ 0x0048551369a5751aULL, 0x0031252584a3306aULL,
+ 0x0084e15df770e6fcULL, 0x00d7bba1c74b5805ULL,
+ 0x00a80ef223af1012ULL, 0x0089c85ceb843a34ULL)},
+ {FIELD_LITERAL(0x00c4545be4a54004ULL, 0x0099e11f60357e6cULL,
+ 0x001f3936d19515a6ULL, 0x007793df84341a6eULL,
+ 0x0051061886717ffaULL, 0x00e9b0a660b28f85ULL,
+ 0x0044ea685892de0dULL, 0x000257d2a1fda9d9ULL)},
+ {FIELD_LITERAL(0x007e8b01b24ac8a8ULL, 0x006cf3b0b5ca1337ULL,
+ 0x00f1607d3e36a570ULL, 0x0039b7fab82991a1ULL,
+ 0x00231777065840c5ULL, 0x00998e5afdd346f9ULL,
+ 0x00b7dc3e64acc85fULL, 0x00baacc748013ad6ULL)},
}}, {{
- {FIELD_LITERAL(0x008ea6a4177580bf,0x005fa1953e3f0378,0x005fe409ac74d614,0x00452327f477e047,0x00a4018507fb6073,0x007b6e71951caac8,0x0012b42ab8a6ce91,0x0080eca677294ab7)},
- {FIELD_LITERAL(0x00a53edc023ba69b,0x00c6afa83ddde2e8,0x00c3f638b307b14e,0x004a357a64414062,0x00e4d94d8b582dc9,0x001739caf71695b7,0x0012431b2ae28de1,0x003b6bc98682907c)},
- {FIELD_LITERAL(0x008a9a93be1f99d6,0x0079fa627cc699c8,0x00b0cfb134ba84c8,0x001c4b778249419a,0x00df4ab3d9c44f40,0x009f596e6c1a9e3c,0x001979c0df237316,0x00501e953a919b87)},
+ {FIELD_LITERAL(0x008ea6a4177580bfULL, 0x005fa1953e3f0378ULL,
+ 0x005fe409ac74d614ULL, 0x00452327f477e047ULL,
+ 0x00a4018507fb6073ULL, 0x007b6e71951caac8ULL,
+ 0x0012b42ab8a6ce91ULL, 0x0080eca677294ab7ULL)},
+ {FIELD_LITERAL(0x00a53edc023ba69bULL, 0x00c6afa83ddde2e8ULL,
+ 0x00c3f638b307b14eULL, 0x004a357a64414062ULL,
+ 0x00e4d94d8b582dc9ULL, 0x001739caf71695b7ULL,
+ 0x0012431b2ae28de1ULL, 0x003b6bc98682907cULL)},
+ {FIELD_LITERAL(0x008a9a93be1f99d6ULL, 0x0079fa627cc699c8ULL,
+ 0x00b0cfb134ba84c8ULL, 0x001c4b778249419aULL,
+ 0x00df4ab3d9c44f40ULL, 0x009f596e6c1a9e3cULL,
+ 0x001979c0df237316ULL, 0x00501e953a919b87ULL)},
}}
};
const niels_t *curve448_wnaf_base = curve448_wnaf_base_table;
diff --git a/crypto/ec/curve448/curve448utils.h b/crypto/ec/curve448/curve448utils.h
index 9bf837993c94..9032bb4f730a 100644
--- a/crypto/ec/curve448/curve448utils.h
+++ b/crypto/ec/curve448/curve448utils.h
@@ -1,78 +1,80 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Mike Hamburg
*/
#ifndef HEADER_CURVE448UTILS_H
# define HEADER_CURVE448UTILS_H
# include <openssl/e_os2.h>
/*
* Internal word types. Somewhat tricky. This could be decided separately per
* platform. However, the structs do need to be all the same size and
* alignment on a given platform to support dynamic linking, since even if you
* header was built with eg arch_neon, you might end up linking a library built
* with arch_arm32.
*/
# ifndef C448_WORD_BITS
# if (defined(__SIZEOF_INT128__) && (__SIZEOF_INT128__ == 16)) \
- && !defined(__sparc__)
+ && !defined(__sparc__) \
+ && (!defined(__SIZEOF_LONG__) || (__SIZEOF_LONG__ == 8))
+
# define C448_WORD_BITS 64 /* The number of bits in a word */
# else
# define C448_WORD_BITS 32 /* The number of bits in a word */
# endif
# endif
# if C448_WORD_BITS == 64
/* Word size for internal computations */
typedef uint64_t c448_word_t;
/* Signed word size for internal computations */
typedef int64_t c448_sword_t;
/* "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */
typedef uint64_t c448_bool_t;
/* Double-word size for internal computations */
typedef __uint128_t c448_dword_t;
/* Signed double-word size for internal computations */
typedef __int128_t c448_dsword_t;
# elif C448_WORD_BITS == 32
/* Word size for internal computations */
typedef uint32_t c448_word_t;
/* Signed word size for internal computations */
typedef int32_t c448_sword_t;
/* "Boolean" type, will be set to all-zero or all-one (i.e. -1u) */
typedef uint32_t c448_bool_t;
/* Double-word size for internal computations */
typedef uint64_t c448_dword_t;
/* Signed double-word size for internal computations */
typedef int64_t c448_dsword_t;
# else
# error "Only supporting C448_WORD_BITS = 32 or 64 for now"
# endif
/* C448_TRUE = -1 so that C448_TRUE & x = x */
# define C448_TRUE (0 - (c448_bool_t)1)
/* C448_FALSE = 0 so that C448_FALSE & x = 0 */
# define C448_FALSE 0
/* Another boolean type used to indicate success or failure. */
typedef enum {
C448_SUCCESS = -1, /**< The operation succeeded. */
C448_FAILURE = 0 /**< The operation failed. */
} c448_error_t;
/* Return success if x is true */
static ossl_inline c448_error_t c448_succeed_if(c448_bool_t x)
{
return (c448_error_t) x;
}
#endif /* __C448_COMMON_H__ */
diff --git a/crypto/ec/curve448/f_generic.c b/crypto/ec/curve448/f_generic.c
index ed8f36d868f9..09d08165e250 100644
--- a/crypto/ec/curve448/f_generic.c
+++ b/crypto/ec/curve448/f_generic.c
@@ -1,204 +1,204 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Mike Hamburg
*/
#include "field.h"
static const gf MODULUS = {
- FIELD_LITERAL(0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff,
- 0xffffffffffffff, 0xfffffffffffffe, 0xffffffffffffff,
- 0xffffffffffffff, 0xffffffffffffff)
+ FIELD_LITERAL(0xffffffffffffffULL, 0xffffffffffffffULL, 0xffffffffffffffULL,
+ 0xffffffffffffffULL, 0xfffffffffffffeULL, 0xffffffffffffffULL,
+ 0xffffffffffffffULL, 0xffffffffffffffULL)
};
/* Serialize to wire format. */
void gf_serialize(uint8_t serial[SER_BYTES], const gf x, int with_hibit)
{
unsigned int j = 0, fill = 0;
dword_t buffer = 0;
int i;
gf red;
gf_copy(red, x);
gf_strong_reduce(red);
if (!with_hibit)
assert(gf_hibit(red) == 0);
for (i = 0; i < (with_hibit ? X_SER_BYTES : SER_BYTES); i++) {
if (fill < 8 && j < NLIMBS) {
buffer |= ((dword_t) red->limb[LIMBPERM(j)]) << fill;
fill += LIMB_PLACE_VALUE(LIMBPERM(j));
j++;
}
serial[i] = (uint8_t)buffer;
fill -= 8;
buffer >>= 8;
}
}
/* Return high bit of x = low bit of 2x mod p */
mask_t gf_hibit(const gf x)
{
gf y;
gf_add(y, x, x);
gf_strong_reduce(y);
return 0 - (y->limb[0] & 1);
}
/* Return high bit of x = low bit of 2x mod p */
mask_t gf_lobit(const gf x)
{
gf y;
gf_copy(y, x);
gf_strong_reduce(y);
return 0 - (y->limb[0] & 1);
}
/* Deserialize from wire format; return -1 on success and 0 on failure. */
mask_t gf_deserialize(gf x, const uint8_t serial[SER_BYTES], int with_hibit,
uint8_t hi_nmask)
{
unsigned int j = 0, fill = 0;
dword_t buffer = 0;
dsword_t scarry = 0;
const unsigned nbytes = with_hibit ? X_SER_BYTES : SER_BYTES;
unsigned int i;
mask_t succ;
for (i = 0; i < NLIMBS; i++) {
while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < nbytes) {
uint8_t sj;
sj = serial[j];
if (j == nbytes - 1)
sj &= ~hi_nmask;
buffer |= ((dword_t) sj) << fill;
fill += 8;
j++;
}
x->limb[LIMBPERM(i)] = (word_t)
((i < NLIMBS - 1) ? buffer & LIMB_MASK(LIMBPERM(i)) : buffer);
fill -= LIMB_PLACE_VALUE(LIMBPERM(i));
buffer >>= LIMB_PLACE_VALUE(LIMBPERM(i));
scarry =
(scarry + x->limb[LIMBPERM(i)] -
MODULUS->limb[LIMBPERM(i)]) >> (8 * sizeof(word_t));
}
succ = with_hibit ? 0 - (mask_t) 1 : ~gf_hibit(x);
return succ & word_is_zero((word_t)buffer) & ~word_is_zero((word_t)scarry);
}
/* Reduce to canonical form. */
void gf_strong_reduce(gf a)
{
dsword_t scarry;
word_t scarry_0;
dword_t carry = 0;
unsigned int i;
/* first, clear high */
gf_weak_reduce(a); /* Determined to have negligible perf impact. */
/* now the total is less than 2p */
/* compute total_value - p. No need to reduce mod p. */
scarry = 0;
for (i = 0; i < NLIMBS; i++) {
scarry = scarry + a->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)];
a->limb[LIMBPERM(i)] = scarry & LIMB_MASK(LIMBPERM(i));
scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
}
/*
* uncommon case: it was >= p, so now scarry = 0 and this = x common case:
* it was < p, so now scarry = -1 and this = x - p + 2^255 so let's add
* back in p. will carry back off the top for 2^255.
*/
assert(scarry == 0 || scarry == -1);
scarry_0 = (word_t)scarry;
/* add it back */
for (i = 0; i < NLIMBS; i++) {
carry =
carry + a->limb[LIMBPERM(i)] +
(scarry_0 & MODULUS->limb[LIMBPERM(i)]);
a->limb[LIMBPERM(i)] = carry & LIMB_MASK(LIMBPERM(i));
carry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
}
assert(carry < 2 && ((word_t)carry + scarry_0) == 0);
}
/* Subtract two gf elements d=a-b */
void gf_sub(gf d, const gf a, const gf b)
{
gf_sub_RAW(d, a, b);
gf_bias(d, 2);
gf_weak_reduce(d);
}
/* Add two field elements d = a+b */
void gf_add(gf d, const gf a, const gf b)
{
gf_add_RAW(d, a, b);
gf_weak_reduce(d);
}
/* Compare a==b */
mask_t gf_eq(const gf a, const gf b)
{
gf c;
mask_t ret = 0;
unsigned int i;
gf_sub(c, a, b);
gf_strong_reduce(c);
for (i = 0; i < NLIMBS; i++)
ret |= c->limb[LIMBPERM(i)];
return word_is_zero(ret);
}
mask_t gf_isr(gf a, const gf x)
{
gf L0, L1, L2;
gf_sqr(L1, x);
gf_mul(L2, x, L1);
gf_sqr(L1, L2);
gf_mul(L2, x, L1);
gf_sqrn(L1, L2, 3);
gf_mul(L0, L2, L1);
gf_sqrn(L1, L0, 3);
gf_mul(L0, L2, L1);
gf_sqrn(L2, L0, 9);
gf_mul(L1, L0, L2);
gf_sqr(L0, L1);
gf_mul(L2, x, L0);
gf_sqrn(L0, L2, 18);
gf_mul(L2, L1, L0);
gf_sqrn(L0, L2, 37);
gf_mul(L1, L2, L0);
gf_sqrn(L0, L1, 37);
gf_mul(L1, L2, L0);
gf_sqrn(L0, L1, 111);
gf_mul(L2, L1, L0);
gf_sqr(L0, L2);
gf_mul(L1, x, L0);
gf_sqrn(L0, L1, 223);
gf_mul(L1, L2, L0);
gf_sqr(L2, L1);
gf_mul(L0, L2, x);
gf_copy(a, L1);
return gf_eq(L0, ONE);
}
diff --git a/crypto/ec/curve448/scalar.c b/crypto/ec/curve448/scalar.c
index b5702c025570..347794bbac38 100644
--- a/crypto/ec/curve448/scalar.c
+++ b/crypto/ec/curve448/scalar.c
@@ -1,235 +1,235 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2015-2016 Cryptography Research, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Mike Hamburg
*/
#include <openssl/crypto.h>
#include "word.h"
#include "point_448.h"
-static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t) 0x3bd440fae918bc5;
+static const c448_word_t MONTGOMERY_FACTOR = (c448_word_t) 0x3bd440fae918bc5ULL;
static const curve448_scalar_t sc_p = {
{
{
- SC_LIMB(0x2378c292ab5844f3), SC_LIMB(0x216cc2728dc58f55),
- SC_LIMB(0xc44edb49aed63690), SC_LIMB(0xffffffff7cca23e9),
- SC_LIMB(0xffffffffffffffff), SC_LIMB(0xffffffffffffffff),
- SC_LIMB(0x3fffffffffffffff)
+ SC_LIMB(0x2378c292ab5844f3ULL), SC_LIMB(0x216cc2728dc58f55ULL),
+ SC_LIMB(0xc44edb49aed63690ULL), SC_LIMB(0xffffffff7cca23e9ULL),
+ SC_LIMB(0xffffffffffffffffULL), SC_LIMB(0xffffffffffffffffULL),
+ SC_LIMB(0x3fffffffffffffffULL)
}
}
}, sc_r2 = {
{
{
- SC_LIMB(0xe3539257049b9b60), SC_LIMB(0x7af32c4bc1b195d9),
- SC_LIMB(0x0d66de2388ea1859), SC_LIMB(0xae17cf725ee4d838),
- SC_LIMB(0x1a9cc14ba3c47c44), SC_LIMB(0x2052bcb7e4d070af),
- SC_LIMB(0x3402a939f823b729)
+ SC_LIMB(0xe3539257049b9b60ULL), SC_LIMB(0x7af32c4bc1b195d9ULL),
+ SC_LIMB(0x0d66de2388ea1859ULL), SC_LIMB(0xae17cf725ee4d838ULL),
+ SC_LIMB(0x1a9cc14ba3c47c44ULL), SC_LIMB(0x2052bcb7e4d070afULL),
+ SC_LIMB(0x3402a939f823b729ULL)
}
}
};
#define WBITS C448_WORD_BITS /* NB this may be different from ARCH_WORD_BITS */
const curve448_scalar_t curve448_scalar_one = {{{1}}};
const curve448_scalar_t curve448_scalar_zero = {{{0}}};
/*
* {extra,accum} - sub +? p
* Must have extra <= 1
*/
static void sc_subx(curve448_scalar_t out,
const c448_word_t accum[C448_SCALAR_LIMBS],
const curve448_scalar_t sub,
const curve448_scalar_t p, c448_word_t extra)
{
c448_dsword_t chain = 0;
unsigned int i;
c448_word_t borrow;
for (i = 0; i < C448_SCALAR_LIMBS; i++) {
chain = (chain + accum[i]) - sub->limb[i];
out->limb[i] = (c448_word_t)chain;
chain >>= WBITS;
}
borrow = (c448_word_t)chain + extra; /* = 0 or -1 */
chain = 0;
for (i = 0; i < C448_SCALAR_LIMBS; i++) {
chain = (chain + out->limb[i]) + (p->limb[i] & borrow);
out->limb[i] = (c448_word_t)chain;
chain >>= WBITS;
}
}
static void sc_montmul(curve448_scalar_t out, const curve448_scalar_t a,
const curve448_scalar_t b)
{
unsigned int i, j;
c448_word_t accum[C448_SCALAR_LIMBS + 1] = { 0 };
c448_word_t hi_carry = 0;
for (i = 0; i < C448_SCALAR_LIMBS; i++) {
c448_word_t mand = a->limb[i];
const c448_word_t *mier = b->limb;
c448_dword_t chain = 0;
for (j = 0; j < C448_SCALAR_LIMBS; j++) {
chain += ((c448_dword_t) mand) * mier[j] + accum[j];
accum[j] = (c448_word_t)chain;
chain >>= WBITS;
}
accum[j] = (c448_word_t)chain;
mand = accum[0] * MONTGOMERY_FACTOR;
chain = 0;
mier = sc_p->limb;
for (j = 0; j < C448_SCALAR_LIMBS; j++) {
chain += (c448_dword_t) mand *mier[j] + accum[j];
if (j)
accum[j - 1] = (c448_word_t)chain;
chain >>= WBITS;
}
chain += accum[j];
chain += hi_carry;
accum[j - 1] = (c448_word_t)chain;
hi_carry = chain >> WBITS;
}
sc_subx(out, accum, sc_p, sc_p, hi_carry);
}
void curve448_scalar_mul(curve448_scalar_t out, const curve448_scalar_t a,
const curve448_scalar_t b)
{
sc_montmul(out, a, b);
sc_montmul(out, out, sc_r2);
}
void curve448_scalar_sub(curve448_scalar_t out, const curve448_scalar_t a,
const curve448_scalar_t b)
{
sc_subx(out, a->limb, b, sc_p, 0);
}
void curve448_scalar_add(curve448_scalar_t out, const curve448_scalar_t a,
const curve448_scalar_t b)
{
c448_dword_t chain = 0;
unsigned int i;
for (i = 0; i < C448_SCALAR_LIMBS; i++) {
chain = (chain + a->limb[i]) + b->limb[i];
out->limb[i] = (c448_word_t)chain;
chain >>= WBITS;
}
sc_subx(out, out->limb, sc_p, sc_p, (c448_word_t)chain);
}
static ossl_inline void scalar_decode_short(curve448_scalar_t s,
const unsigned char *ser,
size_t nbytes)
{
size_t i, j, k = 0;
for (i = 0; i < C448_SCALAR_LIMBS; i++) {
c448_word_t out = 0;
for (j = 0; j < sizeof(c448_word_t) && k < nbytes; j++, k++)
out |= ((c448_word_t) ser[k]) << (8 * j);
s->limb[i] = out;
}
}
c448_error_t curve448_scalar_decode(
curve448_scalar_t s,
const unsigned char ser[C448_SCALAR_BYTES])
{
unsigned int i;
c448_dsword_t accum = 0;
scalar_decode_short(s, ser, C448_SCALAR_BYTES);
for (i = 0; i < C448_SCALAR_LIMBS; i++)
accum = (accum + s->limb[i] - sc_p->limb[i]) >> WBITS;
/* Here accum == 0 or -1 */
curve448_scalar_mul(s, s, curve448_scalar_one); /* ham-handed reduce */
return c448_succeed_if(~word_is_zero((uint32_t)accum));
}
void curve448_scalar_destroy(curve448_scalar_t scalar)
{
OPENSSL_cleanse(scalar, sizeof(curve448_scalar_t));
}
void curve448_scalar_decode_long(curve448_scalar_t s,
const unsigned char *ser, size_t ser_len)
{
size_t i;
curve448_scalar_t t1, t2;
if (ser_len == 0) {
curve448_scalar_copy(s, curve448_scalar_zero);
return;
}
i = ser_len - (ser_len % C448_SCALAR_BYTES);
if (i == ser_len)
i -= C448_SCALAR_BYTES;
scalar_decode_short(t1, &ser[i], ser_len - i);
if (ser_len == sizeof(curve448_scalar_t)) {
assert(i == 0);
/* ham-handed reduce */
curve448_scalar_mul(s, t1, curve448_scalar_one);
curve448_scalar_destroy(t1);
return;
}
while (i) {
i -= C448_SCALAR_BYTES;
sc_montmul(t1, t1, sc_r2);
(void)curve448_scalar_decode(t2, ser + i);
curve448_scalar_add(t1, t1, t2);
}
curve448_scalar_copy(s, t1);
curve448_scalar_destroy(t1);
curve448_scalar_destroy(t2);
}
void curve448_scalar_encode(unsigned char ser[C448_SCALAR_BYTES],
const curve448_scalar_t s)
{
unsigned int i, j, k = 0;
for (i = 0; i < C448_SCALAR_LIMBS; i++) {
for (j = 0; j < sizeof(c448_word_t); j++, k++)
ser[k] = s->limb[i] >> (8 * j);
}
}
void curve448_scalar_halve(curve448_scalar_t out, const curve448_scalar_t a)
{
c448_word_t mask = 0 - (a->limb[0] & 1);
c448_dword_t chain = 0;
unsigned int i;
for (i = 0; i < C448_SCALAR_LIMBS; i++) {
chain = (chain + a->limb[i]) + (sc_p->limb[i] & mask);
out->limb[i] = (c448_word_t)chain;
chain >>= C448_WORD_BITS;
}
for (i = 0; i < C448_SCALAR_LIMBS - 1; i++)
out->limb[i] = out->limb[i] >> 1 | out->limb[i + 1] << (WBITS - 1);
out->limb[i] = out->limb[i] >> 1 | (c448_word_t)(chain << (WBITS - 1));
}
diff --git a/crypto/ec/ec2_oct.c b/crypto/ec/ec2_oct.c
index 0867f994ea50..ee300518d69c 100644
--- a/crypto/ec/ec2_oct.c
+++ b/crypto/ec/ec2_oct.c
@@ -1,337 +1,338 @@
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/err.h>
#include "ec_lcl.h"
#ifndef OPENSSL_NO_EC2M
/*-
* Calculates and sets the affine coordinates of an EC_POINT from the given
* compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
* Note that the simple implementation only uses affine coordinates.
*
* The method is from the following publication:
*
* Harper, Menezes, Vanstone:
* "Public-Key Cryptosystems with Very Small Key Lengths",
* EUROCRYPT '92, Springer-Verlag LNCS 658,
* published February 1993
*
* US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
* the same method, but claim no priority date earlier than July 29, 1994
* (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
*/
int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
EC_POINT *point,
const BIGNUM *x_, int y_bit,
BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *tmp, *x, *y, *z;
int ret = 0, z0;
/* clear error queue */
ERR_clear_error();
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
y_bit = (y_bit != 0) ? 1 : 0;
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
z = BN_CTX_get(ctx);
if (z == NULL)
goto err;
if (!BN_GF2m_mod_arr(x, x_, group->poly))
goto err;
if (BN_is_zero(x)) {
if (!BN_GF2m_mod_sqrt_arr(y, group->b, group->poly, ctx))
goto err;
} else {
if (!group->meth->field_sqr(group, tmp, x, ctx))
goto err;
if (!group->meth->field_div(group, tmp, group->b, tmp, ctx))
goto err;
if (!BN_GF2m_add(tmp, group->a, tmp))
goto err;
if (!BN_GF2m_add(tmp, x, tmp))
goto err;
if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) {
unsigned long err = ERR_peek_last_error();
if (ERR_GET_LIB(err) == ERR_LIB_BN
&& ERR_GET_REASON(err) == BN_R_NO_SOLUTION) {
ERR_clear_error();
ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
EC_R_INVALID_COMPRESSED_POINT);
} else
ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
ERR_R_BN_LIB);
goto err;
}
z0 = (BN_is_odd(z)) ? 1 : 0;
if (!group->meth->field_mul(group, y, x, z, ctx))
goto err;
if (z0 != y_bit) {
if (!BN_GF2m_add(y, y, x))
goto err;
}
}
if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/*
* Converts an EC_POINT to an octet string. If buf is NULL, the encoded
* length will be returned. If the length len of buf is smaller than required
* an error will be returned.
*/
size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
point_conversion_form_t form,
unsigned char *buf, size_t len, BN_CTX *ctx)
{
size_t ret;
BN_CTX *new_ctx = NULL;
int used_ctx = 0;
BIGNUM *x, *y, *yxi;
size_t field_len, i, skip;
if ((form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID)) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
goto err;
}
if (EC_POINT_is_at_infinity(group, point)) {
/* encodes to a single 0 octet */
if (buf != NULL) {
if (len < 1) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
return 0;
}
buf[0] = 0;
}
return 1;
}
/* ret := required output buffer length */
field_len = (EC_GROUP_get_degree(group) + 7) / 8;
ret =
(form ==
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
/* if 'buf' is NULL, just return required length */
if (buf != NULL) {
if (len < ret) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
goto err;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
used_ctx = 1;
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
yxi = BN_CTX_get(ctx);
if (yxi == NULL)
goto err;
if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
goto err;
buf[0] = form;
if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) {
if (!group->meth->field_div(group, yxi, y, x, ctx))
goto err;
if (BN_is_odd(yxi))
buf[0]++;
}
i = 1;
skip = field_len - BN_num_bytes(x);
if (skip > field_len) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
goto err;
}
while (skip > 0) {
buf[i++] = 0;
skip--;
}
skip = BN_bn2bin(x, buf + i);
i += skip;
if (i != 1 + field_len) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
goto err;
}
if (form == POINT_CONVERSION_UNCOMPRESSED
|| form == POINT_CONVERSION_HYBRID) {
skip = field_len - BN_num_bytes(y);
if (skip > field_len) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
goto err;
}
while (skip > 0) {
buf[i++] = 0;
skip--;
}
skip = BN_bn2bin(y, buf + i);
i += skip;
}
if (i != ret) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (used_ctx)
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
err:
if (used_ctx)
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return 0;
}
/*
* Converts an octet string representation to an EC_POINT. Note that the
* simple implementation only uses affine coordinates.
*/
int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
const unsigned char *buf, size_t len,
BN_CTX *ctx)
{
point_conversion_form_t form;
- int y_bit;
+ int y_bit, m;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y, *yxi;
size_t field_len, enc_len;
int ret = 0;
if (len == 0) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
return 0;
}
form = buf[0];
y_bit = form & 1;
form = form & ~1U;
if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
&& (form != POINT_CONVERSION_UNCOMPRESSED)
&& (form != POINT_CONVERSION_HYBRID)) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
return 0;
}
if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
return 0;
}
if (form == 0) {
if (len != 1) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
return 0;
}
return EC_POINT_set_to_infinity(group, point);
}
- field_len = (EC_GROUP_get_degree(group) + 7) / 8;
+ m = EC_GROUP_get_degree(group);
+ field_len = (m + 7) / 8;
enc_len =
(form ==
POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
if (len != enc_len) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
return 0;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
yxi = BN_CTX_get(ctx);
if (yxi == NULL)
goto err;
if (!BN_bin2bn(buf + 1, field_len, x))
goto err;
- if (BN_ucmp(x, group->field) >= 0) {
+ if (BN_num_bits(x) > m) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
if (form == POINT_CONVERSION_COMPRESSED) {
if (!EC_POINT_set_compressed_coordinates(group, point, x, y_bit, ctx))
goto err;
} else {
if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
goto err;
- if (BN_ucmp(y, group->field) >= 0) {
+ if (BN_num_bits(y) > m) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
if (form == POINT_CONVERSION_HYBRID) {
if (!group->meth->field_div(group, yxi, y, x, ctx))
goto err;
if (y_bit != BN_is_odd(yxi)) {
ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
goto err;
}
}
/*
* EC_POINT_set_affine_coordinates is responsible for checking that
* the point is on the curve.
*/
if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
}
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
#endif
diff --git a/crypto/ec/ec2_smpl.c b/crypto/ec/ec2_smpl.c
index 0a05a7aeea61..898e741fcb97 100644
--- a/crypto/ec/ec2_smpl.c
+++ b/crypto/ec/ec2_smpl.c
@@ -1,970 +1,969 @@
/*
* Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/err.h>
#include "internal/bn_int.h"
#include "ec_lcl.h"
#ifndef OPENSSL_NO_EC2M
/*
* Initialize a GF(2^m)-based EC_GROUP structure. Note that all other members
* are handled by EC_GROUP_new.
*/
int ec_GF2m_simple_group_init(EC_GROUP *group)
{
group->field = BN_new();
group->a = BN_new();
group->b = BN_new();
if (group->field == NULL || group->a == NULL || group->b == NULL) {
BN_free(group->field);
BN_free(group->a);
BN_free(group->b);
return 0;
}
return 1;
}
/*
* Free a GF(2^m)-based EC_GROUP structure. Note that all other members are
* handled by EC_GROUP_free.
*/
void ec_GF2m_simple_group_finish(EC_GROUP *group)
{
BN_free(group->field);
BN_free(group->a);
BN_free(group->b);
}
/*
* Clear and free a GF(2^m)-based EC_GROUP structure. Note that all other
* members are handled by EC_GROUP_clear_free.
*/
void ec_GF2m_simple_group_clear_finish(EC_GROUP *group)
{
BN_clear_free(group->field);
BN_clear_free(group->a);
BN_clear_free(group->b);
group->poly[0] = 0;
group->poly[1] = 0;
group->poly[2] = 0;
group->poly[3] = 0;
group->poly[4] = 0;
group->poly[5] = -1;
}
/*
* Copy a GF(2^m)-based EC_GROUP structure. Note that all other members are
* handled by EC_GROUP_copy.
*/
int ec_GF2m_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
{
if (!BN_copy(dest->field, src->field))
return 0;
if (!BN_copy(dest->a, src->a))
return 0;
if (!BN_copy(dest->b, src->b))
return 0;
dest->poly[0] = src->poly[0];
dest->poly[1] = src->poly[1];
dest->poly[2] = src->poly[2];
dest->poly[3] = src->poly[3];
dest->poly[4] = src->poly[4];
dest->poly[5] = src->poly[5];
if (bn_wexpand(dest->a, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
NULL)
return 0;
if (bn_wexpand(dest->b, (int)(dest->poly[0] + BN_BITS2 - 1) / BN_BITS2) ==
NULL)
return 0;
bn_set_all_zero(dest->a);
bn_set_all_zero(dest->b);
return 1;
}
/* Set the curve parameters of an EC_GROUP structure. */
int ec_GF2m_simple_group_set_curve(EC_GROUP *group,
const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
int ret = 0, i;
/* group->field */
if (!BN_copy(group->field, p))
goto err;
i = BN_GF2m_poly2arr(group->field, group->poly, 6) - 1;
if ((i != 5) && (i != 3)) {
ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_SET_CURVE, EC_R_UNSUPPORTED_FIELD);
goto err;
}
/* group->a */
if (!BN_GF2m_mod_arr(group->a, a, group->poly))
goto err;
if (bn_wexpand(group->a, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
== NULL)
goto err;
bn_set_all_zero(group->a);
/* group->b */
if (!BN_GF2m_mod_arr(group->b, b, group->poly))
goto err;
if (bn_wexpand(group->b, (int)(group->poly[0] + BN_BITS2 - 1) / BN_BITS2)
== NULL)
goto err;
bn_set_all_zero(group->b);
ret = 1;
err:
return ret;
}
/*
* Get the curve parameters of an EC_GROUP structure. If p, a, or b are NULL
* then there values will not be set but the method will return with success.
*/
int ec_GF2m_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p,
BIGNUM *a, BIGNUM *b, BN_CTX *ctx)
{
int ret = 0;
if (p != NULL) {
if (!BN_copy(p, group->field))
return 0;
}
if (a != NULL) {
if (!BN_copy(a, group->a))
goto err;
}
if (b != NULL) {
if (!BN_copy(b, group->b))
goto err;
}
ret = 1;
err:
return ret;
}
/*
* Gets the degree of the field. For a curve over GF(2^m) this is the value
* m.
*/
int ec_GF2m_simple_group_get_degree(const EC_GROUP *group)
{
return BN_num_bits(group->field) - 1;
}
/*
* Checks the discriminant of the curve. y^2 + x*y = x^3 + a*x^2 + b is an
* elliptic curve <=> b != 0 (mod p)
*/
int ec_GF2m_simple_group_check_discriminant(const EC_GROUP *group,
BN_CTX *ctx)
{
int ret = 0;
BIGNUM *b;
BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
ECerr(EC_F_EC_GF2M_SIMPLE_GROUP_CHECK_DISCRIMINANT,
ERR_R_MALLOC_FAILURE);
goto err;
}
}
BN_CTX_start(ctx);
b = BN_CTX_get(ctx);
if (b == NULL)
goto err;
if (!BN_GF2m_mod_arr(b, group->b, group->poly))
goto err;
/*
* check the discriminant: y^2 + x*y = x^3 + a*x^2 + b is an elliptic
* curve <=> b != 0 (mod p)
*/
if (BN_is_zero(b))
goto err;
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/* Initializes an EC_POINT. */
int ec_GF2m_simple_point_init(EC_POINT *point)
{
point->X = BN_new();
point->Y = BN_new();
point->Z = BN_new();
if (point->X == NULL || point->Y == NULL || point->Z == NULL) {
BN_free(point->X);
BN_free(point->Y);
BN_free(point->Z);
return 0;
}
return 1;
}
/* Frees an EC_POINT. */
void ec_GF2m_simple_point_finish(EC_POINT *point)
{
BN_free(point->X);
BN_free(point->Y);
BN_free(point->Z);
}
/* Clears and frees an EC_POINT. */
void ec_GF2m_simple_point_clear_finish(EC_POINT *point)
{
BN_clear_free(point->X);
BN_clear_free(point->Y);
BN_clear_free(point->Z);
point->Z_is_one = 0;
}
/*
* Copy the contents of one EC_POINT into another. Assumes dest is
* initialized.
*/
int ec_GF2m_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
{
if (!BN_copy(dest->X, src->X))
return 0;
if (!BN_copy(dest->Y, src->Y))
return 0;
if (!BN_copy(dest->Z, src->Z))
return 0;
dest->Z_is_one = src->Z_is_one;
dest->curve_name = src->curve_name;
return 1;
}
/*
* Set an EC_POINT to the point at infinity. A point at infinity is
* represented by having Z=0.
*/
int ec_GF2m_simple_point_set_to_infinity(const EC_GROUP *group,
EC_POINT *point)
{
point->Z_is_one = 0;
BN_zero(point->Z);
return 1;
}
/*
* Set the coordinates of an EC_POINT using affine coordinates. Note that
* the simple implementation only uses affine coordinates.
*/
int ec_GF2m_simple_point_set_affine_coordinates(const EC_GROUP *group,
EC_POINT *point,
const BIGNUM *x,
const BIGNUM *y, BN_CTX *ctx)
{
int ret = 0;
if (x == NULL || y == NULL) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT_SET_AFFINE_COORDINATES,
ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (!BN_copy(point->X, x))
goto err;
BN_set_negative(point->X, 0);
if (!BN_copy(point->Y, y))
goto err;
BN_set_negative(point->Y, 0);
if (!BN_copy(point->Z, BN_value_one()))
goto err;
BN_set_negative(point->Z, 0);
point->Z_is_one = 1;
ret = 1;
err:
return ret;
}
/*
* Gets the affine coordinates of an EC_POINT. Note that the simple
* implementation only uses affine coordinates.
*/
int ec_GF2m_simple_point_get_affine_coordinates(const EC_GROUP *group,
const EC_POINT *point,
BIGNUM *x, BIGNUM *y,
BN_CTX *ctx)
{
int ret = 0;
if (EC_POINT_is_at_infinity(group, point)) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
EC_R_POINT_AT_INFINITY);
return 0;
}
if (BN_cmp(point->Z, BN_value_one())) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINT_GET_AFFINE_COORDINATES,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (x != NULL) {
if (!BN_copy(x, point->X))
goto err;
BN_set_negative(x, 0);
}
if (y != NULL) {
if (!BN_copy(y, point->Y))
goto err;
BN_set_negative(y, 0);
}
ret = 1;
err:
return ret;
}
/*
* Computes a + b and stores the result in r. r could be a or b, a could be
* b. Uses algorithm A.10.2 of IEEE P1363.
*/
int ec_GF2m_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *x0, *y0, *x1, *y1, *x2, *y2, *s, *t;
int ret = 0;
if (EC_POINT_is_at_infinity(group, a)) {
if (!EC_POINT_copy(r, b))
return 0;
return 1;
}
if (EC_POINT_is_at_infinity(group, b)) {
if (!EC_POINT_copy(r, a))
return 0;
return 1;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
x0 = BN_CTX_get(ctx);
y0 = BN_CTX_get(ctx);
x1 = BN_CTX_get(ctx);
y1 = BN_CTX_get(ctx);
x2 = BN_CTX_get(ctx);
y2 = BN_CTX_get(ctx);
s = BN_CTX_get(ctx);
t = BN_CTX_get(ctx);
if (t == NULL)
goto err;
if (a->Z_is_one) {
if (!BN_copy(x0, a->X))
goto err;
if (!BN_copy(y0, a->Y))
goto err;
} else {
if (!EC_POINT_get_affine_coordinates(group, a, x0, y0, ctx))
goto err;
}
if (b->Z_is_one) {
if (!BN_copy(x1, b->X))
goto err;
if (!BN_copy(y1, b->Y))
goto err;
} else {
if (!EC_POINT_get_affine_coordinates(group, b, x1, y1, ctx))
goto err;
}
if (BN_GF2m_cmp(x0, x1)) {
if (!BN_GF2m_add(t, x0, x1))
goto err;
if (!BN_GF2m_add(s, y0, y1))
goto err;
if (!group->meth->field_div(group, s, s, t, ctx))
goto err;
if (!group->meth->field_sqr(group, x2, s, ctx))
goto err;
if (!BN_GF2m_add(x2, x2, group->a))
goto err;
if (!BN_GF2m_add(x2, x2, s))
goto err;
if (!BN_GF2m_add(x2, x2, t))
goto err;
} else {
if (BN_GF2m_cmp(y0, y1) || BN_is_zero(x1)) {
if (!EC_POINT_set_to_infinity(group, r))
goto err;
ret = 1;
goto err;
}
if (!group->meth->field_div(group, s, y1, x1, ctx))
goto err;
if (!BN_GF2m_add(s, s, x1))
goto err;
if (!group->meth->field_sqr(group, x2, s, ctx))
goto err;
if (!BN_GF2m_add(x2, x2, s))
goto err;
if (!BN_GF2m_add(x2, x2, group->a))
goto err;
}
if (!BN_GF2m_add(y2, x1, x2))
goto err;
if (!group->meth->field_mul(group, y2, y2, s, ctx))
goto err;
if (!BN_GF2m_add(y2, y2, x2))
goto err;
if (!BN_GF2m_add(y2, y2, y1))
goto err;
if (!EC_POINT_set_affine_coordinates(group, r, x2, y2, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/*
* Computes 2 * a and stores the result in r. r could be a. Uses algorithm
* A.10.2 of IEEE P1363.
*/
int ec_GF2m_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
BN_CTX *ctx)
{
return ec_GF2m_simple_add(group, r, a, a, ctx);
}
int ec_GF2m_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
{
if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
/* point is its own inverse */
return 1;
if (!EC_POINT_make_affine(group, point, ctx))
return 0;
return BN_GF2m_add(point->Y, point->X, point->Y);
}
/* Indicates whether the given point is the point at infinity. */
int ec_GF2m_simple_is_at_infinity(const EC_GROUP *group,
const EC_POINT *point)
{
return BN_is_zero(point->Z);
}
/*-
* Determines whether the given EC_POINT is an actual point on the curve defined
* in the EC_GROUP. A point is valid if it satisfies the Weierstrass equation:
* y^2 + x*y = x^3 + a*x^2 + b.
*/
int ec_GF2m_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BN_CTX *ctx)
{
int ret = -1;
BN_CTX *new_ctx = NULL;
BIGNUM *lh, *y2;
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
if (EC_POINT_is_at_infinity(group, point))
return 1;
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
/* only support affine coordinates */
if (!point->Z_is_one)
return -1;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return -1;
}
BN_CTX_start(ctx);
y2 = BN_CTX_get(ctx);
lh = BN_CTX_get(ctx);
if (lh == NULL)
goto err;
/*-
* We have a curve defined by a Weierstrass equation
* y^2 + x*y = x^3 + a*x^2 + b.
* <=> x^3 + a*x^2 + x*y + b + y^2 = 0
* <=> ((x + a) * x + y ) * x + b + y^2 = 0
*/
if (!BN_GF2m_add(lh, point->X, group->a))
goto err;
if (!field_mul(group, lh, lh, point->X, ctx))
goto err;
if (!BN_GF2m_add(lh, lh, point->Y))
goto err;
if (!field_mul(group, lh, lh, point->X, ctx))
goto err;
if (!BN_GF2m_add(lh, lh, group->b))
goto err;
if (!field_sqr(group, y2, point->Y, ctx))
goto err;
if (!BN_GF2m_add(lh, lh, y2))
goto err;
ret = BN_is_zero(lh);
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/*-
* Indicates whether two points are equal.
* Return values:
* -1 error
* 0 equal (in affine coordinates)
* 1 not equal
*/
int ec_GF2m_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
BIGNUM *aX, *aY, *bX, *bY;
BN_CTX *new_ctx = NULL;
int ret = -1;
if (EC_POINT_is_at_infinity(group, a)) {
return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
}
if (EC_POINT_is_at_infinity(group, b))
return 1;
if (a->Z_is_one && b->Z_is_one) {
return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return -1;
}
BN_CTX_start(ctx);
aX = BN_CTX_get(ctx);
aY = BN_CTX_get(ctx);
bX = BN_CTX_get(ctx);
bY = BN_CTX_get(ctx);
if (bY == NULL)
goto err;
if (!EC_POINT_get_affine_coordinates(group, a, aX, aY, ctx))
goto err;
if (!EC_POINT_get_affine_coordinates(group, b, bX, bY, ctx))
goto err;
ret = ((BN_cmp(aX, bX) == 0) && BN_cmp(aY, bY) == 0) ? 0 : 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/* Forces the given EC_POINT to internally use affine coordinates. */
int ec_GF2m_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
int ret = 0;
if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
return 1;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
if (y == NULL)
goto err;
if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
goto err;
if (!BN_copy(point->X, x))
goto err;
if (!BN_copy(point->Y, y))
goto err;
if (!BN_one(point->Z))
goto err;
point->Z_is_one = 1;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/*
* Forces each of the EC_POINTs in the given array to use affine coordinates.
*/
int ec_GF2m_simple_points_make_affine(const EC_GROUP *group, size_t num,
EC_POINT *points[], BN_CTX *ctx)
{
size_t i;
for (i = 0; i < num; i++) {
if (!group->meth->make_affine(group, points[i], ctx))
return 0;
}
return 1;
}
/* Wrapper to simple binary polynomial field multiplication implementation. */
int ec_GF2m_simple_field_mul(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
return BN_GF2m_mod_mul_arr(r, a, b, group->poly, ctx);
}
/* Wrapper to simple binary polynomial field squaring implementation. */
int ec_GF2m_simple_field_sqr(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *a, BN_CTX *ctx)
{
return BN_GF2m_mod_sqr_arr(r, a, group->poly, ctx);
}
/* Wrapper to simple binary polynomial field division implementation. */
int ec_GF2m_simple_field_div(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
{
return BN_GF2m_mod_div(r, a, b, group->field, ctx);
}
/*-
* Lopez-Dahab ladder, pre step.
* See e.g. "Guide to ECC" Alg 3.40.
* Modified to blind s and r independently.
* s:= p, r := 2p
*/
static
int ec_GF2m_simple_ladder_pre(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
EC_POINT *p, BN_CTX *ctx)
{
/* if p is not affine, something is wrong */
if (p->Z_is_one == 0)
return 0;
/* s blinding: make sure lambda (s->Z here) is not zero */
do {
if (!BN_priv_rand(s->Z, BN_num_bits(group->field) - 1,
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
return 0;
}
} while (BN_is_zero(s->Z));
/* if field_encode defined convert between representations */
if ((group->meth->field_encode != NULL
&& !group->meth->field_encode(group, s->Z, s->Z, ctx))
|| !group->meth->field_mul(group, s->X, p->X, s->Z, ctx))
return 0;
/* r blinding: make sure lambda (r->Y here for storage) is not zero */
do {
if (!BN_priv_rand(r->Y, BN_num_bits(group->field) - 1,
BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_PRE, ERR_R_BN_LIB);
return 0;
}
} while (BN_is_zero(r->Y));
if ((group->meth->field_encode != NULL
&& !group->meth->field_encode(group, r->Y, r->Y, ctx))
|| !group->meth->field_sqr(group, r->Z, p->X, ctx)
|| !group->meth->field_sqr(group, r->X, r->Z, ctx)
|| !BN_GF2m_add(r->X, r->X, group->b)
|| !group->meth->field_mul(group, r->Z, r->Z, r->Y, ctx)
|| !group->meth->field_mul(group, r->X, r->X, r->Y, ctx))
return 0;
s->Z_is_one = 0;
r->Z_is_one = 0;
return 1;
}
/*-
* Ladder step: differential addition-and-doubling, mixed Lopez-Dahab coords.
* http://www.hyperelliptic.org/EFD/g12o/auto-code/shortw/xz/ladder/mladd-2003-s.op3
* s := r + s, r := 2r
*/
static
int ec_GF2m_simple_ladder_step(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
EC_POINT *p, BN_CTX *ctx)
{
if (!group->meth->field_mul(group, r->Y, r->Z, s->X, ctx)
|| !group->meth->field_mul(group, s->X, r->X, s->Z, ctx)
|| !group->meth->field_sqr(group, s->Y, r->Z, ctx)
|| !group->meth->field_sqr(group, r->Z, r->X, ctx)
|| !BN_GF2m_add(s->Z, r->Y, s->X)
|| !group->meth->field_sqr(group, s->Z, s->Z, ctx)
|| !group->meth->field_mul(group, s->X, r->Y, s->X, ctx)
|| !group->meth->field_mul(group, r->Y, s->Z, p->X, ctx)
|| !BN_GF2m_add(s->X, s->X, r->Y)
|| !group->meth->field_sqr(group, r->Y, r->Z, ctx)
|| !group->meth->field_mul(group, r->Z, r->Z, s->Y, ctx)
|| !group->meth->field_sqr(group, s->Y, s->Y, ctx)
|| !group->meth->field_mul(group, s->Y, s->Y, group->b, ctx)
|| !BN_GF2m_add(r->X, r->Y, s->Y))
return 0;
return 1;
}
/*-
* Recover affine (x,y) result from Lopez-Dahab r and s, affine p.
* See e.g. "Fast Multiplication on Elliptic Curves over GF(2**m)
* without Precomputation" (Lopez and Dahab, CHES 1999),
* Appendix Alg Mxy.
*/
static
int ec_GF2m_simple_ladder_post(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
EC_POINT *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *t0, *t1, *t2 = NULL;
if (BN_is_zero(r->Z))
return EC_POINT_set_to_infinity(group, r);
if (BN_is_zero(s->Z)) {
if (!EC_POINT_copy(r, p)
|| !EC_POINT_invert(group, r, ctx)) {
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_EC_LIB);
return 0;
}
return 1;
}
BN_CTX_start(ctx);
t0 = BN_CTX_get(ctx);
t1 = BN_CTX_get(ctx);
t2 = BN_CTX_get(ctx);
if (t2 == NULL) {
ECerr(EC_F_EC_GF2M_SIMPLE_LADDER_POST, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!group->meth->field_mul(group, t0, r->Z, s->Z, ctx)
|| !group->meth->field_mul(group, t1, p->X, r->Z, ctx)
|| !BN_GF2m_add(t1, r->X, t1)
|| !group->meth->field_mul(group, t2, p->X, s->Z, ctx)
|| !group->meth->field_mul(group, r->Z, r->X, t2, ctx)
|| !BN_GF2m_add(t2, t2, s->X)
|| !group->meth->field_mul(group, t1, t1, t2, ctx)
|| !group->meth->field_sqr(group, t2, p->X, ctx)
|| !BN_GF2m_add(t2, p->Y, t2)
|| !group->meth->field_mul(group, t2, t2, t0, ctx)
|| !BN_GF2m_add(t1, t2, t1)
|| !group->meth->field_mul(group, t2, p->X, t0, ctx)
|| !group->meth->field_inv(group, t2, t2, ctx)
|| !group->meth->field_mul(group, t1, t1, t2, ctx)
|| !group->meth->field_mul(group, r->X, r->Z, t2, ctx)
|| !BN_GF2m_add(t2, p->X, r->X)
|| !group->meth->field_mul(group, t2, t2, t1, ctx)
|| !BN_GF2m_add(r->Y, p->Y, t2)
|| !BN_one(r->Z))
goto err;
r->Z_is_one = 1;
/* GF(2^m) field elements should always have BIGNUM::neg = 0 */
BN_set_negative(r->X, 0);
BN_set_negative(r->Y, 0);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
static
int ec_GF2m_simple_points_mul(const EC_GROUP *group, EC_POINT *r,
const BIGNUM *scalar, size_t num,
const EC_POINT *points[],
const BIGNUM *scalars[],
BN_CTX *ctx)
{
int ret = 0;
EC_POINT *t = NULL;
/*-
* We limit use of the ladder only to the following cases:
* - r := scalar * G
* Fixed point mul: scalar != NULL && num == 0;
* - r := scalars[0] * points[0]
* Variable point mul: scalar == NULL && num == 1;
* - r := scalar * G + scalars[0] * points[0]
* used, e.g., in ECDSA verification: scalar != NULL && num == 1
*
* In any other case (num > 1) we use the default wNAF implementation.
*
* We also let the default implementation handle degenerate cases like group
* order or cofactor set to 0.
*/
if (num > 1 || BN_is_zero(group->order) || BN_is_zero(group->cofactor))
return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
if (scalar != NULL && num == 0)
/* Fixed point multiplication */
return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
if (scalar == NULL && num == 1)
/* Variable point multiplication */
return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
/*-
* Double point multiplication:
* r := scalar * G + scalars[0] * points[0]
*/
if ((t = EC_POINT_new(group)) == NULL) {
ECerr(EC_F_EC_GF2M_SIMPLE_POINTS_MUL, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!ec_scalar_mul_ladder(group, t, scalar, NULL, ctx)
|| !ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx)
|| !EC_POINT_add(group, r, t, r, ctx))
goto err;
ret = 1;
err:
EC_POINT_free(t);
return ret;
}
/*-
* Computes the multiplicative inverse of a in GF(2^m), storing the result in r.
* If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error.
* SCA hardening is with blinding: BN_GF2m_mod_inv does that.
*/
static int ec_GF2m_simple_field_inv(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *a, BN_CTX *ctx)
{
int ret;
if (!(ret = BN_GF2m_mod_inv(r, a, group->field, ctx)))
ECerr(EC_F_EC_GF2M_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT);
return ret;
}
const EC_METHOD *EC_GF2m_simple_method(void)
{
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_characteristic_two_field,
ec_GF2m_simple_group_init,
ec_GF2m_simple_group_finish,
ec_GF2m_simple_group_clear_finish,
ec_GF2m_simple_group_copy,
ec_GF2m_simple_group_set_curve,
ec_GF2m_simple_group_get_curve,
ec_GF2m_simple_group_get_degree,
ec_group_simple_order_bits,
ec_GF2m_simple_group_check_discriminant,
ec_GF2m_simple_point_init,
ec_GF2m_simple_point_finish,
ec_GF2m_simple_point_clear_finish,
ec_GF2m_simple_point_copy,
ec_GF2m_simple_point_set_to_infinity,
0, /* set_Jprojective_coordinates_GFp */
0, /* get_Jprojective_coordinates_GFp */
ec_GF2m_simple_point_set_affine_coordinates,
ec_GF2m_simple_point_get_affine_coordinates,
0, /* point_set_compressed_coordinates */
0, /* point2oct */
0, /* oct2point */
ec_GF2m_simple_add,
ec_GF2m_simple_dbl,
ec_GF2m_simple_invert,
ec_GF2m_simple_is_at_infinity,
ec_GF2m_simple_is_on_curve,
ec_GF2m_simple_cmp,
ec_GF2m_simple_make_affine,
ec_GF2m_simple_points_make_affine,
ec_GF2m_simple_points_mul,
0, /* precompute_mult */
0, /* have_precompute_mult */
ec_GF2m_simple_field_mul,
ec_GF2m_simple_field_sqr,
ec_GF2m_simple_field_div,
ec_GF2m_simple_field_inv,
0, /* field_encode */
0, /* field_decode */
0, /* field_set_to_one */
ec_key_simple_priv2oct,
ec_key_simple_oct2priv,
0, /* set private */
ec_key_simple_generate_key,
ec_key_simple_check_key,
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
0, /* field_inverse_mod_ord */
0, /* blind_coordinates */
ec_GF2m_simple_ladder_pre,
ec_GF2m_simple_ladder_step,
ec_GF2m_simple_ladder_post
};
return &ret;
}
#endif
diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c
index 8b363e096bed..c086f47ab3cc 100644
--- a/crypto/ec/ec_ameth.c
+++ b/crypto/ec/ec_ameth.c
@@ -1,942 +1,947 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/x509.h>
#include <openssl/ec.h>
#include <openssl/bn.h>
#include <openssl/cms.h>
#include <openssl/asn1t.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#include "ec_lcl.h"
#ifndef OPENSSL_NO_CMS
static int ecdh_cms_decrypt(CMS_RecipientInfo *ri);
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri);
#endif
static int eckey_param2type(int *pptype, void **ppval, EC_KEY *ec_key)
{
const EC_GROUP *group;
int nid;
if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
ECerr(EC_F_ECKEY_PARAM2TYPE, EC_R_MISSING_PARAMETERS);
return 0;
}
if (EC_GROUP_get_asn1_flag(group)
&& (nid = EC_GROUP_get_curve_name(group)))
/* we have a 'named curve' => just set the OID */
{
*ppval = OBJ_nid2obj(nid);
*pptype = V_ASN1_OBJECT;
} else { /* explicit parameters */
ASN1_STRING *pstr = NULL;
pstr = ASN1_STRING_new();
if (pstr == NULL)
return 0;
pstr->length = i2d_ECParameters(ec_key, &pstr->data);
if (pstr->length <= 0) {
ASN1_STRING_free(pstr);
ECerr(EC_F_ECKEY_PARAM2TYPE, ERR_R_EC_LIB);
return 0;
}
*ppval = pstr;
*pptype = V_ASN1_SEQUENCE;
}
return 1;
}
static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
{
EC_KEY *ec_key = pkey->pkey.ec;
void *pval = NULL;
int ptype;
unsigned char *penc = NULL, *p;
int penclen;
if (!eckey_param2type(&ptype, &pval, ec_key)) {
ECerr(EC_F_ECKEY_PUB_ENCODE, ERR_R_EC_LIB);
return 0;
}
penclen = i2o_ECPublicKey(ec_key, NULL);
if (penclen <= 0)
goto err;
penc = OPENSSL_malloc(penclen);
if (penc == NULL)
goto err;
p = penc;
penclen = i2o_ECPublicKey(ec_key, &p);
if (penclen <= 0)
goto err;
if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
ptype, pval, penc, penclen))
return 1;
err:
if (ptype == V_ASN1_OBJECT)
ASN1_OBJECT_free(pval);
else
ASN1_STRING_free(pval);
OPENSSL_free(penc);
return 0;
}
static EC_KEY *eckey_type2param(int ptype, const void *pval)
{
EC_KEY *eckey = NULL;
EC_GROUP *group = NULL;
if (ptype == V_ASN1_SEQUENCE) {
const ASN1_STRING *pstr = pval;
const unsigned char *pm = pstr->data;
int pmlen = pstr->length;
if ((eckey = d2i_ECParameters(NULL, &pm, pmlen)) == NULL) {
ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
goto ecerr;
}
} else if (ptype == V_ASN1_OBJECT) {
const ASN1_OBJECT *poid = pval;
/*
* type == V_ASN1_OBJECT => the parameters are given by an asn1 OID
*/
if ((eckey = EC_KEY_new()) == NULL) {
ECerr(EC_F_ECKEY_TYPE2PARAM, ERR_R_MALLOC_FAILURE);
goto ecerr;
}
group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(poid));
if (group == NULL)
goto ecerr;
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
if (EC_KEY_set_group(eckey, group) == 0)
goto ecerr;
EC_GROUP_free(group);
} else {
ECerr(EC_F_ECKEY_TYPE2PARAM, EC_R_DECODE_ERROR);
goto ecerr;
}
return eckey;
ecerr:
EC_KEY_free(eckey);
EC_GROUP_free(group);
return NULL;
}
static int eckey_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
{
const unsigned char *p = NULL;
const void *pval;
int ptype, pklen;
EC_KEY *eckey = NULL;
X509_ALGOR *palg;
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
return 0;
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
eckey = eckey_type2param(ptype, pval);
if (!eckey) {
ECerr(EC_F_ECKEY_PUB_DECODE, ERR_R_EC_LIB);
return 0;
}
/* We have parameters now set public key */
if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
ECerr(EC_F_ECKEY_PUB_DECODE, EC_R_DECODE_ERROR);
goto ecerr;
}
EVP_PKEY_assign_EC_KEY(pkey, eckey);
return 1;
ecerr:
EC_KEY_free(eckey);
return 0;
}
static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
int r;
const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
*pb = EC_KEY_get0_public_key(b->pkey.ec);
if (group == NULL || pa == NULL || pb == NULL)
return -2;
r = EC_POINT_cmp(group, pa, pb, NULL);
if (r == 0)
return 1;
if (r == 1)
return 0;
return -2;
}
static int eckey_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
{
const unsigned char *p = NULL;
const void *pval;
int ptype, pklen;
EC_KEY *eckey = NULL;
const X509_ALGOR *palg;
if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
return 0;
X509_ALGOR_get0(NULL, &ptype, &pval, palg);
eckey = eckey_type2param(ptype, pval);
if (!eckey)
goto ecliberr;
/* We have parameters now set private key */
if (!d2i_ECPrivateKey(&eckey, &p, pklen)) {
ECerr(EC_F_ECKEY_PRIV_DECODE, EC_R_DECODE_ERROR);
goto ecerr;
}
EVP_PKEY_assign_EC_KEY(pkey, eckey);
return 1;
ecliberr:
ECerr(EC_F_ECKEY_PRIV_DECODE, ERR_R_EC_LIB);
ecerr:
EC_KEY_free(eckey);
return 0;
}
static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
{
EC_KEY ec_key = *(pkey->pkey.ec);
unsigned char *ep, *p;
int eplen, ptype;
void *pval;
unsigned int old_flags;
if (!eckey_param2type(&ptype, &pval, &ec_key)) {
ECerr(EC_F_ECKEY_PRIV_ENCODE, EC_R_DECODE_ERROR);
return 0;
}
/* set the private key */
/*
* do not include the parameters in the SEC1 private key see PKCS#11
* 12.11
*/
old_flags = EC_KEY_get_enc_flags(&ec_key);
EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS);
eplen = i2d_ECPrivateKey(&ec_key, NULL);
if (!eplen) {
ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
return 0;
}
ep = OPENSSL_malloc(eplen);
if (ep == NULL) {
ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
return 0;
}
p = ep;
if (!i2d_ECPrivateKey(&ec_key, &p)) {
OPENSSL_free(ep);
ECerr(EC_F_ECKEY_PRIV_ENCODE, ERR_R_EC_LIB);
return 0;
}
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
ptype, pval, ep, eplen)) {
OPENSSL_free(ep);
return 0;
}
return 1;
}
static int int_ec_size(const EVP_PKEY *pkey)
{
return ECDSA_size(pkey->pkey.ec);
}
static int ec_bits(const EVP_PKEY *pkey)
{
return EC_GROUP_order_bits(EC_KEY_get0_group(pkey->pkey.ec));
}
static int ec_security_bits(const EVP_PKEY *pkey)
{
int ecbits = ec_bits(pkey);
if (ecbits >= 512)
return 256;
if (ecbits >= 384)
return 192;
if (ecbits >= 256)
return 128;
if (ecbits >= 224)
return 112;
if (ecbits >= 160)
return 80;
return ecbits / 2;
}
static int ec_missing_parameters(const EVP_PKEY *pkey)
{
if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL)
return 1;
return 0;
}
static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
{
EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
if (group == NULL)
return 0;
if (to->pkey.ec == NULL) {
to->pkey.ec = EC_KEY_new();
if (to->pkey.ec == NULL)
goto err;
}
if (EC_KEY_set_group(to->pkey.ec, group) == 0)
goto err;
EC_GROUP_free(group);
return 1;
err:
EC_GROUP_free(group);
return 0;
}
static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
*group_b = EC_KEY_get0_group(b->pkey.ec);
if (group_a == NULL || group_b == NULL)
return -2;
if (EC_GROUP_cmp(group_a, group_b, NULL))
return 0;
else
return 1;
}
static void int_ec_free(EVP_PKEY *pkey)
{
EC_KEY_free(pkey->pkey.ec);
}
typedef enum {
EC_KEY_PRINT_PRIVATE,
EC_KEY_PRINT_PUBLIC,
EC_KEY_PRINT_PARAM
} ec_print_t;
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
{
const char *ecstr;
unsigned char *priv = NULL, *pub = NULL;
size_t privlen = 0, publen = 0;
int ret = 0;
const EC_GROUP *group;
if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) {
publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL);
if (publen == 0)
goto err;
}
if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) {
privlen = EC_KEY_priv2buf(x, &priv);
if (privlen == 0)
goto err;
}
if (ktype == EC_KEY_PRINT_PRIVATE)
ecstr = "Private-Key";
else if (ktype == EC_KEY_PRINT_PUBLIC)
ecstr = "Public-Key";
else
ecstr = "ECDSA-Parameters";
if (!BIO_indent(bp, off, 128))
goto err;
if (BIO_printf(bp, "%s: (%d bit)\n", ecstr,
EC_GROUP_order_bits(group)) <= 0)
goto err;
if (privlen != 0) {
if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0)
goto err;
if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0)
goto err;
}
if (publen != 0) {
if (BIO_printf(bp, "%*spub:\n", off, "") <= 0)
goto err;
if (ASN1_buf_print(bp, pub, publen, off + 4) == 0)
goto err;
}
if (!ECPKParameters_print(bp, group, off))
goto err;
ret = 1;
err:
if (!ret)
ECerr(EC_F_DO_EC_KEY_PRINT, ERR_R_EC_LIB);
OPENSSL_clear_free(priv, privlen);
OPENSSL_free(pub);
return ret;
}
static int eckey_param_decode(EVP_PKEY *pkey,
const unsigned char **pder, int derlen)
{
EC_KEY *eckey;
if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL) {
ECerr(EC_F_ECKEY_PARAM_DECODE, ERR_R_EC_LIB);
return 0;
}
EVP_PKEY_assign_EC_KEY(pkey, eckey);
return 1;
}
static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
{
return i2d_ECParameters(pkey->pkey.ec, pder);
}
static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PARAM);
}
static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PUBLIC);
}
static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PRIVATE);
}
static int old_ec_priv_decode(EVP_PKEY *pkey,
const unsigned char **pder, int derlen)
{
EC_KEY *ec;
if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL) {
ECerr(EC_F_OLD_EC_PRIV_DECODE, EC_R_DECODE_ERROR);
return 0;
}
EVP_PKEY_assign_EC_KEY(pkey, ec);
return 1;
}
static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
{
return i2d_ECPrivateKey(pkey->pkey.ec, pder);
}
static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
switch (op) {
case ASN1_PKEY_CTRL_PKCS7_SIGN:
if (arg1 == 0) {
int snid, hnid;
X509_ALGOR *alg1, *alg2;
PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, &alg1, &alg2);
if (alg1 == NULL || alg1->algorithm == NULL)
return -1;
hnid = OBJ_obj2nid(alg1->algorithm);
if (hnid == NID_undef)
return -1;
if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
return -1;
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
}
return 1;
#ifndef OPENSSL_NO_CMS
case ASN1_PKEY_CTRL_CMS_SIGN:
if (arg1 == 0) {
int snid, hnid;
X509_ALGOR *alg1, *alg2;
CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
if (alg1 == NULL || alg1->algorithm == NULL)
return -1;
hnid = OBJ_obj2nid(alg1->algorithm);
if (hnid == NID_undef)
return -1;
if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
return -1;
X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
}
return 1;
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
if (arg1 == 1)
return ecdh_cms_decrypt(arg2);
else if (arg1 == 0)
return ecdh_cms_encrypt(arg2);
return -2;
case ASN1_PKEY_CTRL_CMS_RI_TYPE:
*(int *)arg2 = CMS_RECIPINFO_AGREE;
return 1;
#endif
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
- *(int *)arg2 = NID_sha256;
+ if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) {
+ /* For SM2, the only valid digest-alg is SM3 */
+ *(int *)arg2 = NID_sm3;
+ } else {
+ *(int *)arg2 = NID_sha256;
+ }
return 1;
case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
return EC_KEY_oct2key(EVP_PKEY_get0_EC_KEY(pkey), arg2, arg1, NULL);
case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
return EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(pkey),
POINT_CONVERSION_UNCOMPRESSED, arg2, NULL);
default:
return -2;
}
}
static int ec_pkey_check(const EVP_PKEY *pkey)
{
EC_KEY *eckey = pkey->pkey.ec;
/* stay consistent to what EVP_PKEY_check demands */
if (eckey->priv_key == NULL) {
ECerr(EC_F_EC_PKEY_CHECK, EC_R_MISSING_PRIVATE_KEY);
return 0;
}
return EC_KEY_check_key(eckey);
}
static int ec_pkey_public_check(const EVP_PKEY *pkey)
{
EC_KEY *eckey = pkey->pkey.ec;
/*
* Note: it unnecessary to check eckey->pub_key here since
* it will be checked in EC_KEY_check_key(). In fact, the
* EC_KEY_check_key() mainly checks the public key, and checks
* the private key optionally (only if there is one). So if
* someone passes a whole EC key (public + private), this
* will also work...
*/
return EC_KEY_check_key(eckey);
}
static int ec_pkey_param_check(const EVP_PKEY *pkey)
{
EC_KEY *eckey = pkey->pkey.ec;
/* stay consistent to what EVP_PKEY_check demands */
if (eckey->group == NULL) {
ECerr(EC_F_EC_PKEY_PARAM_CHECK, EC_R_MISSING_PARAMETERS);
return 0;
}
return EC_GROUP_check(eckey->group, NULL);
}
const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
EVP_PKEY_EC,
EVP_PKEY_EC,
0,
"EC",
"OpenSSL EC algorithm",
eckey_pub_decode,
eckey_pub_encode,
eckey_pub_cmp,
eckey_pub_print,
eckey_priv_decode,
eckey_priv_encode,
eckey_priv_print,
int_ec_size,
ec_bits,
ec_security_bits,
eckey_param_decode,
eckey_param_encode,
ec_missing_parameters,
ec_copy_parameters,
ec_cmp_parameters,
eckey_param_print,
0,
int_ec_free,
ec_pkey_ctrl,
old_ec_priv_decode,
old_ec_priv_encode,
0, 0, 0,
ec_pkey_check,
ec_pkey_public_check,
ec_pkey_param_check
};
#if !defined(OPENSSL_NO_SM2)
const EVP_PKEY_ASN1_METHOD sm2_asn1_meth = {
EVP_PKEY_SM2,
EVP_PKEY_EC,
ASN1_PKEY_ALIAS
};
#endif
int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
{
int private = EC_KEY_get0_private_key(x) != NULL;
return do_EC_KEY_print(bp, x, off,
private ? EC_KEY_PRINT_PRIVATE : EC_KEY_PRINT_PUBLIC);
}
int ECParameters_print(BIO *bp, const EC_KEY *x)
{
return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM);
}
#ifndef OPENSSL_NO_CMS
static int ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx,
X509_ALGOR *alg, ASN1_BIT_STRING *pubkey)
{
const ASN1_OBJECT *aoid;
int atype;
const void *aval;
int rv = 0;
EVP_PKEY *pkpeer = NULL;
EC_KEY *ecpeer = NULL;
const unsigned char *p;
int plen;
X509_ALGOR_get0(&aoid, &atype, &aval, alg);
if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
goto err;
/* If absent parameters get group from main key */
if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
const EC_GROUP *grp;
EVP_PKEY *pk;
pk = EVP_PKEY_CTX_get0_pkey(pctx);
if (!pk)
goto err;
grp = EC_KEY_get0_group(pk->pkey.ec);
ecpeer = EC_KEY_new();
if (ecpeer == NULL)
goto err;
if (!EC_KEY_set_group(ecpeer, grp))
goto err;
} else {
ecpeer = eckey_type2param(atype, aval);
if (!ecpeer)
goto err;
}
/* We have parameters now set public key */
plen = ASN1_STRING_length(pubkey);
p = ASN1_STRING_get0_data(pubkey);
if (!p || !plen)
goto err;
if (!o2i_ECPublicKey(&ecpeer, &p, plen))
goto err;
pkpeer = EVP_PKEY_new();
if (pkpeer == NULL)
goto err;
EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer);
if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
rv = 1;
err:
EC_KEY_free(ecpeer);
EVP_PKEY_free(pkpeer);
return rv;
}
/* Set KDF parameters based on KDF NID */
static int ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
{
int kdf_nid, kdfmd_nid, cofactor;
const EVP_MD *kdf_md;
if (eckdf_nid == NID_undef)
return 0;
/* Lookup KDF type, cofactor mode and digest */
if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
return 0;
if (kdf_nid == NID_dh_std_kdf)
cofactor = 0;
else if (kdf_nid == NID_dh_cofactor_kdf)
cofactor = 1;
else
return 0;
if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
return 0;
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
return 0;
kdf_md = EVP_get_digestbynid(kdfmd_nid);
if (!kdf_md)
return 0;
if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
return 0;
return 1;
}
static int ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
{
int rv = 0;
X509_ALGOR *alg, *kekalg = NULL;
ASN1_OCTET_STRING *ukm;
const unsigned char *p;
unsigned char *der = NULL;
int plen, keylen;
const EVP_CIPHER *kekcipher;
EVP_CIPHER_CTX *kekctx;
if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
return 0;
if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
ECerr(EC_F_ECDH_CMS_SET_SHARED_INFO, EC_R_KDF_PARAMETER_ERROR);
return 0;
}
if (alg->parameter->type != V_ASN1_SEQUENCE)
return 0;
p = alg->parameter->value.sequence->data;
plen = alg->parameter->value.sequence->length;
kekalg = d2i_X509_ALGOR(NULL, &p, plen);
if (!kekalg)
goto err;
kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
if (!kekctx)
goto err;
kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
goto err;
if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
goto err;
if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
goto err;
keylen = EVP_CIPHER_CTX_key_length(kekctx);
if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
goto err;
plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
if (!plen)
goto err;
if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
goto err;
der = NULL;
rv = 1;
err:
X509_ALGOR_free(kekalg);
OPENSSL_free(der);
return rv;
}
static int ecdh_cms_decrypt(CMS_RecipientInfo *ri)
{
EVP_PKEY_CTX *pctx;
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (!pctx)
return 0;
/* See if we need to set peer key */
if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
X509_ALGOR *alg;
ASN1_BIT_STRING *pubkey;
if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
NULL, NULL, NULL))
return 0;
if (!alg || !pubkey)
return 0;
if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_PEER_KEY_ERROR);
return 0;
}
}
/* Set ECDH derivation parameters and initialise unwrap context */
if (!ecdh_cms_set_shared_info(pctx, ri)) {
ECerr(EC_F_ECDH_CMS_DECRYPT, EC_R_SHARED_INFO_ERROR);
return 0;
}
return 1;
}
static int ecdh_cms_encrypt(CMS_RecipientInfo *ri)
{
EVP_PKEY_CTX *pctx;
EVP_PKEY *pkey;
EVP_CIPHER_CTX *ctx;
int keylen;
X509_ALGOR *talg, *wrap_alg = NULL;
const ASN1_OBJECT *aoid;
ASN1_BIT_STRING *pubkey;
ASN1_STRING *wrap_str;
ASN1_OCTET_STRING *ukm;
unsigned char *penc = NULL;
int penclen;
int rv = 0;
int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
const EVP_MD *kdf_md;
pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (!pctx)
return 0;
/* Get ephemeral key */
pkey = EVP_PKEY_CTX_get0_pkey(pctx);
if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
NULL, NULL, NULL))
goto err;
X509_ALGOR_get0(&aoid, NULL, NULL, talg);
/* Is everything uninitialised? */
if (aoid == OBJ_nid2obj(NID_undef)) {
EC_KEY *eckey = pkey->pkey.ec;
/* Set the key */
unsigned char *p;
penclen = i2o_ECPublicKey(eckey, NULL);
if (penclen <= 0)
goto err;
penc = OPENSSL_malloc(penclen);
if (penc == NULL)
goto err;
p = penc;
penclen = i2o_ECPublicKey(eckey, &p);
if (penclen <= 0)
goto err;
ASN1_STRING_set0(pubkey, penc, penclen);
pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
penc = NULL;
X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
V_ASN1_UNDEF, NULL);
}
/* See if custom parameters set */
kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
if (kdf_type <= 0)
goto err;
if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
goto err;
ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
if (ecdh_nid < 0)
goto err;
else if (ecdh_nid == 0)
ecdh_nid = NID_dh_std_kdf;
else if (ecdh_nid == 1)
ecdh_nid = NID_dh_cofactor_kdf;
if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
goto err;
} else
/* Unknown KDF */
goto err;
if (kdf_md == NULL) {
/* Fixme later for better MD */
kdf_md = EVP_sha1();
if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
goto err;
}
if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
goto err;
/* Lookup NID for KDF+cofactor+digest */
if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
goto err;
/* Get wrap NID */
ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
wrap_nid = EVP_CIPHER_CTX_type(ctx);
keylen = EVP_CIPHER_CTX_key_length(ctx);
/* Package wrap algorithm in an AlgorithmIdentifier */
wrap_alg = X509_ALGOR_new();
if (wrap_alg == NULL)
goto err;
wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
wrap_alg->parameter = ASN1_TYPE_new();
if (wrap_alg->parameter == NULL)
goto err;
if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
goto err;
if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
ASN1_TYPE_free(wrap_alg->parameter);
wrap_alg->parameter = NULL;
}
if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
goto err;
penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
if (!penclen)
goto err;
if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
goto err;
penc = NULL;
/*
* Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
* of another AlgorithmIdentifier.
*/
penclen = i2d_X509_ALGOR(wrap_alg, &penc);
if (!penc || !penclen)
goto err;
wrap_str = ASN1_STRING_new();
if (wrap_str == NULL)
goto err;
ASN1_STRING_set0(wrap_str, penc, penclen);
penc = NULL;
X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
rv = 1;
err:
OPENSSL_free(penc);
X509_ALGOR_free(wrap_alg);
return rv;
}
#endif
diff --git a/crypto/ec/ec_lib.c b/crypto/ec/ec_lib.c
index b89e3979d9dc..8cab5a5061cf 100644
--- a/crypto/ec/ec_lib.c
+++ b/crypto/ec/ec_lib.c
@@ -1,1121 +1,1120 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/err.h>
#include <openssl/opensslv.h>
#include "ec_lcl.h"
/* functions for EC_GROUP objects */
EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
{
EC_GROUP *ret;
if (meth == NULL) {
ECerr(EC_F_EC_GROUP_NEW, EC_R_SLOT_FULL);
return NULL;
}
if (meth->group_init == 0) {
ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->meth = meth;
if ((ret->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
ret->order = BN_new();
if (ret->order == NULL)
goto err;
ret->cofactor = BN_new();
if (ret->cofactor == NULL)
goto err;
}
ret->asn1_flag = OPENSSL_EC_NAMED_CURVE;
ret->asn1_form = POINT_CONVERSION_UNCOMPRESSED;
if (!meth->group_init(ret))
goto err;
return ret;
err:
BN_free(ret->order);
BN_free(ret->cofactor);
OPENSSL_free(ret);
return NULL;
}
void EC_pre_comp_free(EC_GROUP *group)
{
switch (group->pre_comp_type) {
case PCT_none:
break;
case PCT_nistz256:
#ifdef ECP_NISTZ256_ASM
EC_nistz256_pre_comp_free(group->pre_comp.nistz256);
#endif
break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
case PCT_nistp224:
EC_nistp224_pre_comp_free(group->pre_comp.nistp224);
break;
case PCT_nistp256:
EC_nistp256_pre_comp_free(group->pre_comp.nistp256);
break;
case PCT_nistp521:
EC_nistp521_pre_comp_free(group->pre_comp.nistp521);
break;
#else
case PCT_nistp224:
case PCT_nistp256:
case PCT_nistp521:
break;
#endif
case PCT_ec:
EC_ec_pre_comp_free(group->pre_comp.ec);
break;
}
group->pre_comp.ec = NULL;
}
void EC_GROUP_free(EC_GROUP *group)
{
if (!group)
return;
if (group->meth->group_finish != 0)
group->meth->group_finish(group);
EC_pre_comp_free(group);
BN_MONT_CTX_free(group->mont_data);
EC_POINT_free(group->generator);
BN_free(group->order);
BN_free(group->cofactor);
OPENSSL_free(group->seed);
OPENSSL_free(group);
}
void EC_GROUP_clear_free(EC_GROUP *group)
{
if (!group)
return;
if (group->meth->group_clear_finish != 0)
group->meth->group_clear_finish(group);
else if (group->meth->group_finish != 0)
group->meth->group_finish(group);
EC_pre_comp_free(group);
BN_MONT_CTX_free(group->mont_data);
EC_POINT_clear_free(group->generator);
BN_clear_free(group->order);
BN_clear_free(group->cofactor);
OPENSSL_clear_free(group->seed, group->seed_len);
OPENSSL_clear_free(group, sizeof(*group));
}
int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
{
if (dest->meth->group_copy == 0) {
ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (dest->meth != src->meth) {
ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (dest == src)
return 1;
dest->curve_name = src->curve_name;
/* Copy precomputed */
dest->pre_comp_type = src->pre_comp_type;
switch (src->pre_comp_type) {
case PCT_none:
dest->pre_comp.ec = NULL;
break;
case PCT_nistz256:
#ifdef ECP_NISTZ256_ASM
dest->pre_comp.nistz256 = EC_nistz256_pre_comp_dup(src->pre_comp.nistz256);
#endif
break;
#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
case PCT_nistp224:
dest->pre_comp.nistp224 = EC_nistp224_pre_comp_dup(src->pre_comp.nistp224);
break;
case PCT_nistp256:
dest->pre_comp.nistp256 = EC_nistp256_pre_comp_dup(src->pre_comp.nistp256);
break;
case PCT_nistp521:
dest->pre_comp.nistp521 = EC_nistp521_pre_comp_dup(src->pre_comp.nistp521);
break;
#else
case PCT_nistp224:
case PCT_nistp256:
case PCT_nistp521:
break;
#endif
case PCT_ec:
dest->pre_comp.ec = EC_ec_pre_comp_dup(src->pre_comp.ec);
break;
}
if (src->mont_data != NULL) {
if (dest->mont_data == NULL) {
dest->mont_data = BN_MONT_CTX_new();
if (dest->mont_data == NULL)
return 0;
}
if (!BN_MONT_CTX_copy(dest->mont_data, src->mont_data))
return 0;
} else {
/* src->generator == NULL */
BN_MONT_CTX_free(dest->mont_data);
dest->mont_data = NULL;
}
if (src->generator != NULL) {
if (dest->generator == NULL) {
dest->generator = EC_POINT_new(dest);
if (dest->generator == NULL)
return 0;
}
if (!EC_POINT_copy(dest->generator, src->generator))
return 0;
} else {
/* src->generator == NULL */
EC_POINT_clear_free(dest->generator);
dest->generator = NULL;
}
if ((src->meth->flags & EC_FLAGS_CUSTOM_CURVE) == 0) {
if (!BN_copy(dest->order, src->order))
return 0;
if (!BN_copy(dest->cofactor, src->cofactor))
return 0;
}
dest->asn1_flag = src->asn1_flag;
dest->asn1_form = src->asn1_form;
if (src->seed) {
OPENSSL_free(dest->seed);
if ((dest->seed = OPENSSL_malloc(src->seed_len)) == NULL) {
ECerr(EC_F_EC_GROUP_COPY, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!memcpy(dest->seed, src->seed, src->seed_len))
return 0;
dest->seed_len = src->seed_len;
} else {
OPENSSL_free(dest->seed);
dest->seed = NULL;
dest->seed_len = 0;
}
return dest->meth->group_copy(dest, src);
}
EC_GROUP *EC_GROUP_dup(const EC_GROUP *a)
{
EC_GROUP *t = NULL;
int ok = 0;
if (a == NULL)
return NULL;
if ((t = EC_GROUP_new(a->meth)) == NULL)
return NULL;
if (!EC_GROUP_copy(t, a))
goto err;
ok = 1;
err:
if (!ok) {
EC_GROUP_free(t);
return NULL;
}
return t;
}
const EC_METHOD *EC_GROUP_method_of(const EC_GROUP *group)
{
return group->meth;
}
int EC_METHOD_get_field_type(const EC_METHOD *meth)
{
return meth->field_type;
}
static int ec_precompute_mont_data(EC_GROUP *);
int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator,
const BIGNUM *order, const BIGNUM *cofactor)
{
if (generator == NULL) {
ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (group->generator == NULL) {
group->generator = EC_POINT_new(group);
if (group->generator == NULL)
return 0;
}
if (!EC_POINT_copy(group->generator, generator))
return 0;
if (order != NULL) {
if (!BN_copy(group->order, order))
return 0;
} else
BN_zero(group->order);
if (cofactor != NULL) {
if (!BN_copy(group->cofactor, cofactor))
return 0;
} else
BN_zero(group->cofactor);
/*
* Some groups have an order with
* factors of two, which makes the Montgomery setup fail.
* |group->mont_data| will be NULL in this case.
*/
if (BN_is_odd(group->order)) {
return ec_precompute_mont_data(group);
}
BN_MONT_CTX_free(group->mont_data);
group->mont_data = NULL;
return 1;
}
const EC_POINT *EC_GROUP_get0_generator(const EC_GROUP *group)
{
return group->generator;
}
BN_MONT_CTX *EC_GROUP_get_mont_data(const EC_GROUP *group)
{
return group->mont_data;
}
int EC_GROUP_get_order(const EC_GROUP *group, BIGNUM *order, BN_CTX *ctx)
{
if (group->order == NULL)
return 0;
if (!BN_copy(order, group->order))
return 0;
return !BN_is_zero(order);
}
const BIGNUM *EC_GROUP_get0_order(const EC_GROUP *group)
{
return group->order;
}
int EC_GROUP_order_bits(const EC_GROUP *group)
{
return group->meth->group_order_bits(group);
}
int EC_GROUP_get_cofactor(const EC_GROUP *group, BIGNUM *cofactor,
BN_CTX *ctx)
{
if (group->cofactor == NULL)
return 0;
if (!BN_copy(cofactor, group->cofactor))
return 0;
return !BN_is_zero(group->cofactor);
}
const BIGNUM *EC_GROUP_get0_cofactor(const EC_GROUP *group)
{
return group->cofactor;
}
void EC_GROUP_set_curve_name(EC_GROUP *group, int nid)
{
group->curve_name = nid;
}
int EC_GROUP_get_curve_name(const EC_GROUP *group)
{
return group->curve_name;
}
void EC_GROUP_set_asn1_flag(EC_GROUP *group, int flag)
{
group->asn1_flag = flag;
}
int EC_GROUP_get_asn1_flag(const EC_GROUP *group)
{
return group->asn1_flag;
}
void EC_GROUP_set_point_conversion_form(EC_GROUP *group,
point_conversion_form_t form)
{
group->asn1_form = form;
}
point_conversion_form_t EC_GROUP_get_point_conversion_form(const EC_GROUP
*group)
{
return group->asn1_form;
}
size_t EC_GROUP_set_seed(EC_GROUP *group, const unsigned char *p, size_t len)
{
OPENSSL_free(group->seed);
group->seed = NULL;
group->seed_len = 0;
if (!len || !p)
return 1;
if ((group->seed = OPENSSL_malloc(len)) == NULL) {
ECerr(EC_F_EC_GROUP_SET_SEED, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(group->seed, p, len);
group->seed_len = len;
return len;
}
unsigned char *EC_GROUP_get0_seed(const EC_GROUP *group)
{
return group->seed;
}
size_t EC_GROUP_get_seed_len(const EC_GROUP *group)
{
return group->seed_len;
}
int EC_GROUP_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
if (group->meth->group_set_curve == 0) {
ECerr(EC_F_EC_GROUP_SET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_set_curve(group, p, a, b, ctx);
}
int EC_GROUP_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a, BIGNUM *b,
BN_CTX *ctx)
{
if (group->meth->group_get_curve == NULL) {
ECerr(EC_F_EC_GROUP_GET_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_get_curve(group, p, a, b, ctx);
}
#if OPENSSL_API_COMPAT < 0x10200000L
int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
return EC_GROUP_set_curve(group, p, a, b, ctx);
}
int EC_GROUP_get_curve_GFp(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *ctx)
{
return EC_GROUP_get_curve(group, p, a, b, ctx);
}
# ifndef OPENSSL_NO_EC2M
int EC_GROUP_set_curve_GF2m(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
return EC_GROUP_set_curve(group, p, a, b, ctx);
}
int EC_GROUP_get_curve_GF2m(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *ctx)
{
return EC_GROUP_get_curve(group, p, a, b, ctx);
}
# endif
#endif
int EC_GROUP_get_degree(const EC_GROUP *group)
{
if (group->meth->group_get_degree == 0) {
ECerr(EC_F_EC_GROUP_GET_DEGREE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_get_degree(group);
}
int EC_GROUP_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
{
if (group->meth->group_check_discriminant == 0) {
ECerr(EC_F_EC_GROUP_CHECK_DISCRIMINANT,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
return group->meth->group_check_discriminant(group, ctx);
}
int EC_GROUP_cmp(const EC_GROUP *a, const EC_GROUP *b, BN_CTX *ctx)
{
int r = 0;
BIGNUM *a1, *a2, *a3, *b1, *b2, *b3;
BN_CTX *ctx_new = NULL;
/* compare the field types */
if (EC_METHOD_get_field_type(EC_GROUP_method_of(a)) !=
EC_METHOD_get_field_type(EC_GROUP_method_of(b)))
return 1;
/* compare the curve name (if present in both) */
if (EC_GROUP_get_curve_name(a) && EC_GROUP_get_curve_name(b) &&
EC_GROUP_get_curve_name(a) != EC_GROUP_get_curve_name(b))
return 1;
if (a->meth->flags & EC_FLAGS_CUSTOM_CURVE)
return 0;
if (ctx == NULL)
ctx_new = ctx = BN_CTX_new();
if (ctx == NULL)
return -1;
BN_CTX_start(ctx);
a1 = BN_CTX_get(ctx);
a2 = BN_CTX_get(ctx);
a3 = BN_CTX_get(ctx);
b1 = BN_CTX_get(ctx);
b2 = BN_CTX_get(ctx);
b3 = BN_CTX_get(ctx);
if (b3 == NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx_new);
return -1;
}
/*
* XXX This approach assumes that the external representation of curves
* over the same field type is the same.
*/
if (!a->meth->group_get_curve(a, a1, a2, a3, ctx) ||
!b->meth->group_get_curve(b, b1, b2, b3, ctx))
r = 1;
if (r || BN_cmp(a1, b1) || BN_cmp(a2, b2) || BN_cmp(a3, b3))
r = 1;
/* XXX EC_POINT_cmp() assumes that the methods are equal */
if (r || EC_POINT_cmp(a, EC_GROUP_get0_generator(a),
EC_GROUP_get0_generator(b), ctx))
r = 1;
if (!r) {
const BIGNUM *ao, *bo, *ac, *bc;
/* compare the order and cofactor */
ao = EC_GROUP_get0_order(a);
bo = EC_GROUP_get0_order(b);
ac = EC_GROUP_get0_cofactor(a);
bc = EC_GROUP_get0_cofactor(b);
if (ao == NULL || bo == NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx_new);
return -1;
}
if (BN_cmp(ao, bo) || BN_cmp(ac, bc))
r = 1;
}
BN_CTX_end(ctx);
BN_CTX_free(ctx_new);
return r;
}
/* functions for EC_POINT objects */
EC_POINT *EC_POINT_new(const EC_GROUP *group)
{
EC_POINT *ret;
if (group == NULL) {
ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
return NULL;
}
if (group->meth->point_init == NULL) {
ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->meth = group->meth;
ret->curve_name = group->curve_name;
if (!ret->meth->point_init(ret)) {
OPENSSL_free(ret);
return NULL;
}
return ret;
}
void EC_POINT_free(EC_POINT *point)
{
if (!point)
return;
if (point->meth->point_finish != 0)
point->meth->point_finish(point);
OPENSSL_free(point);
}
void EC_POINT_clear_free(EC_POINT *point)
{
if (!point)
return;
if (point->meth->point_clear_finish != 0)
point->meth->point_clear_finish(point);
else if (point->meth->point_finish != 0)
point->meth->point_finish(point);
OPENSSL_clear_free(point, sizeof(*point));
}
int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
{
if (dest->meth->point_copy == 0) {
ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (dest->meth != src->meth
|| (dest->curve_name != src->curve_name
&& dest->curve_name != 0
&& src->curve_name != 0)) {
ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (dest == src)
return 1;
return dest->meth->point_copy(dest, src);
}
EC_POINT *EC_POINT_dup(const EC_POINT *a, const EC_GROUP *group)
{
EC_POINT *t;
int r;
if (a == NULL)
return NULL;
t = EC_POINT_new(group);
if (t == NULL)
return NULL;
r = EC_POINT_copy(t, a);
if (!r) {
EC_POINT_free(t);
return NULL;
}
return t;
}
const EC_METHOD *EC_POINT_method_of(const EC_POINT *point)
{
return point->meth;
}
int EC_POINT_set_to_infinity(const EC_GROUP *group, EC_POINT *point)
{
if (group->meth->point_set_to_infinity == 0) {
ECerr(EC_F_EC_POINT_SET_TO_INFINITY,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (group->meth != point->meth) {
ECerr(EC_F_EC_POINT_SET_TO_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->point_set_to_infinity(group, point);
}
int EC_POINT_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, const BIGNUM *z,
BN_CTX *ctx)
{
if (group->meth->point_set_Jprojective_coordinates_GFp == 0) {
ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ECerr(EC_F_EC_POINT_SET_JPROJECTIVE_COORDINATES_GFP,
EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->point_set_Jprojective_coordinates_GFp(group, point, x,
y, z, ctx);
}
int EC_POINT_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x,
BIGNUM *y, BIGNUM *z,
BN_CTX *ctx)
{
if (group->meth->point_get_Jprojective_coordinates_GFp == 0) {
ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ECerr(EC_F_EC_POINT_GET_JPROJECTIVE_COORDINATES_GFP,
EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->point_get_Jprojective_coordinates_GFp(group, point, x,
y, z, ctx);
}
int EC_POINT_set_affine_coordinates(const EC_GROUP *group, EC_POINT *point,
const BIGNUM *x, const BIGNUM *y,
BN_CTX *ctx)
{
if (group->meth->point_set_affine_coordinates == NULL) {
ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (!group->meth->point_set_affine_coordinates(group, point, x, y, ctx))
return 0;
if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
ECerr(EC_F_EC_POINT_SET_AFFINE_COORDINATES, EC_R_POINT_IS_NOT_ON_CURVE);
return 0;
}
return 1;
}
#if OPENSSL_API_COMPAT < 0x10200000L
int EC_POINT_set_affine_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, BN_CTX *ctx)
{
return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
}
# ifndef OPENSSL_NO_EC2M
int EC_POINT_set_affine_coordinates_GF2m(const EC_GROUP *group,
EC_POINT *point, const BIGNUM *x,
const BIGNUM *y, BN_CTX *ctx)
{
return EC_POINT_set_affine_coordinates(group, point, x, y, ctx);
}
# endif
#endif
int EC_POINT_get_affine_coordinates(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x, BIGNUM *y,
BN_CTX *ctx)
{
if (group->meth->point_get_affine_coordinates == NULL) {
ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
if (EC_POINT_is_at_infinity(group, point)) {
ECerr(EC_F_EC_POINT_GET_AFFINE_COORDINATES, EC_R_POINT_AT_INFINITY);
return 0;
}
return group->meth->point_get_affine_coordinates(group, point, x, y, ctx);
}
#if OPENSSL_API_COMPAT < 0x10200000L
int EC_POINT_get_affine_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x,
BIGNUM *y, BN_CTX *ctx)
{
return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
}
# ifndef OPENSSL_NO_EC2M
int EC_POINT_get_affine_coordinates_GF2m(const EC_GROUP *group,
const EC_POINT *point, BIGNUM *x,
BIGNUM *y, BN_CTX *ctx)
{
return EC_POINT_get_affine_coordinates(group, point, x, y, ctx);
}
# endif
#endif
int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
if (group->meth->add == 0) {
ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)
|| !ec_point_is_compat(b, group)) {
ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->add(group, r, a, b, ctx);
}
int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
BN_CTX *ctx)
{
if (group->meth->dbl == 0) {
ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(r, group) || !ec_point_is_compat(a, group)) {
ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->dbl(group, r, a, ctx);
}
int EC_POINT_invert(const EC_GROUP *group, EC_POINT *a, BN_CTX *ctx)
{
if (group->meth->invert == 0) {
ECerr(EC_F_EC_POINT_INVERT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(a, group)) {
ECerr(EC_F_EC_POINT_INVERT, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->invert(group, a, ctx);
}
int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
{
if (group->meth->is_at_infinity == 0) {
ECerr(EC_F_EC_POINT_IS_AT_INFINITY,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->is_at_infinity(group, point);
}
/*
* Check whether an EC_POINT is on the curve or not. Note that the return
* value for this function should NOT be treated as a boolean. Return values:
* 1: The point is on the curve
* 0: The point is not on the curve
* -1: An error occurred
*/
int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BN_CTX *ctx)
{
if (group->meth->is_on_curve == 0) {
ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->is_on_curve(group, point, ctx);
}
int EC_POINT_cmp(const EC_GROUP *group, const EC_POINT *a, const EC_POINT *b,
BN_CTX *ctx)
{
if (group->meth->point_cmp == 0) {
ECerr(EC_F_EC_POINT_CMP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return -1;
}
if (!ec_point_is_compat(a, group) || !ec_point_is_compat(b, group)) {
ECerr(EC_F_EC_POINT_CMP, EC_R_INCOMPATIBLE_OBJECTS);
return -1;
}
return group->meth->point_cmp(group, a, b, ctx);
}
int EC_POINT_make_affine(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
{
if (group->meth->make_affine == 0) {
ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
if (!ec_point_is_compat(point, group)) {
ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
return group->meth->make_affine(group, point, ctx);
}
int EC_POINTs_make_affine(const EC_GROUP *group, size_t num,
EC_POINT *points[], BN_CTX *ctx)
{
size_t i;
if (group->meth->points_make_affine == 0) {
ECerr(EC_F_EC_POINTS_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
for (i = 0; i < num; i++) {
if (!ec_point_is_compat(points[i], group)) {
ECerr(EC_F_EC_POINTS_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
}
return group->meth->points_make_affine(group, num, points, ctx);
}
/*
* Functions for point multiplication. If group->meth->mul is 0, we use the
* wNAF-based implementations in ec_mult.c; otherwise we dispatch through
* methods.
*/
int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t num, const EC_POINT *points[],
const BIGNUM *scalars[], BN_CTX *ctx)
{
int ret = 0;
size_t i = 0;
BN_CTX *new_ctx = NULL;
if ((scalar == NULL) && (num == 0)) {
return EC_POINT_set_to_infinity(group, r);
}
if (!ec_point_is_compat(r, group)) {
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
for (i = 0; i < num; i++) {
if (!ec_point_is_compat(points[i], group)) {
ECerr(EC_F_EC_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
return 0;
}
}
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL) {
ECerr(EC_F_EC_POINTS_MUL, ERR_R_INTERNAL_ERROR);
return 0;
}
if (group->meth->mul != NULL)
ret = group->meth->mul(group, r, scalar, num, points, scalars, ctx);
else
/* use default */
ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
BN_CTX_free(new_ctx);
return ret;
}
int EC_POINT_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar,
const EC_POINT *point, const BIGNUM *p_scalar, BN_CTX *ctx)
{
/* just a convenient interface to EC_POINTs_mul() */
const EC_POINT *points[1];
const BIGNUM *scalars[1];
points[0] = point;
scalars[0] = p_scalar;
return EC_POINTs_mul(group, r, g_scalar,
(point != NULL
&& p_scalar != NULL), points, scalars, ctx);
}
int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
if (group->meth->mul == 0)
/* use default */
return ec_wNAF_precompute_mult(group, ctx);
if (group->meth->precompute_mult != 0)
return group->meth->precompute_mult(group, ctx);
else
return 1; /* nothing to do, so report success */
}
int EC_GROUP_have_precompute_mult(const EC_GROUP *group)
{
if (group->meth->mul == 0)
/* use default */
return ec_wNAF_have_precompute_mult(group);
if (group->meth->have_precompute_mult != 0)
return group->meth->have_precompute_mult(group);
else
return 0; /* cannot tell whether precomputation has
* been performed */
}
/*
* ec_precompute_mont_data sets |group->mont_data| from |group->order| and
* returns one on success. On error it returns zero.
*/
static int ec_precompute_mont_data(EC_GROUP *group)
{
BN_CTX *ctx = BN_CTX_new();
int ret = 0;
BN_MONT_CTX_free(group->mont_data);
group->mont_data = NULL;
if (ctx == NULL)
goto err;
group->mont_data = BN_MONT_CTX_new();
if (group->mont_data == NULL)
goto err;
if (!BN_MONT_CTX_set(group->mont_data, group->order, ctx)) {
BN_MONT_CTX_free(group->mont_data);
group->mont_data = NULL;
goto err;
}
ret = 1;
err:
BN_CTX_free(ctx);
return ret;
}
int EC_KEY_set_ex_data(EC_KEY *key, int idx, void *arg)
{
return CRYPTO_set_ex_data(&key->ex_data, idx, arg);
}
void *EC_KEY_get_ex_data(const EC_KEY *key, int idx)
{
return CRYPTO_get_ex_data(&key->ex_data, idx);
}
int ec_group_simple_order_bits(const EC_GROUP *group)
{
if (group->order == NULL)
return 0;
return BN_num_bits(group->order);
}
static int ec_field_inverse_mod_ord(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *x, BN_CTX *ctx)
{
BIGNUM *e = NULL;
BN_CTX *new_ctx = NULL;
int ret = 0;
if (group->mont_data == NULL)
return 0;
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
return 0;
BN_CTX_start(ctx);
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
/*-
* We want inverse in constant time, therefore we utilize the fact
* order must be prime and use Fermats Little Theorem instead.
*/
if (!BN_set_word(e, 2))
goto err;
if (!BN_sub(e, group->order, e))
goto err;
/*-
* Exponent e is public.
* No need for scatter-gather or BN_FLG_CONSTTIME.
*/
if (!BN_mod_exp_mont(r, x, e, group->order, ctx, group->mont_data))
goto err;
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/*-
* Default behavior, if group->meth->field_inverse_mod_ord is NULL:
* - When group->order is even, this function returns an error.
* - When group->order is otherwise composite, the correctness
* of the output is not guaranteed.
* - When x is outside the range [1, group->order), the correctness
* of the output is not guaranteed.
* - Otherwise, this function returns the multiplicative inverse in the
* range [1, group->order).
*
* EC_METHODs must implement their own field_inverse_mod_ord for
* other functionality.
*/
int ec_group_do_inverse_ord(const EC_GROUP *group, BIGNUM *res,
const BIGNUM *x, BN_CTX *ctx)
{
if (group->meth->field_inverse_mod_ord != NULL)
return group->meth->field_inverse_mod_ord(group, res, x, ctx);
else
return ec_field_inverse_mod_ord(group, res, x, ctx);
}
/*-
* Coordinate blinding for EC_POINT.
*
* The underlying EC_METHOD can optionally implement this function:
* underlying implementations should return 0 on errors, or 1 on
* success.
*
* This wrapper returns 1 in case the underlying EC_METHOD does not
* support coordinate blinding.
*/
int ec_point_blind_coordinates(const EC_GROUP *group, EC_POINT *p, BN_CTX *ctx)
{
if (group->meth->blind_coordinates == NULL)
return 1; /* ignore if not implemented */
return group->meth->blind_coordinates(group, p, ctx);
}
diff --git a/crypto/ec/ec_mult.c b/crypto/ec/ec_mult.c
index 0e0a5e1394af..57bdf116f1b6 100644
--- a/crypto/ec/ec_mult.c
+++ b/crypto/ec/ec_mult.c
@@ -1,970 +1,969 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/err.h>
#include "internal/cryptlib.h"
#include "internal/bn_int.h"
#include "ec_lcl.h"
#include "internal/refcount.h"
/*
* This file implements the wNAF-based interleaving multi-exponentiation method
* Formerly at:
* http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#multiexp
* You might now find it here:
* http://link.springer.com/chapter/10.1007%2F3-540-45537-X_13
* http://www.bmoeller.de/pdf/TI-01-08.multiexp.pdf
* For multiplication with precomputation, we use wNAF splitting, formerly at:
* http://www.informatik.tu-darmstadt.de/TI/Mitarbeiter/moeller.html#fastexp
*/
/* structure for precomputed multiples of the generator */
struct ec_pre_comp_st {
const EC_GROUP *group; /* parent EC_GROUP object */
size_t blocksize; /* block size for wNAF splitting */
size_t numblocks; /* max. number of blocks for which we have
* precomputation */
size_t w; /* window size */
EC_POINT **points; /* array with pre-calculated multiples of
* generator: 'num' pointers to EC_POINT
* objects followed by a NULL */
size_t num; /* numblocks * 2^(w-1) */
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
static EC_PRE_COMP *ec_pre_comp_new(const EC_GROUP *group)
{
EC_PRE_COMP *ret = NULL;
if (!group)
return NULL;
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
return ret;
}
ret->group = group;
ret->blocksize = 8; /* default */
ret->w = 4; /* default */
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
ECerr(EC_F_EC_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
return ret;
}
EC_PRE_COMP *EC_ec_pre_comp_dup(EC_PRE_COMP *pre)
{
int i;
if (pre != NULL)
CRYPTO_UP_REF(&pre->references, &i, pre->lock);
return pre;
}
void EC_ec_pre_comp_free(EC_PRE_COMP *pre)
{
int i;
if (pre == NULL)
return;
CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
REF_PRINT_COUNT("EC_ec", pre);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
if (pre->points != NULL) {
EC_POINT **pts;
for (pts = pre->points; *pts != NULL; pts++)
EC_POINT_free(*pts);
OPENSSL_free(pre->points);
}
CRYPTO_THREAD_lock_free(pre->lock);
OPENSSL_free(pre);
}
#define EC_POINT_BN_set_flags(P, flags) do { \
BN_set_flags((P)->X, (flags)); \
BN_set_flags((P)->Y, (flags)); \
BN_set_flags((P)->Z, (flags)); \
} while(0)
/*-
* This functions computes a single point multiplication over the EC group,
* using, at a high level, a Montgomery ladder with conditional swaps, with
* various timing attack defenses.
*
* It performs either a fixed point multiplication
* (scalar * generator)
* when point is NULL, or a variable point multiplication
* (scalar * point)
* when point is not NULL.
*
* `scalar` cannot be NULL and should be in the range [0,n) otherwise all
* constant time bets are off (where n is the cardinality of the EC group).
*
* This function expects `group->order` and `group->cardinality` to be well
* defined and non-zero: it fails with an error code otherwise.
*
* NB: This says nothing about the constant-timeness of the ladder step
* implementation (i.e., the default implementation is based on EC_POINT_add and
* EC_POINT_dbl, which of course are not constant time themselves) or the
* underlying multiprecision arithmetic.
*
* The product is stored in `r`.
*
* This is an internal function: callers are in charge of ensuring that the
* input parameters `group`, `r`, `scalar` and `ctx` are not NULL.
*
* Returns 1 on success, 0 otherwise.
*/
int ec_scalar_mul_ladder(const EC_GROUP *group, EC_POINT *r,
const BIGNUM *scalar, const EC_POINT *point,
BN_CTX *ctx)
{
int i, cardinality_bits, group_top, kbit, pbit, Z_is_one;
EC_POINT *p = NULL;
EC_POINT *s = NULL;
BIGNUM *k = NULL;
BIGNUM *lambda = NULL;
BIGNUM *cardinality = NULL;
int ret = 0;
/* early exit if the input point is the point at infinity */
if (point != NULL && EC_POINT_is_at_infinity(group, point))
return EC_POINT_set_to_infinity(group, r);
if (BN_is_zero(group->order)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_ORDER);
return 0;
}
if (BN_is_zero(group->cofactor)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_UNKNOWN_COFACTOR);
return 0;
}
BN_CTX_start(ctx);
if (((p = EC_POINT_new(group)) == NULL)
|| ((s = EC_POINT_new(group)) == NULL)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE);
goto err;
}
if (point == NULL) {
if (!EC_POINT_copy(p, group->generator)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
goto err;
}
} else {
if (!EC_POINT_copy(p, point)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_EC_LIB);
goto err;
}
}
EC_POINT_BN_set_flags(p, BN_FLG_CONSTTIME);
EC_POINT_BN_set_flags(r, BN_FLG_CONSTTIME);
EC_POINT_BN_set_flags(s, BN_FLG_CONSTTIME);
cardinality = BN_CTX_get(ctx);
lambda = BN_CTX_get(ctx);
k = BN_CTX_get(ctx);
if (k == NULL) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!BN_mul(cardinality, group->order, group->cofactor, ctx)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
goto err;
}
/*
* Group cardinalities are often on a word boundary.
* So when we pad the scalar, some timing diff might
* pop if it needs to be expanded due to carries.
* So expand ahead of time.
*/
cardinality_bits = BN_num_bits(cardinality);
group_top = bn_get_top(cardinality);
if ((bn_wexpand(k, group_top + 2) == NULL)
|| (bn_wexpand(lambda, group_top + 2) == NULL)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
goto err;
}
if (!BN_copy(k, scalar)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
goto err;
}
BN_set_flags(k, BN_FLG_CONSTTIME);
if ((BN_num_bits(k) > cardinality_bits) || (BN_is_negative(k))) {
/*-
* this is an unusual input, and we don't guarantee
* constant-timeness
*/
if (!BN_nnmod(k, k, cardinality, ctx)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
goto err;
}
}
if (!BN_add(lambda, k, cardinality)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
goto err;
}
BN_set_flags(lambda, BN_FLG_CONSTTIME);
if (!BN_add(k, lambda, cardinality)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
goto err;
}
/*
* lambda := scalar + cardinality
* k := scalar + 2*cardinality
*/
kbit = BN_is_bit_set(lambda, cardinality_bits);
BN_consttime_swap(kbit, k, lambda, group_top + 2);
group_top = bn_get_top(group->field);
if ((bn_wexpand(s->X, group_top) == NULL)
|| (bn_wexpand(s->Y, group_top) == NULL)
|| (bn_wexpand(s->Z, group_top) == NULL)
|| (bn_wexpand(r->X, group_top) == NULL)
|| (bn_wexpand(r->Y, group_top) == NULL)
|| (bn_wexpand(r->Z, group_top) == NULL)
|| (bn_wexpand(p->X, group_top) == NULL)
|| (bn_wexpand(p->Y, group_top) == NULL)
|| (bn_wexpand(p->Z, group_top) == NULL)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, ERR_R_BN_LIB);
goto err;
}
/*-
* Apply coordinate blinding for EC_POINT.
*
* The underlying EC_METHOD can optionally implement this function:
* ec_point_blind_coordinates() returns 0 in case of errors or 1 on
* success or if coordinate blinding is not implemented for this
* group.
*/
if (!ec_point_blind_coordinates(group, p, ctx)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_POINT_COORDINATES_BLIND_FAILURE);
goto err;
}
/* Initialize the Montgomery ladder */
if (!ec_point_ladder_pre(group, r, s, p, ctx)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_PRE_FAILURE);
goto err;
}
/* top bit is a 1, in a fixed pos */
pbit = 1;
#define EC_POINT_CSWAP(c, a, b, w, t) do { \
BN_consttime_swap(c, (a)->X, (b)->X, w); \
BN_consttime_swap(c, (a)->Y, (b)->Y, w); \
BN_consttime_swap(c, (a)->Z, (b)->Z, w); \
t = ((a)->Z_is_one ^ (b)->Z_is_one) & (c); \
(a)->Z_is_one ^= (t); \
(b)->Z_is_one ^= (t); \
} while(0)
/*-
* The ladder step, with branches, is
*
* k[i] == 0: S = add(R, S), R = dbl(R)
* k[i] == 1: R = add(S, R), S = dbl(S)
*
* Swapping R, S conditionally on k[i] leaves you with state
*
* k[i] == 0: T, U = R, S
* k[i] == 1: T, U = S, R
*
* Then perform the ECC ops.
*
* U = add(T, U)
* T = dbl(T)
*
* Which leaves you with state
*
* k[i] == 0: U = add(R, S), T = dbl(R)
* k[i] == 1: U = add(S, R), T = dbl(S)
*
* Swapping T, U conditionally on k[i] leaves you with state
*
* k[i] == 0: R, S = T, U
* k[i] == 1: R, S = U, T
*
* Which leaves you with state
*
* k[i] == 0: S = add(R, S), R = dbl(R)
* k[i] == 1: R = add(S, R), S = dbl(S)
*
* So we get the same logic, but instead of a branch it's a
* conditional swap, followed by ECC ops, then another conditional swap.
*
* Optimization: The end of iteration i and start of i-1 looks like
*
* ...
* CSWAP(k[i], R, S)
* ECC
* CSWAP(k[i], R, S)
* (next iteration)
* CSWAP(k[i-1], R, S)
* ECC
* CSWAP(k[i-1], R, S)
* ...
*
* So instead of two contiguous swaps, you can merge the condition
* bits and do a single swap.
*
* k[i] k[i-1] Outcome
* 0 0 No Swap
* 0 1 Swap
* 1 0 Swap
* 1 1 No Swap
*
* This is XOR. pbit tracks the previous bit of k.
*/
for (i = cardinality_bits - 1; i >= 0; i--) {
kbit = BN_is_bit_set(k, i) ^ pbit;
EC_POINT_CSWAP(kbit, r, s, group_top, Z_is_one);
/* Perform a single step of the Montgomery ladder */
if (!ec_point_ladder_step(group, r, s, p, ctx)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_STEP_FAILURE);
goto err;
}
/*
* pbit logic merges this cswap with that of the
* next iteration
*/
pbit ^= kbit;
}
/* one final cswap to move the right value into r */
EC_POINT_CSWAP(pbit, r, s, group_top, Z_is_one);
#undef EC_POINT_CSWAP
/* Finalize ladder (and recover full point coordinates) */
if (!ec_point_ladder_post(group, r, s, p, ctx)) {
ECerr(EC_F_EC_SCALAR_MUL_LADDER, EC_R_LADDER_POST_FAILURE);
goto err;
}
ret = 1;
err:
EC_POINT_free(p);
- EC_POINT_free(s);
+ EC_POINT_clear_free(s);
BN_CTX_end(ctx);
return ret;
}
#undef EC_POINT_BN_set_flags
/*
* TODO: table should be optimised for the wNAF-based implementation,
* sometimes smaller windows will give better performance (thus the
* boundaries should be increased)
*/
#define EC_window_bits_for_scalar_size(b) \
((size_t) \
((b) >= 2000 ? 6 : \
(b) >= 800 ? 5 : \
(b) >= 300 ? 4 : \
(b) >= 70 ? 3 : \
(b) >= 20 ? 2 : \
1))
/*-
* Compute
* \sum scalars[i]*points[i],
* also including
* scalar*generator
* in the addition if scalar != NULL
*/
int ec_wNAF_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
BN_CTX *ctx)
{
const EC_POINT *generator = NULL;
EC_POINT *tmp = NULL;
size_t totalnum;
size_t blocksize = 0, numblocks = 0; /* for wNAF splitting */
size_t pre_points_per_block = 0;
size_t i, j;
int k;
int r_is_inverted = 0;
int r_is_at_infinity = 1;
size_t *wsize = NULL; /* individual window sizes */
signed char **wNAF = NULL; /* individual wNAFs */
size_t *wNAF_len = NULL;
size_t max_len = 0;
size_t num_val;
EC_POINT **val = NULL; /* precomputation */
EC_POINT **v;
EC_POINT ***val_sub = NULL; /* pointers to sub-arrays of 'val' or
* 'pre_comp->points' */
const EC_PRE_COMP *pre_comp = NULL;
int num_scalar = 0; /* flag: will be set to 1 if 'scalar' must be
* treated like other scalars, i.e.
* precomputation is not available */
int ret = 0;
if (!BN_is_zero(group->order) && !BN_is_zero(group->cofactor)) {
/*-
* Handle the common cases where the scalar is secret, enforcing a
* scalar multiplication implementation based on a Montgomery ladder,
* with various timing attack defenses.
*/
- if ((scalar != NULL) && (num == 0)) {
+ if ((scalar != group->order) && (scalar != NULL) && (num == 0)) {
/*-
* In this case we want to compute scalar * GeneratorPoint: this
* codepath is reached most prominently by (ephemeral) key
* generation of EC cryptosystems (i.e. ECDSA keygen and sign setup,
* ECDH keygen/first half), where the scalar is always secret. This
* is why we ignore if BN_FLG_CONSTTIME is actually set and we
* always call the ladder version.
*/
return ec_scalar_mul_ladder(group, r, scalar, NULL, ctx);
}
- if ((scalar == NULL) && (num == 1)) {
+ if ((scalar == NULL) && (num == 1) && (scalars[0] != group->order)) {
/*-
* In this case we want to compute scalar * VariablePoint: this
* codepath is reached most prominently by the second half of ECDH,
* where the secret scalar is multiplied by the peer's public point.
* To protect the secret scalar, we ignore if BN_FLG_CONSTTIME is
* actually set and we always call the ladder version.
*/
return ec_scalar_mul_ladder(group, r, scalars[0], points[0], ctx);
}
}
if (scalar != NULL) {
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
ECerr(EC_F_EC_WNAF_MUL, EC_R_UNDEFINED_GENERATOR);
goto err;
}
/* look if we can use precomputed multiples of generator */
pre_comp = group->pre_comp.ec;
if (pre_comp && pre_comp->numblocks
&& (EC_POINT_cmp(group, generator, pre_comp->points[0], ctx) ==
0)) {
blocksize = pre_comp->blocksize;
/*
* determine maximum number of blocks that wNAF splitting may
* yield (NB: maximum wNAF length is bit length plus one)
*/
numblocks = (BN_num_bits(scalar) / blocksize) + 1;
/*
* we cannot use more blocks than we have precomputation for
*/
if (numblocks > pre_comp->numblocks)
numblocks = pre_comp->numblocks;
pre_points_per_block = (size_t)1 << (pre_comp->w - 1);
/* check that pre_comp looks sane */
if (pre_comp->num != (pre_comp->numblocks * pre_points_per_block)) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
goto err;
}
} else {
/* can't use precomputation */
pre_comp = NULL;
numblocks = 1;
num_scalar = 1; /* treat 'scalar' like 'num'-th element of
* 'scalars' */
}
}
totalnum = num + numblocks;
wsize = OPENSSL_malloc(totalnum * sizeof(wsize[0]));
wNAF_len = OPENSSL_malloc(totalnum * sizeof(wNAF_len[0]));
/* include space for pivot */
wNAF = OPENSSL_malloc((totalnum + 1) * sizeof(wNAF[0]));
val_sub = OPENSSL_malloc(totalnum * sizeof(val_sub[0]));
/* Ensure wNAF is initialised in case we end up going to err */
if (wNAF != NULL)
wNAF[0] = NULL; /* preliminary pivot */
if (wsize == NULL || wNAF_len == NULL || wNAF == NULL || val_sub == NULL) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* num_val will be the total number of temporarily precomputed points
*/
num_val = 0;
for (i = 0; i < num + num_scalar; i++) {
size_t bits;
bits = i < num ? BN_num_bits(scalars[i]) : BN_num_bits(scalar);
wsize[i] = EC_window_bits_for_scalar_size(bits);
num_val += (size_t)1 << (wsize[i] - 1);
wNAF[i + 1] = NULL; /* make sure we always have a pivot */
wNAF[i] =
bn_compute_wNAF((i < num ? scalars[i] : scalar), wsize[i],
&wNAF_len[i]);
if (wNAF[i] == NULL)
goto err;
if (wNAF_len[i] > max_len)
max_len = wNAF_len[i];
}
if (numblocks) {
/* we go here iff scalar != NULL */
if (pre_comp == NULL) {
if (num_scalar != 1) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
goto err;
}
/* we have already generated a wNAF for 'scalar' */
} else {
signed char *tmp_wNAF = NULL;
size_t tmp_len = 0;
if (num_scalar != 0) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* use the window size for which we have precomputation
*/
wsize[num] = pre_comp->w;
tmp_wNAF = bn_compute_wNAF(scalar, wsize[num], &tmp_len);
if (!tmp_wNAF)
goto err;
if (tmp_len <= max_len) {
/*
* One of the other wNAFs is at least as long as the wNAF
* belonging to the generator, so wNAF splitting will not buy
* us anything.
*/
numblocks = 1;
totalnum = num + 1; /* don't use wNAF splitting */
wNAF[num] = tmp_wNAF;
wNAF[num + 1] = NULL;
wNAF_len[num] = tmp_len;
/*
* pre_comp->points starts with the points that we need here:
*/
val_sub[num] = pre_comp->points;
} else {
/*
* don't include tmp_wNAF directly into wNAF array - use wNAF
* splitting and include the blocks
*/
signed char *pp;
EC_POINT **tmp_points;
if (tmp_len < numblocks * blocksize) {
/*
* possibly we can do with fewer blocks than estimated
*/
numblocks = (tmp_len + blocksize - 1) / blocksize;
if (numblocks > pre_comp->numblocks) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
OPENSSL_free(tmp_wNAF);
goto err;
}
totalnum = num + numblocks;
}
/* split wNAF in 'numblocks' parts */
pp = tmp_wNAF;
tmp_points = pre_comp->points;
for (i = num; i < totalnum; i++) {
if (i < totalnum - 1) {
wNAF_len[i] = blocksize;
if (tmp_len < blocksize) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
OPENSSL_free(tmp_wNAF);
goto err;
}
tmp_len -= blocksize;
} else
/*
* last block gets whatever is left (this could be
* more or less than 'blocksize'!)
*/
wNAF_len[i] = tmp_len;
wNAF[i + 1] = NULL;
wNAF[i] = OPENSSL_malloc(wNAF_len[i]);
if (wNAF[i] == NULL) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
OPENSSL_free(tmp_wNAF);
goto err;
}
memcpy(wNAF[i], pp, wNAF_len[i]);
if (wNAF_len[i] > max_len)
max_len = wNAF_len[i];
if (*tmp_points == NULL) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
OPENSSL_free(tmp_wNAF);
goto err;
}
val_sub[i] = tmp_points;
tmp_points += pre_points_per_block;
pp += blocksize;
}
OPENSSL_free(tmp_wNAF);
}
}
}
/*
* All points we precompute now go into a single array 'val'.
* 'val_sub[i]' is a pointer to the subarray for the i-th point, or to a
* subarray of 'pre_comp->points' if we already have precomputation.
*/
val = OPENSSL_malloc((num_val + 1) * sizeof(val[0]));
if (val == NULL) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_MALLOC_FAILURE);
goto err;
}
val[num_val] = NULL; /* pivot element */
/* allocate points for precomputation */
v = val;
for (i = 0; i < num + num_scalar; i++) {
val_sub[i] = v;
for (j = 0; j < ((size_t)1 << (wsize[i] - 1)); j++) {
*v = EC_POINT_new(group);
if (*v == NULL)
goto err;
v++;
}
}
if (!(v == val + num_val)) {
ECerr(EC_F_EC_WNAF_MUL, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((tmp = EC_POINT_new(group)) == NULL)
goto err;
/*-
* prepare precomputed values:
* val_sub[i][0] := points[i]
* val_sub[i][1] := 3 * points[i]
* val_sub[i][2] := 5 * points[i]
* ...
*/
for (i = 0; i < num + num_scalar; i++) {
if (i < num) {
if (!EC_POINT_copy(val_sub[i][0], points[i]))
goto err;
} else {
if (!EC_POINT_copy(val_sub[i][0], generator))
goto err;
}
if (wsize[i] > 1) {
if (!EC_POINT_dbl(group, tmp, val_sub[i][0], ctx))
goto err;
for (j = 1; j < ((size_t)1 << (wsize[i] - 1)); j++) {
if (!EC_POINT_add
(group, val_sub[i][j], val_sub[i][j - 1], tmp, ctx))
goto err;
}
}
}
if (!EC_POINTs_make_affine(group, num_val, val, ctx))
goto err;
r_is_at_infinity = 1;
for (k = max_len - 1; k >= 0; k--) {
if (!r_is_at_infinity) {
if (!EC_POINT_dbl(group, r, r, ctx))
goto err;
}
for (i = 0; i < totalnum; i++) {
if (wNAF_len[i] > (size_t)k) {
int digit = wNAF[i][k];
int is_neg;
if (digit) {
is_neg = digit < 0;
if (is_neg)
digit = -digit;
if (is_neg != r_is_inverted) {
if (!r_is_at_infinity) {
if (!EC_POINT_invert(group, r, ctx))
goto err;
}
r_is_inverted = !r_is_inverted;
}
/* digit > 0 */
if (r_is_at_infinity) {
if (!EC_POINT_copy(r, val_sub[i][digit >> 1]))
goto err;
r_is_at_infinity = 0;
} else {
if (!EC_POINT_add
(group, r, r, val_sub[i][digit >> 1], ctx))
goto err;
}
}
}
}
}
if (r_is_at_infinity) {
if (!EC_POINT_set_to_infinity(group, r))
goto err;
} else {
if (r_is_inverted)
if (!EC_POINT_invert(group, r, ctx))
goto err;
}
ret = 1;
err:
EC_POINT_free(tmp);
OPENSSL_free(wsize);
OPENSSL_free(wNAF_len);
if (wNAF != NULL) {
signed char **w;
for (w = wNAF; *w != NULL; w++)
OPENSSL_free(*w);
OPENSSL_free(wNAF);
}
if (val != NULL) {
for (v = val; *v != NULL; v++)
EC_POINT_clear_free(*v);
OPENSSL_free(val);
}
OPENSSL_free(val_sub);
return ret;
}
/*-
* ec_wNAF_precompute_mult()
* creates an EC_PRE_COMP object with preprecomputed multiples of the generator
* for use with wNAF splitting as implemented in ec_wNAF_mul().
*
* 'pre_comp->points' is an array of multiples of the generator
* of the following form:
* points[0] = generator;
* points[1] = 3 * generator;
* ...
* points[2^(w-1)-1] = (2^(w-1)-1) * generator;
* points[2^(w-1)] = 2^blocksize * generator;
* points[2^(w-1)+1] = 3 * 2^blocksize * generator;
* ...
* points[2^(w-1)*(numblocks-1)-1] = (2^(w-1)) * 2^(blocksize*(numblocks-2)) * generator
* points[2^(w-1)*(numblocks-1)] = 2^(blocksize*(numblocks-1)) * generator
* ...
* points[2^(w-1)*numblocks-1] = (2^(w-1)) * 2^(blocksize*(numblocks-1)) * generator
* points[2^(w-1)*numblocks] = NULL
*/
int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
const EC_POINT *generator;
EC_POINT *tmp_point = NULL, *base = NULL, **var;
BN_CTX *new_ctx = NULL;
const BIGNUM *order;
size_t i, bits, w, pre_points_per_block, blocksize, numblocks, num;
EC_POINT **points = NULL;
EC_PRE_COMP *pre_comp;
int ret = 0;
/* if there is an old EC_PRE_COMP object, throw it away */
EC_pre_comp_free(group);
if ((pre_comp = ec_pre_comp_new(group)) == NULL)
return 0;
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNDEFINED_GENERATOR);
goto err;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
}
BN_CTX_start(ctx);
order = EC_GROUP_get0_order(group);
if (order == NULL)
goto err;
if (BN_is_zero(order)) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, EC_R_UNKNOWN_ORDER);
goto err;
}
bits = BN_num_bits(order);
/*
* The following parameters mean we precompute (approximately) one point
* per bit. TBD: The combination 8, 4 is perfect for 160 bits; for other
* bit lengths, other parameter combinations might provide better
* efficiency.
*/
blocksize = 8;
w = 4;
if (EC_window_bits_for_scalar_size(bits) > w) {
/* let's not make the window too small ... */
w = EC_window_bits_for_scalar_size(bits);
}
numblocks = (bits + blocksize - 1) / blocksize; /* max. number of blocks
* to use for wNAF
* splitting */
pre_points_per_block = (size_t)1 << (w - 1);
num = pre_points_per_block * numblocks; /* number of points to compute
* and store */
points = OPENSSL_malloc(sizeof(*points) * (num + 1));
if (points == NULL) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
goto err;
}
var = points;
var[num] = NULL; /* pivot */
for (i = 0; i < num; i++) {
if ((var[i] = EC_POINT_new(group)) == NULL) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if ((tmp_point = EC_POINT_new(group)) == NULL
|| (base = EC_POINT_new(group)) == NULL) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_POINT_copy(base, generator))
goto err;
/* do the precomputation */
for (i = 0; i < numblocks; i++) {
size_t j;
if (!EC_POINT_dbl(group, tmp_point, base, ctx))
goto err;
if (!EC_POINT_copy(*var++, base))
goto err;
for (j = 1; j < pre_points_per_block; j++, var++) {
/*
* calculate odd multiples of the current base point
*/
if (!EC_POINT_add(group, *var, tmp_point, *(var - 1), ctx))
goto err;
}
if (i < numblocks - 1) {
/*
* get the next base (multiply current one by 2^blocksize)
*/
size_t k;
if (blocksize <= 2) {
ECerr(EC_F_EC_WNAF_PRECOMPUTE_MULT, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!EC_POINT_dbl(group, base, tmp_point, ctx))
goto err;
for (k = 2; k < blocksize; k++) {
if (!EC_POINT_dbl(group, base, base, ctx))
goto err;
}
}
}
if (!EC_POINTs_make_affine(group, num, points, ctx))
goto err;
pre_comp->group = group;
pre_comp->blocksize = blocksize;
pre_comp->numblocks = numblocks;
pre_comp->w = w;
pre_comp->points = points;
points = NULL;
pre_comp->num = num;
SETPRECOMP(group, ec, pre_comp);
pre_comp = NULL;
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
EC_ec_pre_comp_free(pre_comp);
if (points) {
EC_POINT **p;
for (p = points; *p != NULL; p++)
EC_POINT_free(*p);
OPENSSL_free(points);
}
EC_POINT_free(tmp_point);
EC_POINT_free(base);
return ret;
}
int ec_wNAF_have_precompute_mult(const EC_GROUP *group)
{
return HAVEPRECOMP(group, ec);
}
diff --git a/crypto/ec/ec_pmeth.c b/crypto/ec/ec_pmeth.c
index f4ad0749ef45..454be16c5439 100644
--- a/crypto/ec/ec_pmeth.c
+++ b/crypto/ec/ec_pmeth.c
@@ -1,472 +1,476 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/ec.h>
#include "ec_lcl.h"
#include <openssl/evp.h>
#include "internal/evp_int.h"
/* EC pkey context structure */
typedef struct {
/* Key and paramgen group */
EC_GROUP *gen_group;
/* message digest */
const EVP_MD *md;
/* Duplicate key if custom cofactor needed */
EC_KEY *co_key;
/* Cofactor mode */
signed char cofactor_mode;
/* KDF (if any) to use for ECDH */
char kdf_type;
/* Message digest to use for key derivation */
const EVP_MD *kdf_md;
/* User key material */
unsigned char *kdf_ukm;
size_t kdf_ukmlen;
/* KDF output length */
size_t kdf_outlen;
} EC_PKEY_CTX;
static int pkey_ec_init(EVP_PKEY_CTX *ctx)
{
EC_PKEY_CTX *dctx;
if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
ECerr(EC_F_PKEY_EC_INIT, ERR_R_MALLOC_FAILURE);
return 0;
}
dctx->cofactor_mode = -1;
dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
ctx->data = dctx;
return 1;
}
static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
EC_PKEY_CTX *dctx, *sctx;
if (!pkey_ec_init(dst))
return 0;
sctx = src->data;
dctx = dst->data;
if (sctx->gen_group) {
dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
if (!dctx->gen_group)
return 0;
}
dctx->md = sctx->md;
if (sctx->co_key) {
dctx->co_key = EC_KEY_dup(sctx->co_key);
if (!dctx->co_key)
return 0;
}
dctx->kdf_type = sctx->kdf_type;
dctx->kdf_md = sctx->kdf_md;
dctx->kdf_outlen = sctx->kdf_outlen;
if (sctx->kdf_ukm) {
dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
if (!dctx->kdf_ukm)
return 0;
} else
dctx->kdf_ukm = NULL;
dctx->kdf_ukmlen = sctx->kdf_ukmlen;
return 1;
}
static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
{
EC_PKEY_CTX *dctx = ctx->data;
if (dctx != NULL) {
EC_GROUP_free(dctx->gen_group);
EC_KEY_free(dctx->co_key);
OPENSSL_free(dctx->kdf_ukm);
OPENSSL_free(dctx);
ctx->data = NULL;
}
}
static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen)
{
int ret, type;
unsigned int sltmp;
EC_PKEY_CTX *dctx = ctx->data;
EC_KEY *ec = ctx->pkey->pkey.ec;
const int sig_sz = ECDSA_size(ec);
/* ensure cast to size_t is safe */
if (!ossl_assert(sig_sz > 0))
return 0;
if (sig == NULL) {
*siglen = (size_t)sig_sz;
return 1;
}
if (*siglen < (size_t)sig_sz) {
ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
return 0;
}
type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1;
ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
if (ret <= 0)
return ret;
*siglen = (size_t)sltmp;
return 1;
}
static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen)
{
int ret, type;
EC_PKEY_CTX *dctx = ctx->data;
EC_KEY *ec = ctx->pkey->pkey.ec;
if (dctx->md)
type = EVP_MD_type(dctx->md);
else
type = NID_sha1;
ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
return ret;
}
#ifndef OPENSSL_NO_EC
static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
{
int ret;
size_t outlen;
const EC_POINT *pubkey = NULL;
EC_KEY *eckey;
EC_PKEY_CTX *dctx = ctx->data;
if (!ctx->pkey || !ctx->peerkey) {
ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
return 0;
}
eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
if (!key) {
const EC_GROUP *group;
group = EC_KEY_get0_group(eckey);
*keylen = (EC_GROUP_get_degree(group) + 7) / 8;
return 1;
}
pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
/*
* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not
* an error, the result is truncated.
*/
outlen = *keylen;
ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
if (ret <= 0)
return 0;
*keylen = ret;
return 1;
}
static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
unsigned char *key, size_t *keylen)
{
EC_PKEY_CTX *dctx = ctx->data;
unsigned char *ktmp = NULL;
size_t ktmplen;
int rv = 0;
if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
return pkey_ec_derive(ctx, key, keylen);
if (!key) {
*keylen = dctx->kdf_outlen;
return 1;
}
if (*keylen != dctx->kdf_outlen)
return 0;
if (!pkey_ec_derive(ctx, NULL, &ktmplen))
return 0;
if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) {
ECerr(EC_F_PKEY_EC_KDF_DERIVE, ERR_R_MALLOC_FAILURE);
return 0;
}
if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
goto err;
/* Do KDF stuff */
if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen,
dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
goto err;
rv = 1;
err:
OPENSSL_clear_free(ktmp, ktmplen);
return rv;
}
#endif
static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
EC_PKEY_CTX *dctx = ctx->data;
EC_GROUP *group;
switch (type) {
case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
group = EC_GROUP_new_by_curve_name(p1);
if (group == NULL) {
ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
return 0;
}
EC_GROUP_free(dctx->gen_group);
dctx->gen_group = group;
return 1;
case EVP_PKEY_CTRL_EC_PARAM_ENC:
if (!dctx->gen_group) {
ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET);
return 0;
}
EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
return 1;
#ifndef OPENSSL_NO_EC
case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
if (p1 == -2) {
if (dctx->cofactor_mode != -1)
return dctx->cofactor_mode;
else {
EC_KEY *ec_key = ctx->pkey->pkey.ec;
return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
}
} else if (p1 < -1 || p1 > 1)
return -2;
dctx->cofactor_mode = p1;
if (p1 != -1) {
EC_KEY *ec_key = ctx->pkey->pkey.ec;
if (!ec_key->group)
return -2;
/* If cofactor is 1 cofactor mode does nothing */
if (BN_is_one(ec_key->group->cofactor))
return 1;
if (!dctx->co_key) {
dctx->co_key = EC_KEY_dup(ec_key);
if (!dctx->co_key)
return 0;
}
if (p1)
EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
else
EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
} else {
EC_KEY_free(dctx->co_key);
dctx->co_key = NULL;
}
return 1;
#endif
case EVP_PKEY_CTRL_EC_KDF_TYPE:
if (p1 == -2)
return dctx->kdf_type;
if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
return -2;
dctx->kdf_type = p1;
return 1;
case EVP_PKEY_CTRL_EC_KDF_MD:
dctx->kdf_md = p2;
return 1;
case EVP_PKEY_CTRL_GET_EC_KDF_MD:
*(const EVP_MD **)p2 = dctx->kdf_md;
return 1;
case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
if (p1 <= 0)
return -2;
dctx->kdf_outlen = (size_t)p1;
return 1;
case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
*(int *)p2 = dctx->kdf_outlen;
return 1;
case EVP_PKEY_CTRL_EC_KDF_UKM:
OPENSSL_free(dctx->kdf_ukm);
dctx->kdf_ukm = p2;
if (p2)
dctx->kdf_ukmlen = p1;
else
dctx->kdf_ukmlen = 0;
return 1;
case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
*(unsigned char **)p2 = dctx->kdf_ukm;
return dctx->kdf_ukmlen;
case EVP_PKEY_CTRL_MD:
if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
- EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
+ EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512) {
ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
return 0;
}
dctx->md = p2;
return 1;
case EVP_PKEY_CTRL_GET_MD:
*(const EVP_MD **)p2 = dctx->md;
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
/* Default behaviour is OK */
case EVP_PKEY_CTRL_DIGESTINIT:
case EVP_PKEY_CTRL_PKCS7_SIGN:
case EVP_PKEY_CTRL_CMS_SIGN:
return 1;
default:
return -2;
}
}
static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if (strcmp(type, "ec_paramgen_curve") == 0) {
int nid;
nid = EC_curve_nist2nid(value);
if (nid == NID_undef)
nid = OBJ_sn2nid(value);
if (nid == NID_undef)
nid = OBJ_ln2nid(value);
if (nid == NID_undef) {
ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
return 0;
}
return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
} else if (strcmp(type, "ec_param_enc") == 0) {
int param_enc;
if (strcmp(value, "explicit") == 0)
param_enc = 0;
else if (strcmp(value, "named_curve") == 0)
param_enc = OPENSSL_EC_NAMED_CURVE;
else
return -2;
return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
} else if (strcmp(type, "ecdh_kdf_md") == 0) {
const EVP_MD *md;
if ((md = EVP_get_digestbyname(value)) == NULL) {
ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST);
return 0;
}
return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
} else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
int co_mode;
co_mode = atoi(value);
return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
}
return -2;
}
static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
EC_KEY *ec = NULL;
EC_PKEY_CTX *dctx = ctx->data;
int ret;
if (dctx->gen_group == NULL) {
ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
return 0;
}
ec = EC_KEY_new();
if (ec == NULL)
return 0;
if (!(ret = EC_KEY_set_group(ec, dctx->gen_group))
|| !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
EC_KEY_free(ec);
return ret;
}
static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
EC_KEY *ec = NULL;
EC_PKEY_CTX *dctx = ctx->data;
int ret;
if (ctx->pkey == NULL && dctx->gen_group == NULL) {
ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
return 0;
}
ec = EC_KEY_new();
if (ec == NULL)
return 0;
if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
EC_KEY_free(ec);
return 0;
}
/* Note: if error is returned, we count on caller to free pkey->pkey.ec */
if (ctx->pkey != NULL)
ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey);
else
ret = EC_KEY_set_group(ec, dctx->gen_group);
return ret ? EC_KEY_generate_key(ec) : 0;
}
const EVP_PKEY_METHOD ec_pkey_meth = {
EVP_PKEY_EC,
0,
pkey_ec_init,
pkey_ec_copy,
pkey_ec_cleanup,
0,
pkey_ec_paramgen,
0,
pkey_ec_keygen,
0,
pkey_ec_sign,
0,
pkey_ec_verify,
0, 0,
0, 0, 0, 0,
0,
0,
0,
0,
0,
#ifndef OPENSSL_NO_EC
pkey_ec_kdf_derive,
#else
0,
#endif
pkey_ec_ctrl,
pkey_ec_ctrl_str
};
diff --git a/crypto/ec/ecdh_ossl.c b/crypto/ec/ecdh_ossl.c
index bd93793a180a..5608c62b2ac9 100644
--- a/crypto/ec/ecdh_ossl.c
+++ b/crypto/ec/ecdh_ossl.c
@@ -1,121 +1,120 @@
/*
- * Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <limits.h>
#include "internal/cryptlib.h"
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/objects.h>
#include <openssl/ec.h>
#include "ec_lcl.h"
int ossl_ecdh_compute_key(unsigned char **psec, size_t *pseclen,
const EC_POINT *pub_key, const EC_KEY *ecdh)
{
if (ecdh->group->meth->ecdh_compute_key == NULL) {
ECerr(EC_F_OSSL_ECDH_COMPUTE_KEY, EC_R_CURVE_DOES_NOT_SUPPORT_ECDH);
return 0;
}
return ecdh->group->meth->ecdh_compute_key(psec, pseclen, pub_key, ecdh);
}
/*-
* This implementation is based on the following primitives in the IEEE 1363 standard:
* - ECKAS-DH1
* - ECSVDP-DH
*/
int ecdh_simple_compute_key(unsigned char **pout, size_t *poutlen,
const EC_POINT *pub_key, const EC_KEY *ecdh)
{
BN_CTX *ctx;
EC_POINT *tmp = NULL;
BIGNUM *x = NULL;
const BIGNUM *priv_key;
const EC_GROUP *group;
int ret = 0;
size_t buflen, len;
unsigned char *buf = NULL;
if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
if (x == NULL) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
goto err;
}
priv_key = EC_KEY_get0_private_key(ecdh);
if (priv_key == NULL) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_NO_PRIVATE_VALUE);
goto err;
}
group = EC_KEY_get0_group(ecdh);
if (EC_KEY_get_flags(ecdh) & EC_FLAG_COFACTOR_ECDH) {
if (!EC_GROUP_get_cofactor(group, x, NULL) ||
!BN_mul(x, x, priv_key, ctx)) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
goto err;
}
priv_key = x;
}
if ((tmp = EC_POINT_new(group)) == NULL) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!EC_POINT_mul(group, tmp, NULL, pub_key, priv_key, ctx)) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
goto err;
}
if (!EC_POINT_get_affine_coordinates(group, tmp, x, NULL, ctx)) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, EC_R_POINT_ARITHMETIC_FAILURE);
goto err;
}
buflen = (EC_GROUP_get_degree(group) + 7) / 8;
len = BN_num_bytes(x);
if (len > buflen) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_INTERNAL_ERROR);
goto err;
}
if ((buf = OPENSSL_malloc(buflen)) == NULL) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_MALLOC_FAILURE);
goto err;
}
memset(buf, 0, buflen - len);
if (len != (size_t)BN_bn2bin(x, buf + buflen - len)) {
ECerr(EC_F_ECDH_SIMPLE_COMPUTE_KEY, ERR_R_BN_LIB);
goto err;
}
*pout = buf;
*poutlen = buflen;
buf = NULL;
ret = 1;
err:
- EC_POINT_free(tmp);
- if (ctx)
- BN_CTX_end(ctx);
+ EC_POINT_clear_free(tmp);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_free(buf);
return ret;
}
diff --git a/crypto/ec/ecp_nistp521.c b/crypto/ec/ecp_nistp521.c
index 2f47772a3477..e31b85c5f755 100644
--- a/crypto/ec/ecp_nistp521.c
+++ b/crypto/ec/ecp_nistp521.c
@@ -1,2159 +1,2164 @@
/*
* Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Copyright 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
*
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* A 64-bit implementation of the NIST P-521 elliptic curve point multiplication
*
* OpenSSL integration was taken from Emilia Kasper's work in ecp_nistp224.c.
* Otherwise based on Emilia's P224 work, which was inspired by my curve25519
* work which got its smarts from Daniel J. Bernstein's work on the same.
*/
#include <openssl/e_os2.h>
#ifdef OPENSSL_NO_EC_NISTP_64_GCC_128
NON_EMPTY_TRANSLATION_UNIT
#else
# include <string.h>
# include <openssl/err.h>
# include "ec_lcl.h"
# if defined(__SIZEOF_INT128__) && __SIZEOF_INT128__==16
/* even with gcc, the typedef won't work for 32-bit platforms */
typedef __uint128_t uint128_t; /* nonstandard; implemented by gcc on 64-bit
* platforms */
# else
# error "Your compiler doesn't appear to support 128-bit integer types"
# endif
typedef uint8_t u8;
typedef uint64_t u64;
/*
* The underlying field. P521 operates over GF(2^521-1). We can serialise an
* element of this field into 66 bytes where the most significant byte
* contains only a single bit. We call this an felem_bytearray.
*/
typedef u8 felem_bytearray[66];
/*
* These are the parameters of P521, taken from FIPS 186-3, section D.1.2.5.
* These values are big-endian.
*/
static const felem_bytearray nistp521_curve_params[5] = {
{0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* p */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff},
{0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* a = -3 */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xfc},
{0x00, 0x51, 0x95, 0x3e, 0xb9, 0x61, 0x8e, 0x1c, /* b */
0x9a, 0x1f, 0x92, 0x9a, 0x21, 0xa0, 0xb6, 0x85,
0x40, 0xee, 0xa2, 0xda, 0x72, 0x5b, 0x99, 0xb3,
0x15, 0xf3, 0xb8, 0xb4, 0x89, 0x91, 0x8e, 0xf1,
0x09, 0xe1, 0x56, 0x19, 0x39, 0x51, 0xec, 0x7e,
0x93, 0x7b, 0x16, 0x52, 0xc0, 0xbd, 0x3b, 0xb1,
0xbf, 0x07, 0x35, 0x73, 0xdf, 0x88, 0x3d, 0x2c,
0x34, 0xf1, 0xef, 0x45, 0x1f, 0xd4, 0x6b, 0x50,
0x3f, 0x00},
{0x00, 0xc6, 0x85, 0x8e, 0x06, 0xb7, 0x04, 0x04, /* x */
0xe9, 0xcd, 0x9e, 0x3e, 0xcb, 0x66, 0x23, 0x95,
0xb4, 0x42, 0x9c, 0x64, 0x81, 0x39, 0x05, 0x3f,
0xb5, 0x21, 0xf8, 0x28, 0xaf, 0x60, 0x6b, 0x4d,
0x3d, 0xba, 0xa1, 0x4b, 0x5e, 0x77, 0xef, 0xe7,
0x59, 0x28, 0xfe, 0x1d, 0xc1, 0x27, 0xa2, 0xff,
0xa8, 0xde, 0x33, 0x48, 0xb3, 0xc1, 0x85, 0x6a,
0x42, 0x9b, 0xf9, 0x7e, 0x7e, 0x31, 0xc2, 0xe5,
0xbd, 0x66},
{0x01, 0x18, 0x39, 0x29, 0x6a, 0x78, 0x9a, 0x3b, /* y */
0xc0, 0x04, 0x5c, 0x8a, 0x5f, 0xb4, 0x2c, 0x7d,
0x1b, 0xd9, 0x98, 0xf5, 0x44, 0x49, 0x57, 0x9b,
0x44, 0x68, 0x17, 0xaf, 0xbd, 0x17, 0x27, 0x3e,
0x66, 0x2c, 0x97, 0xee, 0x72, 0x99, 0x5e, 0xf4,
0x26, 0x40, 0xc5, 0x50, 0xb9, 0x01, 0x3f, 0xad,
0x07, 0x61, 0x35, 0x3c, 0x70, 0x86, 0xa2, 0x72,
0xc2, 0x40, 0x88, 0xbe, 0x94, 0x76, 0x9f, 0xd1,
0x66, 0x50}
};
/*-
* The representation of field elements.
* ------------------------------------
*
* We represent field elements with nine values. These values are either 64 or
* 128 bits and the field element represented is:
* v[0]*2^0 + v[1]*2^58 + v[2]*2^116 + ... + v[8]*2^464 (mod p)
* Each of the nine values is called a 'limb'. Since the limbs are spaced only
* 58 bits apart, but are greater than 58 bits in length, the most significant
* bits of each limb overlap with the least significant bits of the next.
*
* A field element with 64-bit limbs is an 'felem'. One with 128-bit limbs is a
* 'largefelem' */
# define NLIMBS 9
typedef uint64_t limb;
typedef limb felem[NLIMBS];
typedef uint128_t largefelem[NLIMBS];
static const limb bottom57bits = 0x1ffffffffffffff;
static const limb bottom58bits = 0x3ffffffffffffff;
/*
* bin66_to_felem takes a little-endian byte array and converts it into felem
* form. This assumes that the CPU is little-endian.
*/
static void bin66_to_felem(felem out, const u8 in[66])
{
out[0] = (*((limb *) & in[0])) & bottom58bits;
out[1] = (*((limb *) & in[7]) >> 2) & bottom58bits;
out[2] = (*((limb *) & in[14]) >> 4) & bottom58bits;
out[3] = (*((limb *) & in[21]) >> 6) & bottom58bits;
out[4] = (*((limb *) & in[29])) & bottom58bits;
out[5] = (*((limb *) & in[36]) >> 2) & bottom58bits;
out[6] = (*((limb *) & in[43]) >> 4) & bottom58bits;
out[7] = (*((limb *) & in[50]) >> 6) & bottom58bits;
out[8] = (*((limb *) & in[58])) & bottom57bits;
}
/*
* felem_to_bin66 takes an felem and serialises into a little endian, 66 byte
* array. This assumes that the CPU is little-endian.
*/
static void felem_to_bin66(u8 out[66], const felem in)
{
memset(out, 0, 66);
(*((limb *) & out[0])) = in[0];
(*((limb *) & out[7])) |= in[1] << 2;
(*((limb *) & out[14])) |= in[2] << 4;
(*((limb *) & out[21])) |= in[3] << 6;
(*((limb *) & out[29])) = in[4];
(*((limb *) & out[36])) |= in[5] << 2;
(*((limb *) & out[43])) |= in[6] << 4;
(*((limb *) & out[50])) |= in[7] << 6;
(*((limb *) & out[58])) = in[8];
}
/* To preserve endianness when using BN_bn2bin and BN_bin2bn */
static void flip_endian(u8 *out, const u8 *in, unsigned len)
{
unsigned i;
for (i = 0; i < len; ++i)
out[i] = in[len - 1 - i];
}
/* BN_to_felem converts an OpenSSL BIGNUM into an felem */
static int BN_to_felem(felem out, const BIGNUM *bn)
{
felem_bytearray b_in;
felem_bytearray b_out;
unsigned num_bytes;
/* BN_bn2bin eats leading zeroes */
memset(b_out, 0, sizeof(b_out));
num_bytes = BN_num_bytes(bn);
if (num_bytes > sizeof(b_out)) {
ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
}
if (BN_is_negative(bn)) {
ECerr(EC_F_BN_TO_FELEM, EC_R_BIGNUM_OUT_OF_RANGE);
return 0;
}
num_bytes = BN_bn2bin(bn, b_in);
flip_endian(b_out, b_in, num_bytes);
bin66_to_felem(out, b_out);
return 1;
}
/* felem_to_BN converts an felem into an OpenSSL BIGNUM */
static BIGNUM *felem_to_BN(BIGNUM *out, const felem in)
{
felem_bytearray b_in, b_out;
felem_to_bin66(b_in, in);
flip_endian(b_out, b_in, sizeof(b_out));
return BN_bin2bn(b_out, sizeof(b_out), out);
}
/*-
* Field operations
* ----------------
*/
static void felem_one(felem out)
{
out[0] = 1;
out[1] = 0;
out[2] = 0;
out[3] = 0;
out[4] = 0;
out[5] = 0;
out[6] = 0;
out[7] = 0;
out[8] = 0;
}
static void felem_assign(felem out, const felem in)
{
out[0] = in[0];
out[1] = in[1];
out[2] = in[2];
out[3] = in[3];
out[4] = in[4];
out[5] = in[5];
out[6] = in[6];
out[7] = in[7];
out[8] = in[8];
}
/* felem_sum64 sets out = out + in. */
static void felem_sum64(felem out, const felem in)
{
out[0] += in[0];
out[1] += in[1];
out[2] += in[2];
out[3] += in[3];
out[4] += in[4];
out[5] += in[5];
out[6] += in[6];
out[7] += in[7];
out[8] += in[8];
}
/* felem_scalar sets out = in * scalar */
static void felem_scalar(felem out, const felem in, limb scalar)
{
out[0] = in[0] * scalar;
out[1] = in[1] * scalar;
out[2] = in[2] * scalar;
out[3] = in[3] * scalar;
out[4] = in[4] * scalar;
out[5] = in[5] * scalar;
out[6] = in[6] * scalar;
out[7] = in[7] * scalar;
out[8] = in[8] * scalar;
}
/* felem_scalar64 sets out = out * scalar */
static void felem_scalar64(felem out, limb scalar)
{
out[0] *= scalar;
out[1] *= scalar;
out[2] *= scalar;
out[3] *= scalar;
out[4] *= scalar;
out[5] *= scalar;
out[6] *= scalar;
out[7] *= scalar;
out[8] *= scalar;
}
/* felem_scalar128 sets out = out * scalar */
static void felem_scalar128(largefelem out, limb scalar)
{
out[0] *= scalar;
out[1] *= scalar;
out[2] *= scalar;
out[3] *= scalar;
out[4] *= scalar;
out[5] *= scalar;
out[6] *= scalar;
out[7] *= scalar;
out[8] *= scalar;
}
/*-
* felem_neg sets |out| to |-in|
* On entry:
* in[i] < 2^59 + 2^14
* On exit:
* out[i] < 2^62
*/
static void felem_neg(felem out, const felem in)
{
/* In order to prevent underflow, we subtract from 0 mod p. */
static const limb two62m3 = (((limb) 1) << 62) - (((limb) 1) << 5);
static const limb two62m2 = (((limb) 1) << 62) - (((limb) 1) << 4);
out[0] = two62m3 - in[0];
out[1] = two62m2 - in[1];
out[2] = two62m2 - in[2];
out[3] = two62m2 - in[3];
out[4] = two62m2 - in[4];
out[5] = two62m2 - in[5];
out[6] = two62m2 - in[6];
out[7] = two62m2 - in[7];
out[8] = two62m2 - in[8];
}
/*-
* felem_diff64 subtracts |in| from |out|
* On entry:
* in[i] < 2^59 + 2^14
* On exit:
* out[i] < out[i] + 2^62
*/
static void felem_diff64(felem out, const felem in)
{
/*
* In order to prevent underflow, we add 0 mod p before subtracting.
*/
static const limb two62m3 = (((limb) 1) << 62) - (((limb) 1) << 5);
static const limb two62m2 = (((limb) 1) << 62) - (((limb) 1) << 4);
out[0] += two62m3 - in[0];
out[1] += two62m2 - in[1];
out[2] += two62m2 - in[2];
out[3] += two62m2 - in[3];
out[4] += two62m2 - in[4];
out[5] += two62m2 - in[5];
out[6] += two62m2 - in[6];
out[7] += two62m2 - in[7];
out[8] += two62m2 - in[8];
}
/*-
* felem_diff_128_64 subtracts |in| from |out|
* On entry:
* in[i] < 2^62 + 2^17
* On exit:
* out[i] < out[i] + 2^63
*/
static void felem_diff_128_64(largefelem out, const felem in)
{
/*
- * In order to prevent underflow, we add 0 mod p before subtracting.
+ * In order to prevent underflow, we add 64p mod p (which is equivalent
+ * to 0 mod p) before subtracting. p is 2^521 - 1, i.e. in binary a 521
+ * digit number with all bits set to 1. See "The representation of field
+ * elements" comment above for a description of how limbs are used to
+ * represent a number. 64p is represented with 8 limbs containing a number
+ * with 58 bits set and one limb with a number with 57 bits set.
*/
- static const limb two63m6 = (((limb) 1) << 62) - (((limb) 1) << 5);
- static const limb two63m5 = (((limb) 1) << 62) - (((limb) 1) << 4);
+ static const limb two63m6 = (((limb) 1) << 63) - (((limb) 1) << 6);
+ static const limb two63m5 = (((limb) 1) << 63) - (((limb) 1) << 5);
out[0] += two63m6 - in[0];
out[1] += two63m5 - in[1];
out[2] += two63m5 - in[2];
out[3] += two63m5 - in[3];
out[4] += two63m5 - in[4];
out[5] += two63m5 - in[5];
out[6] += two63m5 - in[6];
out[7] += two63m5 - in[7];
out[8] += two63m5 - in[8];
}
/*-
* felem_diff_128_64 subtracts |in| from |out|
* On entry:
* in[i] < 2^126
* On exit:
* out[i] < out[i] + 2^127 - 2^69
*/
static void felem_diff128(largefelem out, const largefelem in)
{
/*
* In order to prevent underflow, we add 0 mod p before subtracting.
*/
static const uint128_t two127m70 =
(((uint128_t) 1) << 127) - (((uint128_t) 1) << 70);
static const uint128_t two127m69 =
(((uint128_t) 1) << 127) - (((uint128_t) 1) << 69);
out[0] += (two127m70 - in[0]);
out[1] += (two127m69 - in[1]);
out[2] += (two127m69 - in[2]);
out[3] += (two127m69 - in[3]);
out[4] += (two127m69 - in[4]);
out[5] += (two127m69 - in[5]);
out[6] += (two127m69 - in[6]);
out[7] += (two127m69 - in[7]);
out[8] += (two127m69 - in[8]);
}
/*-
* felem_square sets |out| = |in|^2
* On entry:
* in[i] < 2^62
* On exit:
* out[i] < 17 * max(in[i]) * max(in[i])
*/
static void felem_square(largefelem out, const felem in)
{
felem inx2, inx4;
felem_scalar(inx2, in, 2);
felem_scalar(inx4, in, 4);
/*-
* We have many cases were we want to do
* in[x] * in[y] +
* in[y] * in[x]
* This is obviously just
* 2 * in[x] * in[y]
* However, rather than do the doubling on the 128 bit result, we
* double one of the inputs to the multiplication by reading from
* |inx2|
*/
out[0] = ((uint128_t) in[0]) * in[0];
out[1] = ((uint128_t) in[0]) * inx2[1];
out[2] = ((uint128_t) in[0]) * inx2[2] + ((uint128_t) in[1]) * in[1];
out[3] = ((uint128_t) in[0]) * inx2[3] + ((uint128_t) in[1]) * inx2[2];
out[4] = ((uint128_t) in[0]) * inx2[4] +
((uint128_t) in[1]) * inx2[3] + ((uint128_t) in[2]) * in[2];
out[5] = ((uint128_t) in[0]) * inx2[5] +
((uint128_t) in[1]) * inx2[4] + ((uint128_t) in[2]) * inx2[3];
out[6] = ((uint128_t) in[0]) * inx2[6] +
((uint128_t) in[1]) * inx2[5] +
((uint128_t) in[2]) * inx2[4] + ((uint128_t) in[3]) * in[3];
out[7] = ((uint128_t) in[0]) * inx2[7] +
((uint128_t) in[1]) * inx2[6] +
((uint128_t) in[2]) * inx2[5] + ((uint128_t) in[3]) * inx2[4];
out[8] = ((uint128_t) in[0]) * inx2[8] +
((uint128_t) in[1]) * inx2[7] +
((uint128_t) in[2]) * inx2[6] +
((uint128_t) in[3]) * inx2[5] + ((uint128_t) in[4]) * in[4];
/*
* The remaining limbs fall above 2^521, with the first falling at 2^522.
* They correspond to locations one bit up from the limbs produced above
* so we would have to multiply by two to align them. Again, rather than
* operate on the 128-bit result, we double one of the inputs to the
* multiplication. If we want to double for both this reason, and the
* reason above, then we end up multiplying by four.
*/
/* 9 */
out[0] += ((uint128_t) in[1]) * inx4[8] +
((uint128_t) in[2]) * inx4[7] +
((uint128_t) in[3]) * inx4[6] + ((uint128_t) in[4]) * inx4[5];
/* 10 */
out[1] += ((uint128_t) in[2]) * inx4[8] +
((uint128_t) in[3]) * inx4[7] +
((uint128_t) in[4]) * inx4[6] + ((uint128_t) in[5]) * inx2[5];
/* 11 */
out[2] += ((uint128_t) in[3]) * inx4[8] +
((uint128_t) in[4]) * inx4[7] + ((uint128_t) in[5]) * inx4[6];
/* 12 */
out[3] += ((uint128_t) in[4]) * inx4[8] +
((uint128_t) in[5]) * inx4[7] + ((uint128_t) in[6]) * inx2[6];
/* 13 */
out[4] += ((uint128_t) in[5]) * inx4[8] + ((uint128_t) in[6]) * inx4[7];
/* 14 */
out[5] += ((uint128_t) in[6]) * inx4[8] + ((uint128_t) in[7]) * inx2[7];
/* 15 */
out[6] += ((uint128_t) in[7]) * inx4[8];
/* 16 */
out[7] += ((uint128_t) in[8]) * inx2[8];
}
/*-
* felem_mul sets |out| = |in1| * |in2|
* On entry:
* in1[i] < 2^64
* in2[i] < 2^63
* On exit:
* out[i] < 17 * max(in1[i]) * max(in2[i])
*/
static void felem_mul(largefelem out, const felem in1, const felem in2)
{
felem in2x2;
felem_scalar(in2x2, in2, 2);
out[0] = ((uint128_t) in1[0]) * in2[0];
out[1] = ((uint128_t) in1[0]) * in2[1] +
((uint128_t) in1[1]) * in2[0];
out[2] = ((uint128_t) in1[0]) * in2[2] +
((uint128_t) in1[1]) * in2[1] +
((uint128_t) in1[2]) * in2[0];
out[3] = ((uint128_t) in1[0]) * in2[3] +
((uint128_t) in1[1]) * in2[2] +
((uint128_t) in1[2]) * in2[1] +
((uint128_t) in1[3]) * in2[0];
out[4] = ((uint128_t) in1[0]) * in2[4] +
((uint128_t) in1[1]) * in2[3] +
((uint128_t) in1[2]) * in2[2] +
((uint128_t) in1[3]) * in2[1] +
((uint128_t) in1[4]) * in2[0];
out[5] = ((uint128_t) in1[0]) * in2[5] +
((uint128_t) in1[1]) * in2[4] +
((uint128_t) in1[2]) * in2[3] +
((uint128_t) in1[3]) * in2[2] +
((uint128_t) in1[4]) * in2[1] +
((uint128_t) in1[5]) * in2[0];
out[6] = ((uint128_t) in1[0]) * in2[6] +
((uint128_t) in1[1]) * in2[5] +
((uint128_t) in1[2]) * in2[4] +
((uint128_t) in1[3]) * in2[3] +
((uint128_t) in1[4]) * in2[2] +
((uint128_t) in1[5]) * in2[1] +
((uint128_t) in1[6]) * in2[0];
out[7] = ((uint128_t) in1[0]) * in2[7] +
((uint128_t) in1[1]) * in2[6] +
((uint128_t) in1[2]) * in2[5] +
((uint128_t) in1[3]) * in2[4] +
((uint128_t) in1[4]) * in2[3] +
((uint128_t) in1[5]) * in2[2] +
((uint128_t) in1[6]) * in2[1] +
((uint128_t) in1[7]) * in2[0];
out[8] = ((uint128_t) in1[0]) * in2[8] +
((uint128_t) in1[1]) * in2[7] +
((uint128_t) in1[2]) * in2[6] +
((uint128_t) in1[3]) * in2[5] +
((uint128_t) in1[4]) * in2[4] +
((uint128_t) in1[5]) * in2[3] +
((uint128_t) in1[6]) * in2[2] +
((uint128_t) in1[7]) * in2[1] +
((uint128_t) in1[8]) * in2[0];
/* See comment in felem_square about the use of in2x2 here */
out[0] += ((uint128_t) in1[1]) * in2x2[8] +
((uint128_t) in1[2]) * in2x2[7] +
((uint128_t) in1[3]) * in2x2[6] +
((uint128_t) in1[4]) * in2x2[5] +
((uint128_t) in1[5]) * in2x2[4] +
((uint128_t) in1[6]) * in2x2[3] +
((uint128_t) in1[7]) * in2x2[2] +
((uint128_t) in1[8]) * in2x2[1];
out[1] += ((uint128_t) in1[2]) * in2x2[8] +
((uint128_t) in1[3]) * in2x2[7] +
((uint128_t) in1[4]) * in2x2[6] +
((uint128_t) in1[5]) * in2x2[5] +
((uint128_t) in1[6]) * in2x2[4] +
((uint128_t) in1[7]) * in2x2[3] +
((uint128_t) in1[8]) * in2x2[2];
out[2] += ((uint128_t) in1[3]) * in2x2[8] +
((uint128_t) in1[4]) * in2x2[7] +
((uint128_t) in1[5]) * in2x2[6] +
((uint128_t) in1[6]) * in2x2[5] +
((uint128_t) in1[7]) * in2x2[4] +
((uint128_t) in1[8]) * in2x2[3];
out[3] += ((uint128_t) in1[4]) * in2x2[8] +
((uint128_t) in1[5]) * in2x2[7] +
((uint128_t) in1[6]) * in2x2[6] +
((uint128_t) in1[7]) * in2x2[5] +
((uint128_t) in1[8]) * in2x2[4];
out[4] += ((uint128_t) in1[5]) * in2x2[8] +
((uint128_t) in1[6]) * in2x2[7] +
((uint128_t) in1[7]) * in2x2[6] +
((uint128_t) in1[8]) * in2x2[5];
out[5] += ((uint128_t) in1[6]) * in2x2[8] +
((uint128_t) in1[7]) * in2x2[7] +
((uint128_t) in1[8]) * in2x2[6];
out[6] += ((uint128_t) in1[7]) * in2x2[8] +
((uint128_t) in1[8]) * in2x2[7];
out[7] += ((uint128_t) in1[8]) * in2x2[8];
}
static const limb bottom52bits = 0xfffffffffffff;
/*-
* felem_reduce converts a largefelem to an felem.
* On entry:
* in[i] < 2^128
* On exit:
* out[i] < 2^59 + 2^14
*/
static void felem_reduce(felem out, const largefelem in)
{
u64 overflow1, overflow2;
out[0] = ((limb) in[0]) & bottom58bits;
out[1] = ((limb) in[1]) & bottom58bits;
out[2] = ((limb) in[2]) & bottom58bits;
out[3] = ((limb) in[3]) & bottom58bits;
out[4] = ((limb) in[4]) & bottom58bits;
out[5] = ((limb) in[5]) & bottom58bits;
out[6] = ((limb) in[6]) & bottom58bits;
out[7] = ((limb) in[7]) & bottom58bits;
out[8] = ((limb) in[8]) & bottom58bits;
/* out[i] < 2^58 */
out[1] += ((limb) in[0]) >> 58;
out[1] += (((limb) (in[0] >> 64)) & bottom52bits) << 6;
/*-
* out[1] < 2^58 + 2^6 + 2^58
* = 2^59 + 2^6
*/
out[2] += ((limb) (in[0] >> 64)) >> 52;
out[2] += ((limb) in[1]) >> 58;
out[2] += (((limb) (in[1] >> 64)) & bottom52bits) << 6;
out[3] += ((limb) (in[1] >> 64)) >> 52;
out[3] += ((limb) in[2]) >> 58;
out[3] += (((limb) (in[2] >> 64)) & bottom52bits) << 6;
out[4] += ((limb) (in[2] >> 64)) >> 52;
out[4] += ((limb) in[3]) >> 58;
out[4] += (((limb) (in[3] >> 64)) & bottom52bits) << 6;
out[5] += ((limb) (in[3] >> 64)) >> 52;
out[5] += ((limb) in[4]) >> 58;
out[5] += (((limb) (in[4] >> 64)) & bottom52bits) << 6;
out[6] += ((limb) (in[4] >> 64)) >> 52;
out[6] += ((limb) in[5]) >> 58;
out[6] += (((limb) (in[5] >> 64)) & bottom52bits) << 6;
out[7] += ((limb) (in[5] >> 64)) >> 52;
out[7] += ((limb) in[6]) >> 58;
out[7] += (((limb) (in[6] >> 64)) & bottom52bits) << 6;
out[8] += ((limb) (in[6] >> 64)) >> 52;
out[8] += ((limb) in[7]) >> 58;
out[8] += (((limb) (in[7] >> 64)) & bottom52bits) << 6;
/*-
* out[x > 1] < 2^58 + 2^6 + 2^58 + 2^12
* < 2^59 + 2^13
*/
overflow1 = ((limb) (in[7] >> 64)) >> 52;
overflow1 += ((limb) in[8]) >> 58;
overflow1 += (((limb) (in[8] >> 64)) & bottom52bits) << 6;
overflow2 = ((limb) (in[8] >> 64)) >> 52;
overflow1 <<= 1; /* overflow1 < 2^13 + 2^7 + 2^59 */
overflow2 <<= 1; /* overflow2 < 2^13 */
out[0] += overflow1; /* out[0] < 2^60 */
out[1] += overflow2; /* out[1] < 2^59 + 2^6 + 2^13 */
out[1] += out[0] >> 58;
out[0] &= bottom58bits;
/*-
* out[0] < 2^58
* out[1] < 2^59 + 2^6 + 2^13 + 2^2
* < 2^59 + 2^14
*/
}
static void felem_square_reduce(felem out, const felem in)
{
largefelem tmp;
felem_square(tmp, in);
felem_reduce(out, tmp);
}
static void felem_mul_reduce(felem out, const felem in1, const felem in2)
{
largefelem tmp;
felem_mul(tmp, in1, in2);
felem_reduce(out, tmp);
}
/*-
* felem_inv calculates |out| = |in|^{-1}
*
* Based on Fermat's Little Theorem:
* a^p = a (mod p)
* a^{p-1} = 1 (mod p)
* a^{p-2} = a^{-1} (mod p)
*/
static void felem_inv(felem out, const felem in)
{
felem ftmp, ftmp2, ftmp3, ftmp4;
largefelem tmp;
unsigned i;
felem_square(tmp, in);
felem_reduce(ftmp, tmp); /* 2^1 */
felem_mul(tmp, in, ftmp);
felem_reduce(ftmp, tmp); /* 2^2 - 2^0 */
felem_assign(ftmp2, ftmp);
felem_square(tmp, ftmp);
felem_reduce(ftmp, tmp); /* 2^3 - 2^1 */
felem_mul(tmp, in, ftmp);
felem_reduce(ftmp, tmp); /* 2^3 - 2^0 */
felem_square(tmp, ftmp);
felem_reduce(ftmp, tmp); /* 2^4 - 2^1 */
felem_square(tmp, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^3 - 2^1 */
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^4 - 2^2 */
felem_mul(tmp, ftmp3, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^4 - 2^0 */
felem_assign(ftmp2, ftmp3);
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^5 - 2^1 */
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^6 - 2^2 */
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^7 - 2^3 */
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^8 - 2^4 */
felem_assign(ftmp4, ftmp3);
felem_mul(tmp, ftmp3, ftmp);
felem_reduce(ftmp4, tmp); /* 2^8 - 2^1 */
felem_square(tmp, ftmp4);
felem_reduce(ftmp4, tmp); /* 2^9 - 2^2 */
felem_mul(tmp, ftmp3, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^8 - 2^0 */
felem_assign(ftmp2, ftmp3);
for (i = 0; i < 8; i++) {
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^16 - 2^8 */
}
felem_mul(tmp, ftmp3, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^16 - 2^0 */
felem_assign(ftmp2, ftmp3);
for (i = 0; i < 16; i++) {
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^32 - 2^16 */
}
felem_mul(tmp, ftmp3, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^32 - 2^0 */
felem_assign(ftmp2, ftmp3);
for (i = 0; i < 32; i++) {
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^64 - 2^32 */
}
felem_mul(tmp, ftmp3, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^64 - 2^0 */
felem_assign(ftmp2, ftmp3);
for (i = 0; i < 64; i++) {
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^128 - 2^64 */
}
felem_mul(tmp, ftmp3, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^128 - 2^0 */
felem_assign(ftmp2, ftmp3);
for (i = 0; i < 128; i++) {
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^256 - 2^128 */
}
felem_mul(tmp, ftmp3, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^256 - 2^0 */
felem_assign(ftmp2, ftmp3);
for (i = 0; i < 256; i++) {
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^512 - 2^256 */
}
felem_mul(tmp, ftmp3, ftmp2);
felem_reduce(ftmp3, tmp); /* 2^512 - 2^0 */
for (i = 0; i < 9; i++) {
felem_square(tmp, ftmp3);
felem_reduce(ftmp3, tmp); /* 2^521 - 2^9 */
}
felem_mul(tmp, ftmp3, ftmp4);
felem_reduce(ftmp3, tmp); /* 2^512 - 2^2 */
felem_mul(tmp, ftmp3, in);
felem_reduce(out, tmp); /* 2^512 - 3 */
}
/* This is 2^521-1, expressed as an felem */
static const felem kPrime = {
0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff,
0x03ffffffffffffff, 0x03ffffffffffffff, 0x03ffffffffffffff,
0x03ffffffffffffff, 0x03ffffffffffffff, 0x01ffffffffffffff
};
/*-
* felem_is_zero returns a limb with all bits set if |in| == 0 (mod p) and 0
* otherwise.
* On entry:
* in[i] < 2^59 + 2^14
*/
static limb felem_is_zero(const felem in)
{
felem ftmp;
limb is_zero, is_p;
felem_assign(ftmp, in);
ftmp[0] += ftmp[8] >> 57;
ftmp[8] &= bottom57bits;
/* ftmp[8] < 2^57 */
ftmp[1] += ftmp[0] >> 58;
ftmp[0] &= bottom58bits;
ftmp[2] += ftmp[1] >> 58;
ftmp[1] &= bottom58bits;
ftmp[3] += ftmp[2] >> 58;
ftmp[2] &= bottom58bits;
ftmp[4] += ftmp[3] >> 58;
ftmp[3] &= bottom58bits;
ftmp[5] += ftmp[4] >> 58;
ftmp[4] &= bottom58bits;
ftmp[6] += ftmp[5] >> 58;
ftmp[5] &= bottom58bits;
ftmp[7] += ftmp[6] >> 58;
ftmp[6] &= bottom58bits;
ftmp[8] += ftmp[7] >> 58;
ftmp[7] &= bottom58bits;
/* ftmp[8] < 2^57 + 4 */
/*
* The ninth limb of 2*(2^521-1) is 0x03ffffffffffffff, which is greater
* than our bound for ftmp[8]. Therefore we only have to check if the
* zero is zero or 2^521-1.
*/
is_zero = 0;
is_zero |= ftmp[0];
is_zero |= ftmp[1];
is_zero |= ftmp[2];
is_zero |= ftmp[3];
is_zero |= ftmp[4];
is_zero |= ftmp[5];
is_zero |= ftmp[6];
is_zero |= ftmp[7];
is_zero |= ftmp[8];
is_zero--;
/*
* We know that ftmp[i] < 2^63, therefore the only way that the top bit
* can be set is if is_zero was 0 before the decrement.
*/
is_zero = 0 - (is_zero >> 63);
is_p = ftmp[0] ^ kPrime[0];
is_p |= ftmp[1] ^ kPrime[1];
is_p |= ftmp[2] ^ kPrime[2];
is_p |= ftmp[3] ^ kPrime[3];
is_p |= ftmp[4] ^ kPrime[4];
is_p |= ftmp[5] ^ kPrime[5];
is_p |= ftmp[6] ^ kPrime[6];
is_p |= ftmp[7] ^ kPrime[7];
is_p |= ftmp[8] ^ kPrime[8];
is_p--;
is_p = 0 - (is_p >> 63);
is_zero |= is_p;
return is_zero;
}
static int felem_is_zero_int(const void *in)
{
return (int)(felem_is_zero(in) & ((limb) 1));
}
/*-
* felem_contract converts |in| to its unique, minimal representation.
* On entry:
* in[i] < 2^59 + 2^14
*/
static void felem_contract(felem out, const felem in)
{
limb is_p, is_greater, sign;
static const limb two58 = ((limb) 1) << 58;
felem_assign(out, in);
out[0] += out[8] >> 57;
out[8] &= bottom57bits;
/* out[8] < 2^57 */
out[1] += out[0] >> 58;
out[0] &= bottom58bits;
out[2] += out[1] >> 58;
out[1] &= bottom58bits;
out[3] += out[2] >> 58;
out[2] &= bottom58bits;
out[4] += out[3] >> 58;
out[3] &= bottom58bits;
out[5] += out[4] >> 58;
out[4] &= bottom58bits;
out[6] += out[5] >> 58;
out[5] &= bottom58bits;
out[7] += out[6] >> 58;
out[6] &= bottom58bits;
out[8] += out[7] >> 58;
out[7] &= bottom58bits;
/* out[8] < 2^57 + 4 */
/*
* If the value is greater than 2^521-1 then we have to subtract 2^521-1
* out. See the comments in felem_is_zero regarding why we don't test for
* other multiples of the prime.
*/
/*
* First, if |out| is equal to 2^521-1, we subtract it out to get zero.
*/
is_p = out[0] ^ kPrime[0];
is_p |= out[1] ^ kPrime[1];
is_p |= out[2] ^ kPrime[2];
is_p |= out[3] ^ kPrime[3];
is_p |= out[4] ^ kPrime[4];
is_p |= out[5] ^ kPrime[5];
is_p |= out[6] ^ kPrime[6];
is_p |= out[7] ^ kPrime[7];
is_p |= out[8] ^ kPrime[8];
is_p--;
is_p &= is_p << 32;
is_p &= is_p << 16;
is_p &= is_p << 8;
is_p &= is_p << 4;
is_p &= is_p << 2;
is_p &= is_p << 1;
is_p = 0 - (is_p >> 63);
is_p = ~is_p;
/* is_p is 0 iff |out| == 2^521-1 and all ones otherwise */
out[0] &= is_p;
out[1] &= is_p;
out[2] &= is_p;
out[3] &= is_p;
out[4] &= is_p;
out[5] &= is_p;
out[6] &= is_p;
out[7] &= is_p;
out[8] &= is_p;
/*
* In order to test that |out| >= 2^521-1 we need only test if out[8] >>
* 57 is greater than zero as (2^521-1) + x >= 2^522
*/
is_greater = out[8] >> 57;
is_greater |= is_greater << 32;
is_greater |= is_greater << 16;
is_greater |= is_greater << 8;
is_greater |= is_greater << 4;
is_greater |= is_greater << 2;
is_greater |= is_greater << 1;
is_greater = 0 - (is_greater >> 63);
out[0] -= kPrime[0] & is_greater;
out[1] -= kPrime[1] & is_greater;
out[2] -= kPrime[2] & is_greater;
out[3] -= kPrime[3] & is_greater;
out[4] -= kPrime[4] & is_greater;
out[5] -= kPrime[5] & is_greater;
out[6] -= kPrime[6] & is_greater;
out[7] -= kPrime[7] & is_greater;
out[8] -= kPrime[8] & is_greater;
/* Eliminate negative coefficients */
sign = -(out[0] >> 63);
out[0] += (two58 & sign);
out[1] -= (1 & sign);
sign = -(out[1] >> 63);
out[1] += (two58 & sign);
out[2] -= (1 & sign);
sign = -(out[2] >> 63);
out[2] += (two58 & sign);
out[3] -= (1 & sign);
sign = -(out[3] >> 63);
out[3] += (two58 & sign);
out[4] -= (1 & sign);
sign = -(out[4] >> 63);
out[4] += (two58 & sign);
out[5] -= (1 & sign);
sign = -(out[0] >> 63);
out[5] += (two58 & sign);
out[6] -= (1 & sign);
sign = -(out[6] >> 63);
out[6] += (two58 & sign);
out[7] -= (1 & sign);
sign = -(out[7] >> 63);
out[7] += (two58 & sign);
out[8] -= (1 & sign);
sign = -(out[5] >> 63);
out[5] += (two58 & sign);
out[6] -= (1 & sign);
sign = -(out[6] >> 63);
out[6] += (two58 & sign);
out[7] -= (1 & sign);
sign = -(out[7] >> 63);
out[7] += (two58 & sign);
out[8] -= (1 & sign);
}
/*-
* Group operations
* ----------------
*
* Building on top of the field operations we have the operations on the
* elliptic curve group itself. Points on the curve are represented in Jacobian
* coordinates */
/*-
* point_double calculates 2*(x_in, y_in, z_in)
*
* The method is taken from:
* http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#doubling-dbl-2001-b
*
* Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed.
* while x_out == y_in is not (maybe this works, but it's not tested). */
static void
point_double(felem x_out, felem y_out, felem z_out,
const felem x_in, const felem y_in, const felem z_in)
{
largefelem tmp, tmp2;
felem delta, gamma, beta, alpha, ftmp, ftmp2;
felem_assign(ftmp, x_in);
felem_assign(ftmp2, x_in);
/* delta = z^2 */
felem_square(tmp, z_in);
felem_reduce(delta, tmp); /* delta[i] < 2^59 + 2^14 */
/* gamma = y^2 */
felem_square(tmp, y_in);
felem_reduce(gamma, tmp); /* gamma[i] < 2^59 + 2^14 */
/* beta = x*gamma */
felem_mul(tmp, x_in, gamma);
felem_reduce(beta, tmp); /* beta[i] < 2^59 + 2^14 */
/* alpha = 3*(x-delta)*(x+delta) */
felem_diff64(ftmp, delta);
/* ftmp[i] < 2^61 */
felem_sum64(ftmp2, delta);
/* ftmp2[i] < 2^60 + 2^15 */
felem_scalar64(ftmp2, 3);
/* ftmp2[i] < 3*2^60 + 3*2^15 */
felem_mul(tmp, ftmp, ftmp2);
/*-
* tmp[i] < 17(3*2^121 + 3*2^76)
* = 61*2^121 + 61*2^76
* < 64*2^121 + 64*2^76
* = 2^127 + 2^82
* < 2^128
*/
felem_reduce(alpha, tmp);
/* x' = alpha^2 - 8*beta */
felem_square(tmp, alpha);
/*
* tmp[i] < 17*2^120 < 2^125
*/
felem_assign(ftmp, beta);
felem_scalar64(ftmp, 8);
/* ftmp[i] < 2^62 + 2^17 */
felem_diff_128_64(tmp, ftmp);
/* tmp[i] < 2^125 + 2^63 + 2^62 + 2^17 */
felem_reduce(x_out, tmp);
/* z' = (y + z)^2 - gamma - delta */
felem_sum64(delta, gamma);
/* delta[i] < 2^60 + 2^15 */
felem_assign(ftmp, y_in);
felem_sum64(ftmp, z_in);
/* ftmp[i] < 2^60 + 2^15 */
felem_square(tmp, ftmp);
/*
* tmp[i] < 17(2^122) < 2^127
*/
felem_diff_128_64(tmp, delta);
/* tmp[i] < 2^127 + 2^63 */
felem_reduce(z_out, tmp);
/* y' = alpha*(4*beta - x') - 8*gamma^2 */
felem_scalar64(beta, 4);
/* beta[i] < 2^61 + 2^16 */
felem_diff64(beta, x_out);
/* beta[i] < 2^61 + 2^60 + 2^16 */
felem_mul(tmp, alpha, beta);
/*-
* tmp[i] < 17*((2^59 + 2^14)(2^61 + 2^60 + 2^16))
* = 17*(2^120 + 2^75 + 2^119 + 2^74 + 2^75 + 2^30)
* = 17*(2^120 + 2^119 + 2^76 + 2^74 + 2^30)
* < 2^128
*/
felem_square(tmp2, gamma);
/*-
* tmp2[i] < 17*(2^59 + 2^14)^2
* = 17*(2^118 + 2^74 + 2^28)
*/
felem_scalar128(tmp2, 8);
/*-
* tmp2[i] < 8*17*(2^118 + 2^74 + 2^28)
* = 2^125 + 2^121 + 2^81 + 2^77 + 2^35 + 2^31
* < 2^126
*/
felem_diff128(tmp, tmp2);
/*-
* tmp[i] < 2^127 - 2^69 + 17(2^120 + 2^119 + 2^76 + 2^74 + 2^30)
* = 2^127 + 2^124 + 2^122 + 2^120 + 2^118 + 2^80 + 2^78 + 2^76 +
* 2^74 + 2^69 + 2^34 + 2^30
* < 2^128
*/
felem_reduce(y_out, tmp);
}
/* copy_conditional copies in to out iff mask is all ones. */
static void copy_conditional(felem out, const felem in, limb mask)
{
unsigned i;
for (i = 0; i < NLIMBS; ++i) {
const limb tmp = mask & (in[i] ^ out[i]);
out[i] ^= tmp;
}
}
/*-
* point_add calculates (x1, y1, z1) + (x2, y2, z2)
*
* The method is taken from
* http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-3.html#addition-add-2007-bl,
* adapted for mixed addition (z2 = 1, or z2 = 0 for the point at infinity).
*
* This function includes a branch for checking whether the two input points
* are equal (while not equal to the point at infinity). See comment below
* on constant-time.
*/
static void point_add(felem x3, felem y3, felem z3,
const felem x1, const felem y1, const felem z1,
const int mixed, const felem x2, const felem y2,
const felem z2)
{
felem ftmp, ftmp2, ftmp3, ftmp4, ftmp5, ftmp6, x_out, y_out, z_out;
largefelem tmp, tmp2;
limb x_equal, y_equal, z1_is_zero, z2_is_zero;
z1_is_zero = felem_is_zero(z1);
z2_is_zero = felem_is_zero(z2);
/* ftmp = z1z1 = z1**2 */
felem_square(tmp, z1);
felem_reduce(ftmp, tmp);
if (!mixed) {
/* ftmp2 = z2z2 = z2**2 */
felem_square(tmp, z2);
felem_reduce(ftmp2, tmp);
/* u1 = ftmp3 = x1*z2z2 */
felem_mul(tmp, x1, ftmp2);
felem_reduce(ftmp3, tmp);
/* ftmp5 = z1 + z2 */
felem_assign(ftmp5, z1);
felem_sum64(ftmp5, z2);
/* ftmp5[i] < 2^61 */
/* ftmp5 = (z1 + z2)**2 - z1z1 - z2z2 = 2*z1z2 */
felem_square(tmp, ftmp5);
/* tmp[i] < 17*2^122 */
felem_diff_128_64(tmp, ftmp);
/* tmp[i] < 17*2^122 + 2^63 */
felem_diff_128_64(tmp, ftmp2);
/* tmp[i] < 17*2^122 + 2^64 */
felem_reduce(ftmp5, tmp);
/* ftmp2 = z2 * z2z2 */
felem_mul(tmp, ftmp2, z2);
felem_reduce(ftmp2, tmp);
/* s1 = ftmp6 = y1 * z2**3 */
felem_mul(tmp, y1, ftmp2);
felem_reduce(ftmp6, tmp);
} else {
/*
* We'll assume z2 = 1 (special case z2 = 0 is handled later)
*/
/* u1 = ftmp3 = x1*z2z2 */
felem_assign(ftmp3, x1);
/* ftmp5 = 2*z1z2 */
felem_scalar(ftmp5, z1, 2);
/* s1 = ftmp6 = y1 * z2**3 */
felem_assign(ftmp6, y1);
}
/* u2 = x2*z1z1 */
felem_mul(tmp, x2, ftmp);
/* tmp[i] < 17*2^120 */
/* h = ftmp4 = u2 - u1 */
felem_diff_128_64(tmp, ftmp3);
/* tmp[i] < 17*2^120 + 2^63 */
felem_reduce(ftmp4, tmp);
x_equal = felem_is_zero(ftmp4);
/* z_out = ftmp5 * h */
felem_mul(tmp, ftmp5, ftmp4);
felem_reduce(z_out, tmp);
/* ftmp = z1 * z1z1 */
felem_mul(tmp, ftmp, z1);
felem_reduce(ftmp, tmp);
/* s2 = tmp = y2 * z1**3 */
felem_mul(tmp, y2, ftmp);
/* tmp[i] < 17*2^120 */
/* r = ftmp5 = (s2 - s1)*2 */
felem_diff_128_64(tmp, ftmp6);
/* tmp[i] < 17*2^120 + 2^63 */
felem_reduce(ftmp5, tmp);
y_equal = felem_is_zero(ftmp5);
felem_scalar64(ftmp5, 2);
/* ftmp5[i] < 2^61 */
if (x_equal && y_equal && !z1_is_zero && !z2_is_zero) {
/*
* This is obviously not constant-time but it will almost-never happen
* for ECDH / ECDSA. The case where it can happen is during scalar-mult
* where the intermediate value gets very close to the group order.
* Since |ec_GFp_nistp_recode_scalar_bits| produces signed digits for
* the scalar, it's possible for the intermediate value to be a small
* negative multiple of the base point, and for the final signed digit
* to be the same value. We believe that this only occurs for the scalar
* 1fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
* ffffffa51868783bf2f966b7fcc0148f709a5d03bb5c9b8899c47aebb6fb
* 71e913863f7, in that case the penultimate intermediate is -9G and
* the final digit is also -9G. Since this only happens for a single
* scalar, the timing leak is irrelevent. (Any attacker who wanted to
* check whether a secret scalar was that exact value, can already do
* so.)
*/
point_double(x3, y3, z3, x1, y1, z1);
return;
}
/* I = ftmp = (2h)**2 */
felem_assign(ftmp, ftmp4);
felem_scalar64(ftmp, 2);
/* ftmp[i] < 2^61 */
felem_square(tmp, ftmp);
/* tmp[i] < 17*2^122 */
felem_reduce(ftmp, tmp);
/* J = ftmp2 = h * I */
felem_mul(tmp, ftmp4, ftmp);
felem_reduce(ftmp2, tmp);
/* V = ftmp4 = U1 * I */
felem_mul(tmp, ftmp3, ftmp);
felem_reduce(ftmp4, tmp);
/* x_out = r**2 - J - 2V */
felem_square(tmp, ftmp5);
/* tmp[i] < 17*2^122 */
felem_diff_128_64(tmp, ftmp2);
/* tmp[i] < 17*2^122 + 2^63 */
felem_assign(ftmp3, ftmp4);
felem_scalar64(ftmp4, 2);
/* ftmp4[i] < 2^61 */
felem_diff_128_64(tmp, ftmp4);
/* tmp[i] < 17*2^122 + 2^64 */
felem_reduce(x_out, tmp);
/* y_out = r(V-x_out) - 2 * s1 * J */
felem_diff64(ftmp3, x_out);
/*
* ftmp3[i] < 2^60 + 2^60 = 2^61
*/
felem_mul(tmp, ftmp5, ftmp3);
/* tmp[i] < 17*2^122 */
felem_mul(tmp2, ftmp6, ftmp2);
/* tmp2[i] < 17*2^120 */
felem_scalar128(tmp2, 2);
/* tmp2[i] < 17*2^121 */
felem_diff128(tmp, tmp2);
/*-
* tmp[i] < 2^127 - 2^69 + 17*2^122
* = 2^126 - 2^122 - 2^6 - 2^2 - 1
* < 2^127
*/
felem_reduce(y_out, tmp);
copy_conditional(x_out, x2, z1_is_zero);
copy_conditional(x_out, x1, z2_is_zero);
copy_conditional(y_out, y2, z1_is_zero);
copy_conditional(y_out, y1, z2_is_zero);
copy_conditional(z_out, z2, z1_is_zero);
copy_conditional(z_out, z1, z2_is_zero);
felem_assign(x3, x_out);
felem_assign(y3, y_out);
felem_assign(z3, z_out);
}
/*-
* Base point pre computation
* --------------------------
*
* Two different sorts of precomputed tables are used in the following code.
* Each contain various points on the curve, where each point is three field
* elements (x, y, z).
*
* For the base point table, z is usually 1 (0 for the point at infinity).
* This table has 16 elements:
* index | bits | point
* ------+---------+------------------------------
* 0 | 0 0 0 0 | 0G
* 1 | 0 0 0 1 | 1G
* 2 | 0 0 1 0 | 2^130G
* 3 | 0 0 1 1 | (2^130 + 1)G
* 4 | 0 1 0 0 | 2^260G
* 5 | 0 1 0 1 | (2^260 + 1)G
* 6 | 0 1 1 0 | (2^260 + 2^130)G
* 7 | 0 1 1 1 | (2^260 + 2^130 + 1)G
* 8 | 1 0 0 0 | 2^390G
* 9 | 1 0 0 1 | (2^390 + 1)G
* 10 | 1 0 1 0 | (2^390 + 2^130)G
* 11 | 1 0 1 1 | (2^390 + 2^130 + 1)G
* 12 | 1 1 0 0 | (2^390 + 2^260)G
* 13 | 1 1 0 1 | (2^390 + 2^260 + 1)G
* 14 | 1 1 1 0 | (2^390 + 2^260 + 2^130)G
* 15 | 1 1 1 1 | (2^390 + 2^260 + 2^130 + 1)G
*
* The reason for this is so that we can clock bits into four different
* locations when doing simple scalar multiplies against the base point.
*
* Tables for other points have table[i] = iG for i in 0 .. 16. */
/* gmul is the table of precomputed base points */
static const felem gmul[16][3] = {
{{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x017e7e31c2e5bd66, 0x022cf0615a90a6fe, 0x00127a2ffa8de334,
0x01dfbf9d64a3f877, 0x006b4d3dbaa14b5e, 0x014fed487e0a2bd8,
0x015b4429c6481390, 0x03a73678fb2d988e, 0x00c6858e06b70404},
{0x00be94769fd16650, 0x031c21a89cb09022, 0x039013fad0761353,
0x02657bd099031542, 0x03273e662c97ee72, 0x01e6d11a05ebef45,
0x03d1bd998f544495, 0x03001172297ed0b1, 0x011839296a789a3b},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x0373faacbc875bae, 0x00f325023721c671, 0x00f666fd3dbde5ad,
0x01a6932363f88ea7, 0x01fc6d9e13f9c47b, 0x03bcbffc2bbf734e,
0x013ee3c3647f3a92, 0x029409fefe75d07d, 0x00ef9199963d85e5},
{0x011173743ad5b178, 0x02499c7c21bf7d46, 0x035beaeabb8b1a58,
0x00f989c4752ea0a3, 0x0101e1de48a9c1a3, 0x01a20076be28ba6c,
0x02f8052e5eb2de95, 0x01bfe8f82dea117c, 0x0160074d3c36ddb7},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x012f3fc373393b3b, 0x03d3d6172f1419fa, 0x02adc943c0b86873,
0x00d475584177952b, 0x012a4d1673750ee2, 0x00512517a0f13b0c,
0x02b184671a7b1734, 0x0315b84236f1a50a, 0x00a4afc472edbdb9},
{0x00152a7077f385c4, 0x03044007d8d1c2ee, 0x0065829d61d52b52,
0x00494ff6b6631d0d, 0x00a11d94d5f06bcf, 0x02d2f89474d9282e,
0x0241c5727c06eeb9, 0x0386928710fbdb9d, 0x01f883f727b0dfbe},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x019b0c3c9185544d, 0x006243a37c9d97db, 0x02ee3cbe030a2ad2,
0x00cfdd946bb51e0d, 0x0271c00932606b91, 0x03f817d1ec68c561,
0x03f37009806a369c, 0x03c1f30baf184fd5, 0x01091022d6d2f065},
{0x0292c583514c45ed, 0x0316fca51f9a286c, 0x00300af507c1489a,
0x0295f69008298cf1, 0x02c0ed8274943d7b, 0x016509b9b47a431e,
0x02bc9de9634868ce, 0x005b34929bffcb09, 0x000c1a0121681524},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x0286abc0292fb9f2, 0x02665eee9805b3f7, 0x01ed7455f17f26d6,
0x0346355b83175d13, 0x006284944cd0a097, 0x0191895bcdec5e51,
0x02e288370afda7d9, 0x03b22312bfefa67a, 0x01d104d3fc0613fe},
{0x0092421a12f7e47f, 0x0077a83fa373c501, 0x03bd25c5f696bd0d,
0x035c41e4d5459761, 0x01ca0d1742b24f53, 0x00aaab27863a509c,
0x018b6de47df73917, 0x025c0b771705cd01, 0x01fd51d566d760a7},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x01dd92ff6b0d1dbd, 0x039c5e2e8f8afa69, 0x0261ed13242c3b27,
0x0382c6e67026e6a0, 0x01d60b10be2089f9, 0x03c15f3dce86723f,
0x03c764a32d2a062d, 0x017307eac0fad056, 0x018207c0b96c5256},
{0x0196a16d60e13154, 0x03e6ce74c0267030, 0x00ddbf2b4e52a5aa,
0x012738241bbf31c8, 0x00ebe8dc04685a28, 0x024c2ad6d380d4a2,
0x035ee062a6e62d0e, 0x0029ed74af7d3a0f, 0x00eef32aec142ebd},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x00c31ec398993b39, 0x03a9f45bcda68253, 0x00ac733c24c70890,
0x00872b111401ff01, 0x01d178c23195eafb, 0x03bca2c816b87f74,
0x0261a9af46fbad7a, 0x0324b2a8dd3d28f9, 0x00918121d8f24e23},
{0x032bc8c1ca983cd7, 0x00d869dfb08fc8c6, 0x01693cb61fce1516,
0x012a5ea68f4e88a8, 0x010869cab88d7ae3, 0x009081ad277ceee1,
0x033a77166d064cdc, 0x03955235a1fb3a95, 0x01251a4a9b25b65e},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x00148a3a1b27f40b, 0x0123186df1b31fdc, 0x00026e7beaad34ce,
0x01db446ac1d3dbba, 0x0299c1a33437eaec, 0x024540610183cbb7,
0x0173bb0e9ce92e46, 0x02b937e43921214b, 0x01ab0436a9bf01b5},
{0x0383381640d46948, 0x008dacbf0e7f330f, 0x03602122bcc3f318,
0x01ee596b200620d6, 0x03bd0585fda430b3, 0x014aed77fd123a83,
0x005ace749e52f742, 0x0390fe041da2b842, 0x0189a8ceb3299242},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x012a19d6b3282473, 0x00c0915918b423ce, 0x023a954eb94405ae,
0x00529f692be26158, 0x0289fa1b6fa4b2aa, 0x0198ae4ceea346ef,
0x0047d8cdfbdedd49, 0x00cc8c8953f0f6b8, 0x001424abbff49203},
{0x0256732a1115a03a, 0x0351bc38665c6733, 0x03f7b950fb4a6447,
0x000afffa94c22155, 0x025763d0a4dab540, 0x000511e92d4fc283,
0x030a7e9eda0ee96c, 0x004c3cd93a28bf0a, 0x017edb3a8719217f},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x011de5675a88e673, 0x031d7d0f5e567fbe, 0x0016b2062c970ae5,
0x03f4a2be49d90aa7, 0x03cef0bd13822866, 0x03f0923dcf774a6c,
0x0284bebc4f322f72, 0x016ab2645302bb2c, 0x01793f95dace0e2a},
{0x010646e13527a28f, 0x01ca1babd59dc5e7, 0x01afedfd9a5595df,
0x01f15785212ea6b1, 0x0324e5d64f6ae3f4, 0x02d680f526d00645,
0x0127920fadf627a7, 0x03b383f75df4f684, 0x0089e0057e783b0a},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x00f334b9eb3c26c6, 0x0298fdaa98568dce, 0x01c2d24843a82292,
0x020bcb24fa1b0711, 0x02cbdb3d2b1875e6, 0x0014907598f89422,
0x03abe3aa43b26664, 0x02cbf47f720bc168, 0x0133b5e73014b79b},
{0x034aab5dab05779d, 0x00cdc5d71fee9abb, 0x0399f16bd4bd9d30,
0x03582fa592d82647, 0x02be1cdfb775b0e9, 0x0034f7cea32e94cb,
0x0335a7f08f56f286, 0x03b707e9565d1c8b, 0x0015c946ea5b614f},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x024676f6cff72255, 0x00d14625cac96378, 0x00532b6008bc3767,
0x01fc16721b985322, 0x023355ea1b091668, 0x029de7afdc0317c3,
0x02fc8a7ca2da037c, 0x02de1217d74a6f30, 0x013f7173175b73bf},
{0x0344913f441490b5, 0x0200f9e272b61eca, 0x0258a246b1dd55d2,
0x03753db9ea496f36, 0x025e02937a09c5ef, 0x030cbd3d14012692,
0x01793a67e70dc72a, 0x03ec1d37048a662e, 0x006550f700c32a8d},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x00d3f48a347eba27, 0x008e636649b61bd8, 0x00d3b93716778fb3,
0x004d1915757bd209, 0x019d5311a3da44e0, 0x016d1afcbbe6aade,
0x0241bf5f73265616, 0x0384672e5d50d39b, 0x005009fee522b684},
{0x029b4fab064435fe, 0x018868ee095bbb07, 0x01ea3d6936cc92b8,
0x000608b00f78a2f3, 0x02db911073d1c20f, 0x018205938470100a,
0x01f1e4964cbe6ff2, 0x021a19a29eed4663, 0x01414485f42afa81},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x01612b3a17f63e34, 0x03813992885428e6, 0x022b3c215b5a9608,
0x029b4057e19f2fcb, 0x0384059a587af7e6, 0x02d6400ace6fe610,
0x029354d896e8e331, 0x00c047ee6dfba65e, 0x0037720542e9d49d},
{0x02ce9eed7c5e9278, 0x0374ed703e79643b, 0x01316c54c4072006,
0x005aaa09054b2ee8, 0x002824000c840d57, 0x03d4eba24771ed86,
0x0189c50aabc3bdae, 0x0338c01541e15510, 0x00466d56e38eed42},
{1, 0, 0, 0, 0, 0, 0, 0, 0}},
{{0x007efd8330ad8bd6, 0x02465ed48047710b, 0x0034c6606b215e0c,
0x016ae30c53cbf839, 0x01fa17bd37161216, 0x018ead4e61ce8ab9,
0x005482ed5f5dee46, 0x037543755bba1d7f, 0x005e5ac7e70a9d0f},
{0x0117e1bb2fdcb2a2, 0x03deea36249f40c4, 0x028d09b4a6246cb7,
0x03524b8855bcf756, 0x023d7d109d5ceb58, 0x0178e43e3223ef9c,
0x0154536a0c6e966a, 0x037964d1286ee9fe, 0x0199bcd90e125055},
{1, 0, 0, 0, 0, 0, 0, 0, 0}}
};
/*
* select_point selects the |idx|th point from a precomputation table and
* copies it to out.
*/
/* pre_comp below is of the size provided in |size| */
static void select_point(const limb idx, unsigned int size,
const felem pre_comp[][3], felem out[3])
{
unsigned i, j;
limb *outlimbs = &out[0][0];
memset(out, 0, sizeof(*out) * 3);
for (i = 0; i < size; i++) {
const limb *inlimbs = &pre_comp[i][0][0];
limb mask = i ^ idx;
mask |= mask >> 4;
mask |= mask >> 2;
mask |= mask >> 1;
mask &= 1;
mask--;
for (j = 0; j < NLIMBS * 3; j++)
outlimbs[j] |= inlimbs[j] & mask;
}
}
/* get_bit returns the |i|th bit in |in| */
static char get_bit(const felem_bytearray in, int i)
{
if (i < 0)
return 0;
return (in[i >> 3] >> (i & 7)) & 1;
}
/*
* Interleaved point multiplication using precomputed point multiples: The
* small point multiples 0*P, 1*P, ..., 16*P are in pre_comp[], the scalars
* in scalars[]. If g_scalar is non-NULL, we also add this multiple of the
* generator, using certain (large) precomputed multiples in g_pre_comp.
* Output point (X, Y, Z) is stored in x_out, y_out, z_out
*/
static void batch_mul(felem x_out, felem y_out, felem z_out,
const felem_bytearray scalars[],
const unsigned num_points, const u8 *g_scalar,
const int mixed, const felem pre_comp[][17][3],
const felem g_pre_comp[16][3])
{
int i, skip;
unsigned num, gen_mul = (g_scalar != NULL);
felem nq[3], tmp[4];
limb bits;
u8 sign, digit;
/* set nq to the point at infinity */
memset(nq, 0, sizeof(nq));
/*
* Loop over all scalars msb-to-lsb, interleaving additions of multiples
* of the generator (last quarter of rounds) and additions of other
* points multiples (every 5th round).
*/
skip = 1; /* save two point operations in the first
* round */
for (i = (num_points ? 520 : 130); i >= 0; --i) {
/* double */
if (!skip)
point_double(nq[0], nq[1], nq[2], nq[0], nq[1], nq[2]);
/* add multiples of the generator */
if (gen_mul && (i <= 130)) {
bits = get_bit(g_scalar, i + 390) << 3;
if (i < 130) {
bits |= get_bit(g_scalar, i + 260) << 2;
bits |= get_bit(g_scalar, i + 130) << 1;
bits |= get_bit(g_scalar, i);
}
/* select the point to add, in constant time */
select_point(bits, 16, g_pre_comp, tmp);
if (!skip) {
/* The 1 argument below is for "mixed" */
point_add(nq[0], nq[1], nq[2],
nq[0], nq[1], nq[2], 1, tmp[0], tmp[1], tmp[2]);
} else {
memcpy(nq, tmp, 3 * sizeof(felem));
skip = 0;
}
}
/* do other additions every 5 doublings */
if (num_points && (i % 5 == 0)) {
/* loop over all scalars */
for (num = 0; num < num_points; ++num) {
bits = get_bit(scalars[num], i + 4) << 5;
bits |= get_bit(scalars[num], i + 3) << 4;
bits |= get_bit(scalars[num], i + 2) << 3;
bits |= get_bit(scalars[num], i + 1) << 2;
bits |= get_bit(scalars[num], i) << 1;
bits |= get_bit(scalars[num], i - 1);
ec_GFp_nistp_recode_scalar_bits(&sign, &digit, bits);
/*
* select the point to add or subtract, in constant time
*/
select_point(digit, 17, pre_comp[num], tmp);
felem_neg(tmp[3], tmp[1]); /* (X, -Y, Z) is the negative
* point */
copy_conditional(tmp[1], tmp[3], (-(limb) sign));
if (!skip) {
point_add(nq[0], nq[1], nq[2],
nq[0], nq[1], nq[2],
mixed, tmp[0], tmp[1], tmp[2]);
} else {
memcpy(nq, tmp, 3 * sizeof(felem));
skip = 0;
}
}
}
}
felem_assign(x_out, nq[0]);
felem_assign(y_out, nq[1]);
felem_assign(z_out, nq[2]);
}
/* Precomputation for the group generator. */
struct nistp521_pre_comp_st {
felem g_pre_comp[16][3];
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
const EC_METHOD *EC_GFp_nistp521_method(void)
{
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
ec_GFp_nistp521_group_init,
ec_GFp_simple_group_finish,
ec_GFp_simple_group_clear_finish,
ec_GFp_nist_group_copy,
ec_GFp_nistp521_group_set_curve,
ec_GFp_simple_group_get_curve,
ec_GFp_simple_group_get_degree,
ec_group_simple_order_bits,
ec_GFp_simple_group_check_discriminant,
ec_GFp_simple_point_init,
ec_GFp_simple_point_finish,
ec_GFp_simple_point_clear_finish,
ec_GFp_simple_point_copy,
ec_GFp_simple_point_set_to_infinity,
ec_GFp_simple_set_Jprojective_coordinates_GFp,
ec_GFp_simple_get_Jprojective_coordinates_GFp,
ec_GFp_simple_point_set_affine_coordinates,
ec_GFp_nistp521_point_get_affine_coordinates,
0 /* point_set_compressed_coordinates */ ,
0 /* point2oct */ ,
0 /* oct2point */ ,
ec_GFp_simple_add,
ec_GFp_simple_dbl,
ec_GFp_simple_invert,
ec_GFp_simple_is_at_infinity,
ec_GFp_simple_is_on_curve,
ec_GFp_simple_cmp,
ec_GFp_simple_make_affine,
ec_GFp_simple_points_make_affine,
ec_GFp_nistp521_points_mul,
ec_GFp_nistp521_precompute_mult,
ec_GFp_nistp521_have_precompute_mult,
ec_GFp_nist_field_mul,
ec_GFp_nist_field_sqr,
0 /* field_div */ ,
ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
ec_key_simple_priv2oct,
ec_key_simple_oct2priv,
0, /* set private */
ec_key_simple_generate_key,
ec_key_simple_check_key,
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
0, /* field_inverse_mod_ord */
0, /* blind_coordinates */
0, /* ladder_pre */
0, /* ladder_step */
0 /* ladder_post */
};
return &ret;
}
/******************************************************************************/
/*
* FUNCTIONS TO MANAGE PRECOMPUTATION
*/
static NISTP521_PRE_COMP *nistp521_pre_comp_new(void)
{
NISTP521_PRE_COMP *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
return ret;
}
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
ECerr(EC_F_NISTP521_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
return ret;
}
NISTP521_PRE_COMP *EC_nistp521_pre_comp_dup(NISTP521_PRE_COMP *p)
{
int i;
if (p != NULL)
CRYPTO_UP_REF(&p->references, &i, p->lock);
return p;
}
void EC_nistp521_pre_comp_free(NISTP521_PRE_COMP *p)
{
int i;
if (p == NULL)
return;
CRYPTO_DOWN_REF(&p->references, &i, p->lock);
REF_PRINT_COUNT("EC_nistp521", x);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
CRYPTO_THREAD_lock_free(p->lock);
OPENSSL_free(p);
}
/******************************************************************************/
/*
* OPENSSL EC_METHOD FUNCTIONS
*/
int ec_GFp_nistp521_group_init(EC_GROUP *group)
{
int ret;
ret = ec_GFp_simple_group_init(group);
group->a_is_minus3 = 1;
return ret;
}
int ec_GFp_nistp521_group_set_curve(EC_GROUP *group, const BIGNUM *p,
const BIGNUM *a, const BIGNUM *b,
BN_CTX *ctx)
{
int ret = 0;
BN_CTX *new_ctx = NULL;
BIGNUM *curve_p, *curve_a, *curve_b;
if (ctx == NULL)
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
return 0;
BN_CTX_start(ctx);
curve_p = BN_CTX_get(ctx);
curve_a = BN_CTX_get(ctx);
curve_b = BN_CTX_get(ctx);
if (curve_b == NULL)
goto err;
BN_bin2bn(nistp521_curve_params[0], sizeof(felem_bytearray), curve_p);
BN_bin2bn(nistp521_curve_params[1], sizeof(felem_bytearray), curve_a);
BN_bin2bn(nistp521_curve_params[2], sizeof(felem_bytearray), curve_b);
if ((BN_cmp(curve_p, p)) || (BN_cmp(curve_a, a)) || (BN_cmp(curve_b, b))) {
ECerr(EC_F_EC_GFP_NISTP521_GROUP_SET_CURVE,
EC_R_WRONG_CURVE_PARAMETERS);
goto err;
}
group->field_mod_func = BN_nist_mod_521;
ret = ec_GFp_simple_group_set_curve(group, p, a, b, ctx);
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/*
* Takes the Jacobian coordinates (X, Y, Z) of a point and returns (X', Y') =
* (X/Z^2, Y/Z^3)
*/
int ec_GFp_nistp521_point_get_affine_coordinates(const EC_GROUP *group,
const EC_POINT *point,
BIGNUM *x, BIGNUM *y,
BN_CTX *ctx)
{
felem z1, z2, x_in, y_in, x_out, y_out;
largefelem tmp;
if (EC_POINT_is_at_infinity(group, point)) {
ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES,
EC_R_POINT_AT_INFINITY);
return 0;
}
if ((!BN_to_felem(x_in, point->X)) || (!BN_to_felem(y_in, point->Y)) ||
(!BN_to_felem(z1, point->Z)))
return 0;
felem_inv(z2, z1);
felem_square(tmp, z2);
felem_reduce(z1, tmp);
felem_mul(tmp, x_in, z1);
felem_reduce(x_in, tmp);
felem_contract(x_out, x_in);
if (x != NULL) {
if (!felem_to_BN(x, x_out)) {
ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES,
ERR_R_BN_LIB);
return 0;
}
}
felem_mul(tmp, z1, z2);
felem_reduce(z1, tmp);
felem_mul(tmp, y_in, z1);
felem_reduce(y_in, tmp);
felem_contract(y_out, y_in);
if (y != NULL) {
if (!felem_to_BN(y, y_out)) {
ECerr(EC_F_EC_GFP_NISTP521_POINT_GET_AFFINE_COORDINATES,
ERR_R_BN_LIB);
return 0;
}
}
return 1;
}
/* points below is of size |num|, and tmp_felems is of size |num+1/ */
static void make_points_affine(size_t num, felem points[][3],
felem tmp_felems[])
{
/*
* Runs in constant time, unless an input is the point at infinity (which
* normally shouldn't happen).
*/
ec_GFp_nistp_points_make_affine_internal(num,
points,
sizeof(felem),
tmp_felems,
(void (*)(void *))felem_one,
felem_is_zero_int,
(void (*)(void *, const void *))
felem_assign,
(void (*)(void *, const void *))
felem_square_reduce, (void (*)
(void *,
const void
*,
const void
*))
felem_mul_reduce,
(void (*)(void *, const void *))
felem_inv,
(void (*)(void *, const void *))
felem_contract);
}
/*
* Computes scalar*generator + \sum scalars[i]*points[i], ignoring NULL
* values Result is stored in r (r can equal one of the inputs).
*/
int ec_GFp_nistp521_points_mul(const EC_GROUP *group, EC_POINT *r,
const BIGNUM *scalar, size_t num,
const EC_POINT *points[],
const BIGNUM *scalars[], BN_CTX *ctx)
{
int ret = 0;
int j;
int mixed = 0;
BIGNUM *x, *y, *z, *tmp_scalar;
felem_bytearray g_secret;
felem_bytearray *secrets = NULL;
felem (*pre_comp)[17][3] = NULL;
felem *tmp_felems = NULL;
felem_bytearray tmp;
unsigned i, num_bytes;
int have_pre_comp = 0;
size_t num_points = num;
felem x_in, y_in, z_in, x_out, y_out, z_out;
NISTP521_PRE_COMP *pre = NULL;
felem(*g_pre_comp)[3] = NULL;
EC_POINT *generator = NULL;
const EC_POINT *p = NULL;
const BIGNUM *p_scalar = NULL;
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
z = BN_CTX_get(ctx);
tmp_scalar = BN_CTX_get(ctx);
if (tmp_scalar == NULL)
goto err;
if (scalar != NULL) {
pre = group->pre_comp.nistp521;
if (pre)
/* we have precomputation, try to use it */
g_pre_comp = &pre->g_pre_comp[0];
else
/* try to use the standard precomputation */
g_pre_comp = (felem(*)[3]) gmul;
generator = EC_POINT_new(group);
if (generator == NULL)
goto err;
/* get the generator from precomputation */
if (!felem_to_BN(x, g_pre_comp[1][0]) ||
!felem_to_BN(y, g_pre_comp[1][1]) ||
!felem_to_BN(z, g_pre_comp[1][2])) {
ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
goto err;
}
if (!EC_POINT_set_Jprojective_coordinates_GFp(group,
generator, x, y, z,
ctx))
goto err;
if (0 == EC_POINT_cmp(group, generator, group->generator, ctx))
/* precomputation matches generator */
have_pre_comp = 1;
else
/*
* we don't have valid precomputation: treat the generator as a
* random point
*/
num_points++;
}
if (num_points > 0) {
if (num_points >= 2) {
/*
* unless we precompute multiples for just one point, converting
* those into affine form is time well spent
*/
mixed = 1;
}
secrets = OPENSSL_zalloc(sizeof(*secrets) * num_points);
pre_comp = OPENSSL_zalloc(sizeof(*pre_comp) * num_points);
if (mixed)
tmp_felems =
OPENSSL_malloc(sizeof(*tmp_felems) * (num_points * 17 + 1));
if ((secrets == NULL) || (pre_comp == NULL)
|| (mixed && (tmp_felems == NULL))) {
ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* we treat NULL scalars as 0, and NULL points as points at infinity,
* i.e., they contribute nothing to the linear combination
*/
for (i = 0; i < num_points; ++i) {
if (i == num)
/*
* we didn't have a valid precomputation, so we pick the
* generator
*/
{
p = EC_GROUP_get0_generator(group);
p_scalar = scalar;
} else
/* the i^th point */
{
p = points[i];
p_scalar = scalars[i];
}
if ((p_scalar != NULL) && (p != NULL)) {
/* reduce scalar to 0 <= scalar < 2^521 */
if ((BN_num_bits(p_scalar) > 521)
|| (BN_is_negative(p_scalar))) {
/*
* this is an unusual input, and we don't guarantee
* constant-timeness
*/
if (!BN_nnmod(tmp_scalar, p_scalar, group->order, ctx)) {
ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
goto err;
}
num_bytes = BN_bn2bin(tmp_scalar, tmp);
} else
num_bytes = BN_bn2bin(p_scalar, tmp);
flip_endian(secrets[i], tmp, num_bytes);
/* precompute multiples */
if ((!BN_to_felem(x_out, p->X)) ||
(!BN_to_felem(y_out, p->Y)) ||
(!BN_to_felem(z_out, p->Z)))
goto err;
memcpy(pre_comp[i][1][0], x_out, sizeof(felem));
memcpy(pre_comp[i][1][1], y_out, sizeof(felem));
memcpy(pre_comp[i][1][2], z_out, sizeof(felem));
for (j = 2; j <= 16; ++j) {
if (j & 1) {
point_add(pre_comp[i][j][0], pre_comp[i][j][1],
pre_comp[i][j][2], pre_comp[i][1][0],
pre_comp[i][1][1], pre_comp[i][1][2], 0,
pre_comp[i][j - 1][0],
pre_comp[i][j - 1][1],
pre_comp[i][j - 1][2]);
} else {
point_double(pre_comp[i][j][0], pre_comp[i][j][1],
pre_comp[i][j][2], pre_comp[i][j / 2][0],
pre_comp[i][j / 2][1],
pre_comp[i][j / 2][2]);
}
}
}
}
if (mixed)
make_points_affine(num_points * 17, pre_comp[0], tmp_felems);
}
/* the scalar for the generator */
if ((scalar != NULL) && (have_pre_comp)) {
memset(g_secret, 0, sizeof(g_secret));
/* reduce scalar to 0 <= scalar < 2^521 */
if ((BN_num_bits(scalar) > 521) || (BN_is_negative(scalar))) {
/*
* this is an unusual input, and we don't guarantee
* constant-timeness
*/
if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) {
ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
goto err;
}
num_bytes = BN_bn2bin(tmp_scalar, tmp);
} else
num_bytes = BN_bn2bin(scalar, tmp);
flip_endian(g_secret, tmp, num_bytes);
/* do the multiplication with generator precomputation */
batch_mul(x_out, y_out, z_out,
(const felem_bytearray(*))secrets, num_points,
g_secret,
mixed, (const felem(*)[17][3])pre_comp,
(const felem(*)[3])g_pre_comp);
} else
/* do the multiplication without generator precomputation */
batch_mul(x_out, y_out, z_out,
(const felem_bytearray(*))secrets, num_points,
NULL, mixed, (const felem(*)[17][3])pre_comp, NULL);
/* reduce the output to its unique minimal representation */
felem_contract(x_in, x_out);
felem_contract(y_in, y_out);
felem_contract(z_in, z_out);
if ((!felem_to_BN(x, x_in)) || (!felem_to_BN(y, y_in)) ||
(!felem_to_BN(z, z_in))) {
ECerr(EC_F_EC_GFP_NISTP521_POINTS_MUL, ERR_R_BN_LIB);
goto err;
}
ret = EC_POINT_set_Jprojective_coordinates_GFp(group, r, x, y, z, ctx);
err:
BN_CTX_end(ctx);
EC_POINT_free(generator);
OPENSSL_free(secrets);
OPENSSL_free(pre_comp);
OPENSSL_free(tmp_felems);
return ret;
}
int ec_GFp_nistp521_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
{
int ret = 0;
NISTP521_PRE_COMP *pre = NULL;
int i, j;
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
EC_POINT *generator = NULL;
felem tmp_felems[16];
/* throw away old precomputation */
EC_pre_comp_free(group);
if (ctx == NULL)
if ((ctx = new_ctx = BN_CTX_new()) == NULL)
return 0;
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
if (y == NULL)
goto err;
/* get the generator */
if (group->generator == NULL)
goto err;
generator = EC_POINT_new(group);
if (generator == NULL)
goto err;
BN_bin2bn(nistp521_curve_params[3], sizeof(felem_bytearray), x);
BN_bin2bn(nistp521_curve_params[4], sizeof(felem_bytearray), y);
if (!EC_POINT_set_affine_coordinates(group, generator, x, y, ctx))
goto err;
if ((pre = nistp521_pre_comp_new()) == NULL)
goto err;
/*
* if the generator is the standard one, use built-in precomputation
*/
if (0 == EC_POINT_cmp(group, generator, group->generator, ctx)) {
memcpy(pre->g_pre_comp, gmul, sizeof(pre->g_pre_comp));
goto done;
}
if ((!BN_to_felem(pre->g_pre_comp[1][0], group->generator->X)) ||
(!BN_to_felem(pre->g_pre_comp[1][1], group->generator->Y)) ||
(!BN_to_felem(pre->g_pre_comp[1][2], group->generator->Z)))
goto err;
/* compute 2^130*G, 2^260*G, 2^390*G */
for (i = 1; i <= 4; i <<= 1) {
point_double(pre->g_pre_comp[2 * i][0], pre->g_pre_comp[2 * i][1],
pre->g_pre_comp[2 * i][2], pre->g_pre_comp[i][0],
pre->g_pre_comp[i][1], pre->g_pre_comp[i][2]);
for (j = 0; j < 129; ++j) {
point_double(pre->g_pre_comp[2 * i][0],
pre->g_pre_comp[2 * i][1],
pre->g_pre_comp[2 * i][2],
pre->g_pre_comp[2 * i][0],
pre->g_pre_comp[2 * i][1],
pre->g_pre_comp[2 * i][2]);
}
}
/* g_pre_comp[0] is the point at infinity */
memset(pre->g_pre_comp[0], 0, sizeof(pre->g_pre_comp[0]));
/* the remaining multiples */
/* 2^130*G + 2^260*G */
point_add(pre->g_pre_comp[6][0], pre->g_pre_comp[6][1],
pre->g_pre_comp[6][2], pre->g_pre_comp[4][0],
pre->g_pre_comp[4][1], pre->g_pre_comp[4][2],
0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
pre->g_pre_comp[2][2]);
/* 2^130*G + 2^390*G */
point_add(pre->g_pre_comp[10][0], pre->g_pre_comp[10][1],
pre->g_pre_comp[10][2], pre->g_pre_comp[8][0],
pre->g_pre_comp[8][1], pre->g_pre_comp[8][2],
0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
pre->g_pre_comp[2][2]);
/* 2^260*G + 2^390*G */
point_add(pre->g_pre_comp[12][0], pre->g_pre_comp[12][1],
pre->g_pre_comp[12][2], pre->g_pre_comp[8][0],
pre->g_pre_comp[8][1], pre->g_pre_comp[8][2],
0, pre->g_pre_comp[4][0], pre->g_pre_comp[4][1],
pre->g_pre_comp[4][2]);
/* 2^130*G + 2^260*G + 2^390*G */
point_add(pre->g_pre_comp[14][0], pre->g_pre_comp[14][1],
pre->g_pre_comp[14][2], pre->g_pre_comp[12][0],
pre->g_pre_comp[12][1], pre->g_pre_comp[12][2],
0, pre->g_pre_comp[2][0], pre->g_pre_comp[2][1],
pre->g_pre_comp[2][2]);
for (i = 1; i < 8; ++i) {
/* odd multiples: add G */
point_add(pre->g_pre_comp[2 * i + 1][0],
pre->g_pre_comp[2 * i + 1][1],
pre->g_pre_comp[2 * i + 1][2], pre->g_pre_comp[2 * i][0],
pre->g_pre_comp[2 * i][1], pre->g_pre_comp[2 * i][2], 0,
pre->g_pre_comp[1][0], pre->g_pre_comp[1][1],
pre->g_pre_comp[1][2]);
}
make_points_affine(15, &(pre->g_pre_comp[1]), tmp_felems);
done:
SETPRECOMP(group, nistp521, pre);
ret = 1;
pre = NULL;
err:
BN_CTX_end(ctx);
EC_POINT_free(generator);
BN_CTX_free(new_ctx);
EC_nistp521_pre_comp_free(pre);
return ret;
}
int ec_GFp_nistp521_have_precompute_mult(const EC_GROUP *group)
{
return HAVEPRECOMP(group, nistp521);
}
#endif
diff --git a/crypto/ec/ecp_nistz256.c b/crypto/ec/ecp_nistz256.c
index aea6394169ce..7ad5eb627de1 100644
--- a/crypto/ec/ecp_nistz256.c
+++ b/crypto/ec/ecp_nistz256.c
@@ -1,1701 +1,1700 @@
/*
* Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2014, Intel Corporation. All Rights Reserved.
* Copyright (c) 2015, CloudFlare, Inc.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*
* Originally written by Shay Gueron (1, 2), and Vlad Krasnov (1, 3)
* (1) Intel Corporation, Israel Development Center, Haifa, Israel
* (2) University of Haifa, Israel
* (3) CloudFlare, Inc.
*
* Reference:
* S.Gueron and V.Krasnov, "Fast Prime Field Elliptic Curve Cryptography with
* 256 Bit Primes"
*/
#include <string.h>
#include "internal/cryptlib.h"
#include "internal/bn_int.h"
#include "ec_lcl.h"
#include "internal/refcount.h"
#if BN_BITS2 != 64
# define TOBN(hi,lo) lo,hi
#else
# define TOBN(hi,lo) ((BN_ULONG)hi<<32|lo)
#endif
#if defined(__GNUC__)
# define ALIGN32 __attribute((aligned(32)))
#elif defined(_MSC_VER)
# define ALIGN32 __declspec(align(32))
#else
# define ALIGN32
#endif
#define ALIGNPTR(p,N) ((unsigned char *)p+N-(size_t)p%N)
#define P256_LIMBS (256/BN_BITS2)
typedef unsigned short u16;
typedef struct {
BN_ULONG X[P256_LIMBS];
BN_ULONG Y[P256_LIMBS];
BN_ULONG Z[P256_LIMBS];
} P256_POINT;
typedef struct {
BN_ULONG X[P256_LIMBS];
BN_ULONG Y[P256_LIMBS];
} P256_POINT_AFFINE;
typedef P256_POINT_AFFINE PRECOMP256_ROW[64];
/* structure for precomputed multiples of the generator */
struct nistz256_pre_comp_st {
const EC_GROUP *group; /* Parent EC_GROUP object */
size_t w; /* Window size */
/*
* Constant time access to the X and Y coordinates of the pre-computed,
* generator multiplies, in the Montgomery domain. Pre-calculated
* multiplies are stored in affine form.
*/
PRECOMP256_ROW *precomp;
void *precomp_storage;
CRYPTO_REF_COUNT references;
CRYPTO_RWLOCK *lock;
};
/* Functions implemented in assembly */
/*
* Most of below mentioned functions *preserve* the property of inputs
* being fully reduced, i.e. being in [0, modulus) range. Simply put if
* inputs are fully reduced, then output is too. Note that reverse is
* not true, in sense that given partially reduced inputs output can be
* either, not unlikely reduced. And "most" in first sentence refers to
* the fact that given the calculations flow one can tolerate that
* addition, 1st function below, produces partially reduced result *if*
* multiplications by 2 and 3, which customarily use addition, fully
* reduce it. This effectively gives two options: a) addition produces
* fully reduced result [as long as inputs are, just like remaining
* functions]; b) addition is allowed to produce partially reduced
* result, but multiplications by 2 and 3 perform additional reduction
* step. Choice between the two can be platform-specific, but it was a)
* in all cases so far...
*/
/* Modular add: res = a+b mod P */
void ecp_nistz256_add(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS],
const BN_ULONG b[P256_LIMBS]);
/* Modular mul by 2: res = 2*a mod P */
void ecp_nistz256_mul_by_2(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS]);
/* Modular mul by 3: res = 3*a mod P */
void ecp_nistz256_mul_by_3(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS]);
/* Modular div by 2: res = a/2 mod P */
void ecp_nistz256_div_by_2(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS]);
/* Modular sub: res = a-b mod P */
void ecp_nistz256_sub(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS],
const BN_ULONG b[P256_LIMBS]);
/* Modular neg: res = -a mod P */
void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]);
/* Montgomery mul: res = a*b*2^-256 mod P */
void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS],
const BN_ULONG b[P256_LIMBS]);
/* Montgomery sqr: res = a*a*2^-256 mod P */
void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS]);
/* Convert a number from Montgomery domain, by multiplying with 1 */
void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG in[P256_LIMBS]);
/* Convert a number to Montgomery domain, by multiplying with 2^512 mod P*/
void ecp_nistz256_to_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG in[P256_LIMBS]);
/* Functions that perform constant time access to the precomputed tables */
void ecp_nistz256_scatter_w5(P256_POINT *val,
const P256_POINT *in_t, int idx);
void ecp_nistz256_gather_w5(P256_POINT *val,
const P256_POINT *in_t, int idx);
void ecp_nistz256_scatter_w7(P256_POINT_AFFINE *val,
const P256_POINT_AFFINE *in_t, int idx);
void ecp_nistz256_gather_w7(P256_POINT_AFFINE *val,
const P256_POINT_AFFINE *in_t, int idx);
/* One converted into the Montgomery domain */
static const BN_ULONG ONE[P256_LIMBS] = {
TOBN(0x00000000, 0x00000001), TOBN(0xffffffff, 0x00000000),
TOBN(0xffffffff, 0xffffffff), TOBN(0x00000000, 0xfffffffe)
};
static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group);
/* Precomputed tables for the default generator */
extern const PRECOMP256_ROW ecp_nistz256_precomputed[37];
/* Recode window to a signed digit, see ecp_nistputil.c for details */
static unsigned int _booth_recode_w5(unsigned int in)
{
unsigned int s, d;
s = ~((in >> 5) - 1);
d = (1 << 6) - in - 1;
d = (d & s) | (in & ~s);
d = (d >> 1) + (d & 1);
return (d << 1) + (s & 1);
}
static unsigned int _booth_recode_w7(unsigned int in)
{
unsigned int s, d;
s = ~((in >> 7) - 1);
d = (1 << 8) - in - 1;
d = (d & s) | (in & ~s);
d = (d >> 1) + (d & 1);
return (d << 1) + (s & 1);
}
static void copy_conditional(BN_ULONG dst[P256_LIMBS],
const BN_ULONG src[P256_LIMBS], BN_ULONG move)
{
BN_ULONG mask1 = 0-move;
BN_ULONG mask2 = ~mask1;
dst[0] = (src[0] & mask1) ^ (dst[0] & mask2);
dst[1] = (src[1] & mask1) ^ (dst[1] & mask2);
dst[2] = (src[2] & mask1) ^ (dst[2] & mask2);
dst[3] = (src[3] & mask1) ^ (dst[3] & mask2);
if (P256_LIMBS == 8) {
dst[4] = (src[4] & mask1) ^ (dst[4] & mask2);
dst[5] = (src[5] & mask1) ^ (dst[5] & mask2);
dst[6] = (src[6] & mask1) ^ (dst[6] & mask2);
dst[7] = (src[7] & mask1) ^ (dst[7] & mask2);
}
}
static BN_ULONG is_zero(BN_ULONG in)
{
in |= (0 - in);
in = ~in;
in >>= BN_BITS2 - 1;
return in;
}
static BN_ULONG is_equal(const BN_ULONG a[P256_LIMBS],
const BN_ULONG b[P256_LIMBS])
{
BN_ULONG res;
res = a[0] ^ b[0];
res |= a[1] ^ b[1];
res |= a[2] ^ b[2];
res |= a[3] ^ b[3];
if (P256_LIMBS == 8) {
res |= a[4] ^ b[4];
res |= a[5] ^ b[5];
res |= a[6] ^ b[6];
res |= a[7] ^ b[7];
}
return is_zero(res);
}
static BN_ULONG is_one(const BIGNUM *z)
{
BN_ULONG res = 0;
BN_ULONG *a = bn_get_words(z);
if (bn_get_top(z) == (P256_LIMBS - P256_LIMBS / 8)) {
res = a[0] ^ ONE[0];
res |= a[1] ^ ONE[1];
res |= a[2] ^ ONE[2];
res |= a[3] ^ ONE[3];
if (P256_LIMBS == 8) {
res |= a[4] ^ ONE[4];
res |= a[5] ^ ONE[5];
res |= a[6] ^ ONE[6];
/*
* no check for a[7] (being zero) on 32-bit platforms,
* because value of "one" takes only 7 limbs.
*/
}
res = is_zero(res);
}
return res;
}
/*
* For reference, this macro is used only when new ecp_nistz256 assembly
* module is being developed. For example, configure with
* -DECP_NISTZ256_REFERENCE_IMPLEMENTATION and implement only functions
* performing simplest arithmetic operations on 256-bit vectors. Then
* work on implementation of higher-level functions performing point
* operations. Then remove ECP_NISTZ256_REFERENCE_IMPLEMENTATION
* and never define it again. (The correct macro denoting presence of
* ecp_nistz256 module is ECP_NISTZ256_ASM.)
*/
#ifndef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a);
void ecp_nistz256_point_add(P256_POINT *r,
const P256_POINT *a, const P256_POINT *b);
void ecp_nistz256_point_add_affine(P256_POINT *r,
const P256_POINT *a,
const P256_POINT_AFFINE *b);
#else
/* Point double: r = 2*a */
static void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a)
{
BN_ULONG S[P256_LIMBS];
BN_ULONG M[P256_LIMBS];
BN_ULONG Zsqr[P256_LIMBS];
BN_ULONG tmp0[P256_LIMBS];
const BN_ULONG *in_x = a->X;
const BN_ULONG *in_y = a->Y;
const BN_ULONG *in_z = a->Z;
BN_ULONG *res_x = r->X;
BN_ULONG *res_y = r->Y;
BN_ULONG *res_z = r->Z;
ecp_nistz256_mul_by_2(S, in_y);
ecp_nistz256_sqr_mont(Zsqr, in_z);
ecp_nistz256_sqr_mont(S, S);
ecp_nistz256_mul_mont(res_z, in_z, in_y);
ecp_nistz256_mul_by_2(res_z, res_z);
ecp_nistz256_add(M, in_x, Zsqr);
ecp_nistz256_sub(Zsqr, in_x, Zsqr);
ecp_nistz256_sqr_mont(res_y, S);
ecp_nistz256_div_by_2(res_y, res_y);
ecp_nistz256_mul_mont(M, M, Zsqr);
ecp_nistz256_mul_by_3(M, M);
ecp_nistz256_mul_mont(S, S, in_x);
ecp_nistz256_mul_by_2(tmp0, S);
ecp_nistz256_sqr_mont(res_x, M);
ecp_nistz256_sub(res_x, res_x, tmp0);
ecp_nistz256_sub(S, S, res_x);
ecp_nistz256_mul_mont(S, S, M);
ecp_nistz256_sub(res_y, S, res_y);
}
/* Point addition: r = a+b */
static void ecp_nistz256_point_add(P256_POINT *r,
const P256_POINT *a, const P256_POINT *b)
{
BN_ULONG U2[P256_LIMBS], S2[P256_LIMBS];
BN_ULONG U1[P256_LIMBS], S1[P256_LIMBS];
BN_ULONG Z1sqr[P256_LIMBS];
BN_ULONG Z2sqr[P256_LIMBS];
BN_ULONG H[P256_LIMBS], R[P256_LIMBS];
BN_ULONG Hsqr[P256_LIMBS];
BN_ULONG Rsqr[P256_LIMBS];
BN_ULONG Hcub[P256_LIMBS];
BN_ULONG res_x[P256_LIMBS];
BN_ULONG res_y[P256_LIMBS];
BN_ULONG res_z[P256_LIMBS];
BN_ULONG in1infty, in2infty;
const BN_ULONG *in1_x = a->X;
const BN_ULONG *in1_y = a->Y;
const BN_ULONG *in1_z = a->Z;
const BN_ULONG *in2_x = b->X;
const BN_ULONG *in2_y = b->Y;
const BN_ULONG *in2_z = b->Z;
/*
* Infinity in encoded as (,,0)
*/
in1infty = (in1_z[0] | in1_z[1] | in1_z[2] | in1_z[3]);
if (P256_LIMBS == 8)
in1infty |= (in1_z[4] | in1_z[5] | in1_z[6] | in1_z[7]);
in2infty = (in2_z[0] | in2_z[1] | in2_z[2] | in2_z[3]);
if (P256_LIMBS == 8)
in2infty |= (in2_z[4] | in2_z[5] | in2_z[6] | in2_z[7]);
in1infty = is_zero(in1infty);
in2infty = is_zero(in2infty);
ecp_nistz256_sqr_mont(Z2sqr, in2_z); /* Z2^2 */
ecp_nistz256_sqr_mont(Z1sqr, in1_z); /* Z1^2 */
ecp_nistz256_mul_mont(S1, Z2sqr, in2_z); /* S1 = Z2^3 */
ecp_nistz256_mul_mont(S2, Z1sqr, in1_z); /* S2 = Z1^3 */
ecp_nistz256_mul_mont(S1, S1, in1_y); /* S1 = Y1*Z2^3 */
ecp_nistz256_mul_mont(S2, S2, in2_y); /* S2 = Y2*Z1^3 */
ecp_nistz256_sub(R, S2, S1); /* R = S2 - S1 */
ecp_nistz256_mul_mont(U1, in1_x, Z2sqr); /* U1 = X1*Z2^2 */
ecp_nistz256_mul_mont(U2, in2_x, Z1sqr); /* U2 = X2*Z1^2 */
ecp_nistz256_sub(H, U2, U1); /* H = U2 - U1 */
/*
* This should not happen during sign/ecdh, so no constant time violation
*/
if (is_equal(U1, U2) && !in1infty && !in2infty) {
if (is_equal(S1, S2)) {
ecp_nistz256_point_double(r, a);
return;
} else {
memset(r, 0, sizeof(*r));
return;
}
}
ecp_nistz256_sqr_mont(Rsqr, R); /* R^2 */
ecp_nistz256_mul_mont(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */
ecp_nistz256_sqr_mont(Hsqr, H); /* H^2 */
ecp_nistz256_mul_mont(res_z, res_z, in2_z); /* Z3 = H*Z1*Z2 */
ecp_nistz256_mul_mont(Hcub, Hsqr, H); /* H^3 */
ecp_nistz256_mul_mont(U2, U1, Hsqr); /* U1*H^2 */
ecp_nistz256_mul_by_2(Hsqr, U2); /* 2*U1*H^2 */
ecp_nistz256_sub(res_x, Rsqr, Hsqr);
ecp_nistz256_sub(res_x, res_x, Hcub);
ecp_nistz256_sub(res_y, U2, res_x);
ecp_nistz256_mul_mont(S2, S1, Hcub);
ecp_nistz256_mul_mont(res_y, R, res_y);
ecp_nistz256_sub(res_y, res_y, S2);
copy_conditional(res_x, in2_x, in1infty);
copy_conditional(res_y, in2_y, in1infty);
copy_conditional(res_z, in2_z, in1infty);
copy_conditional(res_x, in1_x, in2infty);
copy_conditional(res_y, in1_y, in2infty);
copy_conditional(res_z, in1_z, in2infty);
memcpy(r->X, res_x, sizeof(res_x));
memcpy(r->Y, res_y, sizeof(res_y));
memcpy(r->Z, res_z, sizeof(res_z));
}
/* Point addition when b is known to be affine: r = a+b */
static void ecp_nistz256_point_add_affine(P256_POINT *r,
const P256_POINT *a,
const P256_POINT_AFFINE *b)
{
BN_ULONG U2[P256_LIMBS], S2[P256_LIMBS];
BN_ULONG Z1sqr[P256_LIMBS];
BN_ULONG H[P256_LIMBS], R[P256_LIMBS];
BN_ULONG Hsqr[P256_LIMBS];
BN_ULONG Rsqr[P256_LIMBS];
BN_ULONG Hcub[P256_LIMBS];
BN_ULONG res_x[P256_LIMBS];
BN_ULONG res_y[P256_LIMBS];
BN_ULONG res_z[P256_LIMBS];
BN_ULONG in1infty, in2infty;
const BN_ULONG *in1_x = a->X;
const BN_ULONG *in1_y = a->Y;
const BN_ULONG *in1_z = a->Z;
const BN_ULONG *in2_x = b->X;
const BN_ULONG *in2_y = b->Y;
/*
* Infinity in encoded as (,,0)
*/
in1infty = (in1_z[0] | in1_z[1] | in1_z[2] | in1_z[3]);
if (P256_LIMBS == 8)
in1infty |= (in1_z[4] | in1_z[5] | in1_z[6] | in1_z[7]);
/*
* In affine representation we encode infinity as (0,0), which is
* not on the curve, so it is OK
*/
in2infty = (in2_x[0] | in2_x[1] | in2_x[2] | in2_x[3] |
in2_y[0] | in2_y[1] | in2_y[2] | in2_y[3]);
if (P256_LIMBS == 8)
in2infty |= (in2_x[4] | in2_x[5] | in2_x[6] | in2_x[7] |
in2_y[4] | in2_y[5] | in2_y[6] | in2_y[7]);
in1infty = is_zero(in1infty);
in2infty = is_zero(in2infty);
ecp_nistz256_sqr_mont(Z1sqr, in1_z); /* Z1^2 */
ecp_nistz256_mul_mont(U2, in2_x, Z1sqr); /* U2 = X2*Z1^2 */
ecp_nistz256_sub(H, U2, in1_x); /* H = U2 - U1 */
ecp_nistz256_mul_mont(S2, Z1sqr, in1_z); /* S2 = Z1^3 */
ecp_nistz256_mul_mont(res_z, H, in1_z); /* Z3 = H*Z1*Z2 */
ecp_nistz256_mul_mont(S2, S2, in2_y); /* S2 = Y2*Z1^3 */
ecp_nistz256_sub(R, S2, in1_y); /* R = S2 - S1 */
ecp_nistz256_sqr_mont(Hsqr, H); /* H^2 */
ecp_nistz256_sqr_mont(Rsqr, R); /* R^2 */
ecp_nistz256_mul_mont(Hcub, Hsqr, H); /* H^3 */
ecp_nistz256_mul_mont(U2, in1_x, Hsqr); /* U1*H^2 */
ecp_nistz256_mul_by_2(Hsqr, U2); /* 2*U1*H^2 */
ecp_nistz256_sub(res_x, Rsqr, Hsqr);
ecp_nistz256_sub(res_x, res_x, Hcub);
ecp_nistz256_sub(H, U2, res_x);
ecp_nistz256_mul_mont(S2, in1_y, Hcub);
ecp_nistz256_mul_mont(H, H, R);
ecp_nistz256_sub(res_y, H, S2);
copy_conditional(res_x, in2_x, in1infty);
copy_conditional(res_x, in1_x, in2infty);
copy_conditional(res_y, in2_y, in1infty);
copy_conditional(res_y, in1_y, in2infty);
copy_conditional(res_z, ONE, in1infty);
copy_conditional(res_z, in1_z, in2infty);
memcpy(r->X, res_x, sizeof(res_x));
memcpy(r->Y, res_y, sizeof(res_y));
memcpy(r->Z, res_z, sizeof(res_z));
}
#endif
/* r = in^-1 mod p */
static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS],
const BN_ULONG in[P256_LIMBS])
{
/*
* The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff
* ffffffff ffffffff We use FLT and used poly-2 as exponent
*/
BN_ULONG p2[P256_LIMBS];
BN_ULONG p4[P256_LIMBS];
BN_ULONG p8[P256_LIMBS];
BN_ULONG p16[P256_LIMBS];
BN_ULONG p32[P256_LIMBS];
BN_ULONG res[P256_LIMBS];
int i;
ecp_nistz256_sqr_mont(res, in);
ecp_nistz256_mul_mont(p2, res, in); /* 3*p */
ecp_nistz256_sqr_mont(res, p2);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(p4, res, p2); /* f*p */
ecp_nistz256_sqr_mont(res, p4);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(p8, res, p4); /* ff*p */
ecp_nistz256_sqr_mont(res, p8);
for (i = 0; i < 7; i++)
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(p16, res, p8); /* ffff*p */
ecp_nistz256_sqr_mont(res, p16);
for (i = 0; i < 15; i++)
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(p32, res, p16); /* ffffffff*p */
ecp_nistz256_sqr_mont(res, p32);
for (i = 0; i < 31; i++)
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(res, res, in);
for (i = 0; i < 32 * 4; i++)
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(res, res, p32);
for (i = 0; i < 32; i++)
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(res, res, p32);
for (i = 0; i < 16; i++)
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(res, res, p16);
for (i = 0; i < 8; i++)
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(res, res, p8);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(res, res, p4);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(res, res, p2);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_sqr_mont(res, res);
ecp_nistz256_mul_mont(res, res, in);
memcpy(r, res, sizeof(res));
}
/*
* ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and
* returns one if it fits. Otherwise it returns zero.
*/
__owur static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS],
const BIGNUM *in)
{
return bn_copy_words(out, in, P256_LIMBS);
}
/* r = sum(scalar[i]*point[i]) */
__owur static int ecp_nistz256_windowed_mul(const EC_GROUP *group,
P256_POINT *r,
const BIGNUM **scalar,
const EC_POINT **point,
size_t num, BN_CTX *ctx)
{
size_t i;
int j, ret = 0;
unsigned int idx;
unsigned char (*p_str)[33] = NULL;
const unsigned int window_size = 5;
const unsigned int mask = (1 << (window_size + 1)) - 1;
unsigned int wvalue;
P256_POINT *temp; /* place for 5 temporary points */
const BIGNUM **scalars = NULL;
P256_POINT (*table)[16] = NULL;
void *table_storage = NULL;
if ((num * 16 + 6) > OPENSSL_MALLOC_MAX_NELEMS(P256_POINT)
|| (table_storage =
OPENSSL_malloc((num * 16 + 5) * sizeof(P256_POINT) + 64)) == NULL
|| (p_str =
OPENSSL_malloc(num * 33 * sizeof(unsigned char))) == NULL
|| (scalars = OPENSSL_malloc(num * sizeof(BIGNUM *))) == NULL) {
ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, ERR_R_MALLOC_FAILURE);
goto err;
}
table = (void *)ALIGNPTR(table_storage, 64);
temp = (P256_POINT *)(table + num);
for (i = 0; i < num; i++) {
P256_POINT *row = table[i];
/* This is an unusual input, we don't guarantee constant-timeness. */
if ((BN_num_bits(scalar[i]) > 256) || BN_is_negative(scalar[i])) {
BIGNUM *mod;
if ((mod = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_nnmod(mod, scalar[i], group->order, ctx)) {
ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL, ERR_R_BN_LIB);
goto err;
}
scalars[i] = mod;
} else
scalars[i] = scalar[i];
for (j = 0; j < bn_get_top(scalars[i]) * BN_BYTES; j += BN_BYTES) {
BN_ULONG d = bn_get_words(scalars[i])[j / BN_BYTES];
p_str[i][j + 0] = (unsigned char)d;
p_str[i][j + 1] = (unsigned char)(d >> 8);
p_str[i][j + 2] = (unsigned char)(d >> 16);
p_str[i][j + 3] = (unsigned char)(d >>= 24);
if (BN_BYTES == 8) {
d >>= 8;
p_str[i][j + 4] = (unsigned char)d;
p_str[i][j + 5] = (unsigned char)(d >> 8);
p_str[i][j + 6] = (unsigned char)(d >> 16);
p_str[i][j + 7] = (unsigned char)(d >> 24);
}
}
for (; j < 33; j++)
p_str[i][j] = 0;
if (!ecp_nistz256_bignum_to_field_elem(temp[0].X, point[i]->X)
|| !ecp_nistz256_bignum_to_field_elem(temp[0].Y, point[i]->Y)
|| !ecp_nistz256_bignum_to_field_elem(temp[0].Z, point[i]->Z)) {
ECerr(EC_F_ECP_NISTZ256_WINDOWED_MUL,
EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
/*
* row[0] is implicitly (0,0,0) (the point at infinity), therefore it
* is not stored. All other values are actually stored with an offset
* of -1 in table.
*/
ecp_nistz256_scatter_w5 (row, &temp[0], 1);
ecp_nistz256_point_double(&temp[1], &temp[0]); /*1+1=2 */
ecp_nistz256_scatter_w5 (row, &temp[1], 2);
ecp_nistz256_point_add (&temp[2], &temp[1], &temp[0]); /*2+1=3 */
ecp_nistz256_scatter_w5 (row, &temp[2], 3);
ecp_nistz256_point_double(&temp[1], &temp[1]); /*2*2=4 */
ecp_nistz256_scatter_w5 (row, &temp[1], 4);
ecp_nistz256_point_double(&temp[2], &temp[2]); /*2*3=6 */
ecp_nistz256_scatter_w5 (row, &temp[2], 6);
ecp_nistz256_point_add (&temp[3], &temp[1], &temp[0]); /*4+1=5 */
ecp_nistz256_scatter_w5 (row, &temp[3], 5);
ecp_nistz256_point_add (&temp[4], &temp[2], &temp[0]); /*6+1=7 */
ecp_nistz256_scatter_w5 (row, &temp[4], 7);
ecp_nistz256_point_double(&temp[1], &temp[1]); /*2*4=8 */
ecp_nistz256_scatter_w5 (row, &temp[1], 8);
ecp_nistz256_point_double(&temp[2], &temp[2]); /*2*6=12 */
ecp_nistz256_scatter_w5 (row, &temp[2], 12);
ecp_nistz256_point_double(&temp[3], &temp[3]); /*2*5=10 */
ecp_nistz256_scatter_w5 (row, &temp[3], 10);
ecp_nistz256_point_double(&temp[4], &temp[4]); /*2*7=14 */
ecp_nistz256_scatter_w5 (row, &temp[4], 14);
ecp_nistz256_point_add (&temp[2], &temp[2], &temp[0]); /*12+1=13*/
ecp_nistz256_scatter_w5 (row, &temp[2], 13);
ecp_nistz256_point_add (&temp[3], &temp[3], &temp[0]); /*10+1=11*/
ecp_nistz256_scatter_w5 (row, &temp[3], 11);
ecp_nistz256_point_add (&temp[4], &temp[4], &temp[0]); /*14+1=15*/
ecp_nistz256_scatter_w5 (row, &temp[4], 15);
ecp_nistz256_point_add (&temp[2], &temp[1], &temp[0]); /*8+1=9 */
ecp_nistz256_scatter_w5 (row, &temp[2], 9);
ecp_nistz256_point_double(&temp[1], &temp[1]); /*2*8=16 */
ecp_nistz256_scatter_w5 (row, &temp[1], 16);
}
idx = 255;
wvalue = p_str[0][(idx - 1) / 8];
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
/*
* We gather to temp[0], because we know it's position relative
* to table
*/
ecp_nistz256_gather_w5(&temp[0], table[0], _booth_recode_w5(wvalue) >> 1);
memcpy(r, &temp[0], sizeof(temp[0]));
while (idx >= 5) {
for (i = (idx == 255 ? 1 : 0); i < num; i++) {
unsigned int off = (idx - 1) / 8;
wvalue = p_str[i][off] | p_str[i][off + 1] << 8;
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
wvalue = _booth_recode_w5(wvalue);
ecp_nistz256_gather_w5(&temp[0], table[i], wvalue >> 1);
ecp_nistz256_neg(temp[1].Y, temp[0].Y);
copy_conditional(temp[0].Y, temp[1].Y, (wvalue & 1));
ecp_nistz256_point_add(r, r, &temp[0]);
}
idx -= window_size;
ecp_nistz256_point_double(r, r);
ecp_nistz256_point_double(r, r);
ecp_nistz256_point_double(r, r);
ecp_nistz256_point_double(r, r);
ecp_nistz256_point_double(r, r);
}
/* Final window */
for (i = 0; i < num; i++) {
wvalue = p_str[i][0];
wvalue = (wvalue << 1) & mask;
wvalue = _booth_recode_w5(wvalue);
ecp_nistz256_gather_w5(&temp[0], table[i], wvalue >> 1);
ecp_nistz256_neg(temp[1].Y, temp[0].Y);
copy_conditional(temp[0].Y, temp[1].Y, wvalue & 1);
ecp_nistz256_point_add(r, r, &temp[0]);
}
ret = 1;
err:
OPENSSL_free(table_storage);
OPENSSL_free(p_str);
OPENSSL_free(scalars);
return ret;
}
/* Coordinates of G, for which we have precomputed tables */
static const BN_ULONG def_xG[P256_LIMBS] = {
TOBN(0x79e730d4, 0x18a9143c), TOBN(0x75ba95fc, 0x5fedb601),
TOBN(0x79fb732b, 0x77622510), TOBN(0x18905f76, 0xa53755c6)
};
static const BN_ULONG def_yG[P256_LIMBS] = {
TOBN(0xddf25357, 0xce95560a), TOBN(0x8b4ab8e4, 0xba19e45c),
TOBN(0xd2e88688, 0xdd21f325), TOBN(0x8571ff18, 0x25885d85)
};
/*
* ecp_nistz256_is_affine_G returns one if |generator| is the standard, P-256
* generator.
*/
static int ecp_nistz256_is_affine_G(const EC_POINT *generator)
{
return (bn_get_top(generator->X) == P256_LIMBS) &&
(bn_get_top(generator->Y) == P256_LIMBS) &&
is_equal(bn_get_words(generator->X), def_xG) &&
is_equal(bn_get_words(generator->Y), def_yG) &&
is_one(generator->Z);
}
__owur static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
{
/*
* We precompute a table for a Booth encoded exponent (wNAF) based
* computation. Each table holds 64 values for safe access, with an
* implicit value of infinity at index zero. We use window of size 7, and
* therefore require ceil(256/7) = 37 tables.
*/
const BIGNUM *order;
EC_POINT *P = NULL, *T = NULL;
const EC_POINT *generator;
NISTZ256_PRE_COMP *pre_comp;
BN_CTX *new_ctx = NULL;
int i, j, k, ret = 0;
size_t w;
PRECOMP256_ROW *preComputedTable = NULL;
unsigned char *precomp_storage = NULL;
/* if there is an old NISTZ256_PRE_COMP object, throw it away */
EC_pre_comp_free(group);
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, EC_R_UNDEFINED_GENERATOR);
return 0;
}
if (ecp_nistz256_is_affine_G(generator)) {
/*
* No need to calculate tables for the standard generator because we
* have them statically.
*/
return 1;
}
if ((pre_comp = ecp_nistz256_pre_comp_new(group)) == NULL)
return 0;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
}
BN_CTX_start(ctx);
order = EC_GROUP_get0_order(group);
if (order == NULL)
goto err;
if (BN_is_zero(order)) {
ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, EC_R_UNKNOWN_ORDER);
goto err;
}
w = 7;
if ((precomp_storage =
OPENSSL_malloc(37 * 64 * sizeof(P256_POINT_AFFINE) + 64)) == NULL) {
ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE, ERR_R_MALLOC_FAILURE);
goto err;
}
preComputedTable = (void *)ALIGNPTR(precomp_storage, 64);
P = EC_POINT_new(group);
T = EC_POINT_new(group);
if (P == NULL || T == NULL)
goto err;
/*
* The zero entry is implicitly infinity, and we skip it, storing other
* values with -1 offset.
*/
if (!EC_POINT_copy(T, generator))
goto err;
for (k = 0; k < 64; k++) {
if (!EC_POINT_copy(P, T))
goto err;
for (j = 0; j < 37; j++) {
P256_POINT_AFFINE temp;
/*
* It would be faster to use EC_POINTs_make_affine and
* make multiple points affine at the same time.
*/
if (!EC_POINT_make_affine(group, P, ctx))
goto err;
if (!ecp_nistz256_bignum_to_field_elem(temp.X, P->X) ||
!ecp_nistz256_bignum_to_field_elem(temp.Y, P->Y)) {
ECerr(EC_F_ECP_NISTZ256_MULT_PRECOMPUTE,
EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
ecp_nistz256_scatter_w7(preComputedTable[j], &temp, k);
for (i = 0; i < 7; i++) {
if (!EC_POINT_dbl(group, P, P, ctx))
goto err;
}
}
if (!EC_POINT_add(group, T, T, generator, ctx))
goto err;
}
pre_comp->group = group;
pre_comp->w = w;
pre_comp->precomp = preComputedTable;
pre_comp->precomp_storage = precomp_storage;
precomp_storage = NULL;
SETPRECOMP(group, nistz256, pre_comp);
pre_comp = NULL;
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
EC_nistz256_pre_comp_free(pre_comp);
OPENSSL_free(precomp_storage);
EC_POINT_free(P);
EC_POINT_free(T);
return ret;
}
/*
* Note that by default ECP_NISTZ256_AVX2 is undefined. While it's great
* code processing 4 points in parallel, corresponding serial operation
* is several times slower, because it uses 29x29=58-bit multiplication
* as opposite to 64x64=128-bit in integer-only scalar case. As result
* it doesn't provide *significant* performance improvement. Note that
* just defining ECP_NISTZ256_AVX2 is not sufficient to make it work,
* you'd need to compile even asm/ecp_nistz256-avx.pl module.
*/
#if defined(ECP_NISTZ256_AVX2)
# if !(defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64)) || \
!(defined(__GNUC__) || defined(_MSC_VER)) /* this is for ALIGN32 */
# undef ECP_NISTZ256_AVX2
# else
/* Constant time access, loading four values, from four consecutive tables */
void ecp_nistz256_avx2_multi_gather_w7(void *result, const void *in,
int index0, int index1, int index2,
int index3);
void ecp_nistz256_avx2_transpose_convert(void *RESULTx4, const void *in);
void ecp_nistz256_avx2_convert_transpose_back(void *result, const void *Ax4);
void ecp_nistz256_avx2_point_add_affine_x4(void *RESULTx4, const void *Ax4,
const void *Bx4);
void ecp_nistz256_avx2_point_add_affines_x4(void *RESULTx4, const void *Ax4,
const void *Bx4);
void ecp_nistz256_avx2_to_mont(void *RESULTx4, const void *Ax4);
void ecp_nistz256_avx2_from_mont(void *RESULTx4, const void *Ax4);
void ecp_nistz256_avx2_set1(void *RESULTx4);
int ecp_nistz_avx2_eligible(void);
static void booth_recode_w7(unsigned char *sign,
unsigned char *digit, unsigned char in)
{
unsigned char s, d;
s = ~((in >> 7) - 1);
d = (1 << 8) - in - 1;
d = (d & s) | (in & ~s);
d = (d >> 1) + (d & 1);
*sign = s & 1;
*digit = d;
}
/*
* ecp_nistz256_avx2_mul_g performs multiplication by G, using only the
* precomputed table. It does 4 affine point additions in parallel,
* significantly speeding up point multiplication for a fixed value.
*/
static void ecp_nistz256_avx2_mul_g(P256_POINT *r,
unsigned char p_str[33],
const P256_POINT_AFFINE(*preComputedTable)[64])
{
const unsigned int window_size = 7;
const unsigned int mask = (1 << (window_size + 1)) - 1;
unsigned int wvalue;
/* Using 4 windows at a time */
unsigned char sign0, digit0;
unsigned char sign1, digit1;
unsigned char sign2, digit2;
unsigned char sign3, digit3;
unsigned int idx = 0;
BN_ULONG tmp[P256_LIMBS];
int i;
ALIGN32 BN_ULONG aX4[4 * 9 * 3] = { 0 };
ALIGN32 BN_ULONG bX4[4 * 9 * 2] = { 0 };
ALIGN32 P256_POINT_AFFINE point_arr[4];
ALIGN32 P256_POINT res_point_arr[4];
/* Initial four windows */
wvalue = *((u16 *) & p_str[0]);
wvalue = (wvalue << 1) & mask;
idx += window_size;
booth_recode_w7(&sign0, &digit0, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign1, &digit1, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign2, &digit2, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign3, &digit3, wvalue);
ecp_nistz256_avx2_multi_gather_w7(point_arr, preComputedTable[0],
digit0, digit1, digit2, digit3);
ecp_nistz256_neg(tmp, point_arr[0].Y);
copy_conditional(point_arr[0].Y, tmp, sign0);
ecp_nistz256_neg(tmp, point_arr[1].Y);
copy_conditional(point_arr[1].Y, tmp, sign1);
ecp_nistz256_neg(tmp, point_arr[2].Y);
copy_conditional(point_arr[2].Y, tmp, sign2);
ecp_nistz256_neg(tmp, point_arr[3].Y);
copy_conditional(point_arr[3].Y, tmp, sign3);
ecp_nistz256_avx2_transpose_convert(aX4, point_arr);
ecp_nistz256_avx2_to_mont(aX4, aX4);
ecp_nistz256_avx2_to_mont(&aX4[4 * 9], &aX4[4 * 9]);
ecp_nistz256_avx2_set1(&aX4[4 * 9 * 2]);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign0, &digit0, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign1, &digit1, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign2, &digit2, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign3, &digit3, wvalue);
ecp_nistz256_avx2_multi_gather_w7(point_arr, preComputedTable[4 * 1],
digit0, digit1, digit2, digit3);
ecp_nistz256_neg(tmp, point_arr[0].Y);
copy_conditional(point_arr[0].Y, tmp, sign0);
ecp_nistz256_neg(tmp, point_arr[1].Y);
copy_conditional(point_arr[1].Y, tmp, sign1);
ecp_nistz256_neg(tmp, point_arr[2].Y);
copy_conditional(point_arr[2].Y, tmp, sign2);
ecp_nistz256_neg(tmp, point_arr[3].Y);
copy_conditional(point_arr[3].Y, tmp, sign3);
ecp_nistz256_avx2_transpose_convert(bX4, point_arr);
ecp_nistz256_avx2_to_mont(bX4, bX4);
ecp_nistz256_avx2_to_mont(&bX4[4 * 9], &bX4[4 * 9]);
/* Optimized when both inputs are affine */
ecp_nistz256_avx2_point_add_affines_x4(aX4, aX4, bX4);
for (i = 2; i < 9; i++) {
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign0, &digit0, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign1, &digit1, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign2, &digit2, wvalue);
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
booth_recode_w7(&sign3, &digit3, wvalue);
ecp_nistz256_avx2_multi_gather_w7(point_arr,
preComputedTable[4 * i],
digit0, digit1, digit2, digit3);
ecp_nistz256_neg(tmp, point_arr[0].Y);
copy_conditional(point_arr[0].Y, tmp, sign0);
ecp_nistz256_neg(tmp, point_arr[1].Y);
copy_conditional(point_arr[1].Y, tmp, sign1);
ecp_nistz256_neg(tmp, point_arr[2].Y);
copy_conditional(point_arr[2].Y, tmp, sign2);
ecp_nistz256_neg(tmp, point_arr[3].Y);
copy_conditional(point_arr[3].Y, tmp, sign3);
ecp_nistz256_avx2_transpose_convert(bX4, point_arr);
ecp_nistz256_avx2_to_mont(bX4, bX4);
ecp_nistz256_avx2_to_mont(&bX4[4 * 9], &bX4[4 * 9]);
ecp_nistz256_avx2_point_add_affine_x4(aX4, aX4, bX4);
}
ecp_nistz256_avx2_from_mont(&aX4[4 * 9 * 0], &aX4[4 * 9 * 0]);
ecp_nistz256_avx2_from_mont(&aX4[4 * 9 * 1], &aX4[4 * 9 * 1]);
ecp_nistz256_avx2_from_mont(&aX4[4 * 9 * 2], &aX4[4 * 9 * 2]);
ecp_nistz256_avx2_convert_transpose_back(res_point_arr, aX4);
/* Last window is performed serially */
wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
booth_recode_w7(&sign0, &digit0, wvalue);
ecp_nistz256_gather_w7((P256_POINT_AFFINE *)r,
preComputedTable[36], digit0);
ecp_nistz256_neg(tmp, r->Y);
copy_conditional(r->Y, tmp, sign0);
memcpy(r->Z, ONE, sizeof(ONE));
/* Sum the four windows */
ecp_nistz256_point_add(r, r, &res_point_arr[0]);
ecp_nistz256_point_add(r, r, &res_point_arr[1]);
ecp_nistz256_point_add(r, r, &res_point_arr[2]);
ecp_nistz256_point_add(r, r, &res_point_arr[3]);
}
# endif
#endif
__owur static int ecp_nistz256_set_from_affine(EC_POINT *out, const EC_GROUP *group,
const P256_POINT_AFFINE *in,
BN_CTX *ctx)
{
int ret = 0;
if ((ret = bn_set_words(out->X, in->X, P256_LIMBS))
&& (ret = bn_set_words(out->Y, in->Y, P256_LIMBS))
&& (ret = bn_set_words(out->Z, ONE, P256_LIMBS)))
out->Z_is_one = 1;
return ret;
}
/* r = scalar*G + sum(scalars[i]*points[i]) */
__owur static int ecp_nistz256_points_mul(const EC_GROUP *group,
EC_POINT *r,
const BIGNUM *scalar,
size_t num,
const EC_POINT *points[],
const BIGNUM *scalars[], BN_CTX *ctx)
{
int i = 0, ret = 0, no_precomp_for_generator = 0, p_is_infinity = 0;
unsigned char p_str[33] = { 0 };
const PRECOMP256_ROW *preComputedTable = NULL;
const NISTZ256_PRE_COMP *pre_comp = NULL;
const EC_POINT *generator = NULL;
const BIGNUM **new_scalars = NULL;
const EC_POINT **new_points = NULL;
unsigned int idx = 0;
const unsigned int window_size = 7;
const unsigned int mask = (1 << (window_size + 1)) - 1;
unsigned int wvalue;
ALIGN32 union {
P256_POINT p;
P256_POINT_AFFINE a;
} t, p;
BIGNUM *tmp_scalar;
if ((num + 1) == 0 || (num + 1) > OPENSSL_MALLOC_MAX_NELEMS(void *)) {
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
return 0;
}
BN_CTX_start(ctx);
if (scalar) {
generator = EC_GROUP_get0_generator(group);
if (generator == NULL) {
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_UNDEFINED_GENERATOR);
goto err;
}
/* look if we can use precomputed multiples of generator */
pre_comp = group->pre_comp.nistz256;
if (pre_comp) {
/*
* If there is a precomputed table for the generator, check that
* it was generated with the same generator.
*/
EC_POINT *pre_comp_generator = EC_POINT_new(group);
if (pre_comp_generator == NULL)
goto err;
ecp_nistz256_gather_w7(&p.a, pre_comp->precomp[0], 1);
if (!ecp_nistz256_set_from_affine(pre_comp_generator,
group, &p.a, ctx)) {
EC_POINT_free(pre_comp_generator);
goto err;
}
if (0 == EC_POINT_cmp(group, generator, pre_comp_generator, ctx))
preComputedTable = (const PRECOMP256_ROW *)pre_comp->precomp;
EC_POINT_free(pre_comp_generator);
}
if (preComputedTable == NULL && ecp_nistz256_is_affine_G(generator)) {
/*
* If there is no precomputed data, but the generator is the
* default, a hardcoded table of precomputed data is used. This
* is because applications, such as Apache, do not use
* EC_KEY_precompute_mult.
*/
preComputedTable = ecp_nistz256_precomputed;
}
if (preComputedTable) {
if ((BN_num_bits(scalar) > 256)
|| BN_is_negative(scalar)) {
if ((tmp_scalar = BN_CTX_get(ctx)) == NULL)
goto err;
if (!BN_nnmod(tmp_scalar, scalar, group->order, ctx)) {
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_BN_LIB);
goto err;
}
scalar = tmp_scalar;
}
for (i = 0; i < bn_get_top(scalar) * BN_BYTES; i += BN_BYTES) {
BN_ULONG d = bn_get_words(scalar)[i / BN_BYTES];
p_str[i + 0] = (unsigned char)d;
p_str[i + 1] = (unsigned char)(d >> 8);
p_str[i + 2] = (unsigned char)(d >> 16);
p_str[i + 3] = (unsigned char)(d >>= 24);
if (BN_BYTES == 8) {
d >>= 8;
p_str[i + 4] = (unsigned char)d;
p_str[i + 5] = (unsigned char)(d >> 8);
p_str[i + 6] = (unsigned char)(d >> 16);
p_str[i + 7] = (unsigned char)(d >> 24);
}
}
for (; i < 33; i++)
p_str[i] = 0;
#if defined(ECP_NISTZ256_AVX2)
if (ecp_nistz_avx2_eligible()) {
ecp_nistz256_avx2_mul_g(&p.p, p_str, preComputedTable);
} else
#endif
{
BN_ULONG infty;
/* First window */
wvalue = (p_str[0] << 1) & mask;
idx += window_size;
wvalue = _booth_recode_w7(wvalue);
ecp_nistz256_gather_w7(&p.a, preComputedTable[0],
wvalue >> 1);
ecp_nistz256_neg(p.p.Z, p.p.Y);
copy_conditional(p.p.Y, p.p.Z, wvalue & 1);
/*
* Since affine infinity is encoded as (0,0) and
* Jacobian ias (,,0), we need to harmonize them
* by assigning "one" or zero to Z.
*/
infty = (p.p.X[0] | p.p.X[1] | p.p.X[2] | p.p.X[3] |
p.p.Y[0] | p.p.Y[1] | p.p.Y[2] | p.p.Y[3]);
if (P256_LIMBS == 8)
infty |= (p.p.X[4] | p.p.X[5] | p.p.X[6] | p.p.X[7] |
p.p.Y[4] | p.p.Y[5] | p.p.Y[6] | p.p.Y[7]);
infty = 0 - is_zero(infty);
infty = ~infty;
p.p.Z[0] = ONE[0] & infty;
p.p.Z[1] = ONE[1] & infty;
p.p.Z[2] = ONE[2] & infty;
p.p.Z[3] = ONE[3] & infty;
if (P256_LIMBS == 8) {
p.p.Z[4] = ONE[4] & infty;
p.p.Z[5] = ONE[5] & infty;
p.p.Z[6] = ONE[6] & infty;
p.p.Z[7] = ONE[7] & infty;
}
for (i = 1; i < 37; i++) {
unsigned int off = (idx - 1) / 8;
wvalue = p_str[off] | p_str[off + 1] << 8;
wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
idx += window_size;
wvalue = _booth_recode_w7(wvalue);
ecp_nistz256_gather_w7(&t.a,
preComputedTable[i], wvalue >> 1);
ecp_nistz256_neg(t.p.Z, t.a.Y);
copy_conditional(t.a.Y, t.p.Z, wvalue & 1);
ecp_nistz256_point_add_affine(&p.p, &p.p, &t.a);
}
}
} else {
p_is_infinity = 1;
no_precomp_for_generator = 1;
}
} else
p_is_infinity = 1;
if (no_precomp_for_generator) {
/*
* Without a precomputed table for the generator, it has to be
* handled like a normal point.
*/
new_scalars = OPENSSL_malloc((num + 1) * sizeof(BIGNUM *));
if (new_scalars == NULL) {
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
goto err;
}
new_points = OPENSSL_malloc((num + 1) * sizeof(EC_POINT *));
if (new_points == NULL) {
ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
goto err;
}
memcpy(new_scalars, scalars, num * sizeof(BIGNUM *));
new_scalars[num] = scalar;
memcpy(new_points, points, num * sizeof(EC_POINT *));
new_points[num] = generator;
scalars = new_scalars;
points = new_points;
num++;
}
if (num) {
P256_POINT *out = &t.p;
if (p_is_infinity)
out = &p.p;
if (!ecp_nistz256_windowed_mul(group, out, scalars, points, num, ctx))
goto err;
if (!p_is_infinity)
ecp_nistz256_point_add(&p.p, &p.p, out);
}
/* Not constant-time, but we're only operating on the public output. */
if (!bn_set_words(r->X, p.p.X, P256_LIMBS) ||
!bn_set_words(r->Y, p.p.Y, P256_LIMBS) ||
!bn_set_words(r->Z, p.p.Z, P256_LIMBS)) {
goto err;
}
r->Z_is_one = is_one(r->Z) & 1;
ret = 1;
err:
BN_CTX_end(ctx);
OPENSSL_free(new_points);
OPENSSL_free(new_scalars);
return ret;
}
__owur static int ecp_nistz256_get_affine(const EC_GROUP *group,
const EC_POINT *point,
BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
{
BN_ULONG z_inv2[P256_LIMBS];
BN_ULONG z_inv3[P256_LIMBS];
BN_ULONG x_aff[P256_LIMBS];
BN_ULONG y_aff[P256_LIMBS];
BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS];
BN_ULONG x_ret[P256_LIMBS], y_ret[P256_LIMBS];
if (EC_POINT_is_at_infinity(group, point)) {
ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_POINT_AT_INFINITY);
return 0;
}
if (!ecp_nistz256_bignum_to_field_elem(point_x, point->X) ||
!ecp_nistz256_bignum_to_field_elem(point_y, point->Y) ||
!ecp_nistz256_bignum_to_field_elem(point_z, point->Z)) {
ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_COORDINATES_OUT_OF_RANGE);
return 0;
}
ecp_nistz256_mod_inverse(z_inv3, point_z);
ecp_nistz256_sqr_mont(z_inv2, z_inv3);
ecp_nistz256_mul_mont(x_aff, z_inv2, point_x);
if (x != NULL) {
ecp_nistz256_from_mont(x_ret, x_aff);
if (!bn_set_words(x, x_ret, P256_LIMBS))
return 0;
}
if (y != NULL) {
ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2);
ecp_nistz256_mul_mont(y_aff, z_inv3, point_y);
ecp_nistz256_from_mont(y_ret, y_aff);
if (!bn_set_words(y, y_ret, P256_LIMBS))
return 0;
}
return 1;
}
static NISTZ256_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group)
{
NISTZ256_PRE_COMP *ret = NULL;
if (!group)
return NULL;
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
return ret;
}
ret->group = group;
ret->w = 6; /* default */
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
return ret;
}
NISTZ256_PRE_COMP *EC_nistz256_pre_comp_dup(NISTZ256_PRE_COMP *p)
{
int i;
if (p != NULL)
CRYPTO_UP_REF(&p->references, &i, p->lock);
return p;
}
void EC_nistz256_pre_comp_free(NISTZ256_PRE_COMP *pre)
{
int i;
if (pre == NULL)
return;
CRYPTO_DOWN_REF(&pre->references, &i, pre->lock);
REF_PRINT_COUNT("EC_nistz256", x);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
OPENSSL_free(pre->precomp_storage);
CRYPTO_THREAD_lock_free(pre->lock);
OPENSSL_free(pre);
}
static int ecp_nistz256_window_have_precompute_mult(const EC_GROUP *group)
{
/* There is a hard-coded table for the default generator. */
const EC_POINT *generator = EC_GROUP_get0_generator(group);
if (generator != NULL && ecp_nistz256_is_affine_G(generator)) {
/* There is a hard-coded table for the default generator. */
return 1;
}
return HAVEPRECOMP(group, nistz256);
}
#if defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) || \
defined(__powerpc64__) || defined(_ARCH_PP64) || \
defined(__aarch64__)
/*
* Montgomery mul modulo Order(P): res = a*b*2^-256 mod Order(P)
*/
void ecp_nistz256_ord_mul_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS],
const BN_ULONG b[P256_LIMBS]);
void ecp_nistz256_ord_sqr_mont(BN_ULONG res[P256_LIMBS],
const BN_ULONG a[P256_LIMBS],
int rep);
static int ecp_nistz256_inv_mod_ord(const EC_GROUP *group, BIGNUM *r,
const BIGNUM *x, BN_CTX *ctx)
{
/* RR = 2^512 mod ord(p256) */
static const BN_ULONG RR[P256_LIMBS] = {
TOBN(0x83244c95,0xbe79eea2), TOBN(0x4699799c,0x49bd6fa6),
TOBN(0x2845b239,0x2b6bec59), TOBN(0x66e12d94,0xf3d95620)
};
/* The constant 1 (unlike ONE that is one in Montgomery representation) */
static const BN_ULONG one[P256_LIMBS] = {
TOBN(0,1), TOBN(0,0), TOBN(0,0), TOBN(0,0)
};
/*
* We don't use entry 0 in the table, so we omit it and address
* with -1 offset.
*/
BN_ULONG table[15][P256_LIMBS];
BN_ULONG out[P256_LIMBS], t[P256_LIMBS];
int i, ret = 0;
enum {
i_1 = 0, i_10, i_11, i_101, i_111, i_1010, i_1111,
i_10101, i_101010, i_101111, i_x6, i_x8, i_x16, i_x32
};
/*
* Catch allocation failure early.
*/
if (bn_wexpand(r, P256_LIMBS) == NULL) {
ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB);
goto err;
}
if ((BN_num_bits(x) > 256) || BN_is_negative(x)) {
BIGNUM *tmp;
if ((tmp = BN_CTX_get(ctx)) == NULL
|| !BN_nnmod(tmp, x, group->order, ctx)) {
ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, ERR_R_BN_LIB);
goto err;
}
x = tmp;
}
if (!ecp_nistz256_bignum_to_field_elem(t, x)) {
ECerr(EC_F_ECP_NISTZ256_INV_MOD_ORD, EC_R_COORDINATES_OUT_OF_RANGE);
goto err;
}
ecp_nistz256_ord_mul_mont(table[0], t, RR);
#if 0
/*
* Original sparse-then-fixed-window algorithm, retained for reference.
*/
for (i = 2; i < 16; i += 2) {
ecp_nistz256_ord_sqr_mont(table[i-1], table[i/2-1], 1);
ecp_nistz256_ord_mul_mont(table[i], table[i-1], table[0]);
}
/*
* The top 128bit of the exponent are highly redudndant, so we
* perform an optimized flow
*/
ecp_nistz256_ord_sqr_mont(t, table[15-1], 4); /* f0 */
ecp_nistz256_ord_mul_mont(t, t, table[15-1]); /* ff */
ecp_nistz256_ord_sqr_mont(out, t, 8); /* ff00 */
ecp_nistz256_ord_mul_mont(out, out, t); /* ffff */
ecp_nistz256_ord_sqr_mont(t, out, 16); /* ffff0000 */
ecp_nistz256_ord_mul_mont(t, t, out); /* ffffffff */
ecp_nistz256_ord_sqr_mont(out, t, 64); /* ffffffff0000000000000000 */
ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffff */
ecp_nistz256_ord_sqr_mont(out, out, 32); /* ffffffff00000000ffffffff00000000 */
ecp_nistz256_ord_mul_mont(out, out, t); /* ffffffff00000000ffffffffffffffff */
/*
* The bottom 128 bit of the exponent are processed with fixed 4-bit window
*/
for(i = 0; i < 32; i++) {
/* expLo - the low 128 bits of the exponent we use (ord(p256) - 2),
* split into nibbles */
static const unsigned char expLo[32] = {
0xb,0xc,0xe,0x6,0xf,0xa,0xa,0xd,0xa,0x7,0x1,0x7,0x9,0xe,0x8,0x4,
0xf,0x3,0xb,0x9,0xc,0xa,0xc,0x2,0xf,0xc,0x6,0x3,0x2,0x5,0x4,0xf
};
ecp_nistz256_ord_sqr_mont(out, out, 4);
/* The exponent is public, no need in constant-time access */
ecp_nistz256_ord_mul_mont(out, out, table[expLo[i]-1]);
}
#else
/*
* https://briansmith.org/ecc-inversion-addition-chains-01#p256_scalar_inversion
*
* Even though this code path spares 12 squarings, 4.5%, and 13
* multiplications, 25%, on grand scale sign operation is not that
* much faster, not more that 2%...
*/
/* pre-calculate powers */
ecp_nistz256_ord_sqr_mont(table[i_10], table[i_1], 1);
ecp_nistz256_ord_mul_mont(table[i_11], table[i_1], table[i_10]);
ecp_nistz256_ord_mul_mont(table[i_101], table[i_11], table[i_10]);
ecp_nistz256_ord_mul_mont(table[i_111], table[i_101], table[i_10]);
ecp_nistz256_ord_sqr_mont(table[i_1010], table[i_101], 1);
ecp_nistz256_ord_mul_mont(table[i_1111], table[i_1010], table[i_101]);
ecp_nistz256_ord_sqr_mont(table[i_10101], table[i_1010], 1);
ecp_nistz256_ord_mul_mont(table[i_10101], table[i_10101], table[i_1]);
ecp_nistz256_ord_sqr_mont(table[i_101010], table[i_10101], 1);
ecp_nistz256_ord_mul_mont(table[i_101111], table[i_101010], table[i_101]);
ecp_nistz256_ord_mul_mont(table[i_x6], table[i_101010], table[i_10101]);
ecp_nistz256_ord_sqr_mont(table[i_x8], table[i_x6], 2);
ecp_nistz256_ord_mul_mont(table[i_x8], table[i_x8], table[i_11]);
ecp_nistz256_ord_sqr_mont(table[i_x16], table[i_x8], 8);
ecp_nistz256_ord_mul_mont(table[i_x16], table[i_x16], table[i_x8]);
ecp_nistz256_ord_sqr_mont(table[i_x32], table[i_x16], 16);
ecp_nistz256_ord_mul_mont(table[i_x32], table[i_x32], table[i_x16]);
/* calculations */
ecp_nistz256_ord_sqr_mont(out, table[i_x32], 64);
ecp_nistz256_ord_mul_mont(out, out, table[i_x32]);
for (i = 0; i < 27; i++) {
static const struct { unsigned char p, i; } chain[27] = {
{ 32, i_x32 }, { 6, i_101111 }, { 5, i_111 },
{ 4, i_11 }, { 5, i_1111 }, { 5, i_10101 },
{ 4, i_101 }, { 3, i_101 }, { 3, i_101 },
{ 5, i_111 }, { 9, i_101111 }, { 6, i_1111 },
{ 2, i_1 }, { 5, i_1 }, { 6, i_1111 },
{ 5, i_111 }, { 4, i_111 }, { 5, i_111 },
{ 5, i_101 }, { 3, i_11 }, { 10, i_101111 },
{ 2, i_11 }, { 5, i_11 }, { 5, i_11 },
{ 3, i_1 }, { 7, i_10101 }, { 6, i_1111 }
};
ecp_nistz256_ord_sqr_mont(out, out, chain[i].p);
ecp_nistz256_ord_mul_mont(out, out, table[chain[i].i]);
}
#endif
ecp_nistz256_ord_mul_mont(out, out, one);
/*
* Can't fail, but check return code to be consistent anyway.
*/
if (!bn_set_words(r, out, P256_LIMBS))
goto err;
ret = 1;
err:
return ret;
}
#else
# define ecp_nistz256_inv_mod_ord NULL
#endif
const EC_METHOD *EC_GFp_nistz256_method(void)
{
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
ec_GFp_mont_group_init,
ec_GFp_mont_group_finish,
ec_GFp_mont_group_clear_finish,
ec_GFp_mont_group_copy,
ec_GFp_mont_group_set_curve,
ec_GFp_simple_group_get_curve,
ec_GFp_simple_group_get_degree,
ec_group_simple_order_bits,
ec_GFp_simple_group_check_discriminant,
ec_GFp_simple_point_init,
ec_GFp_simple_point_finish,
ec_GFp_simple_point_clear_finish,
ec_GFp_simple_point_copy,
ec_GFp_simple_point_set_to_infinity,
ec_GFp_simple_set_Jprojective_coordinates_GFp,
ec_GFp_simple_get_Jprojective_coordinates_GFp,
ec_GFp_simple_point_set_affine_coordinates,
ecp_nistz256_get_affine,
0, 0, 0,
ec_GFp_simple_add,
ec_GFp_simple_dbl,
ec_GFp_simple_invert,
ec_GFp_simple_is_at_infinity,
ec_GFp_simple_is_on_curve,
ec_GFp_simple_cmp,
ec_GFp_simple_make_affine,
ec_GFp_simple_points_make_affine,
ecp_nistz256_points_mul, /* mul */
ecp_nistz256_mult_precompute, /* precompute_mult */
ecp_nistz256_window_have_precompute_mult, /* have_precompute_mult */
ec_GFp_mont_field_mul,
ec_GFp_mont_field_sqr,
0, /* field_div */
ec_GFp_mont_field_inv,
ec_GFp_mont_field_encode,
ec_GFp_mont_field_decode,
ec_GFp_mont_field_set_to_one,
ec_key_simple_priv2oct,
ec_key_simple_oct2priv,
0, /* set private */
ec_key_simple_generate_key,
ec_key_simple_check_key,
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
ecp_nistz256_inv_mod_ord, /* can be #define-d NULL */
0, /* blind_coordinates */
0, /* ladder_pre */
0, /* ladder_step */
0 /* ladder_post */
};
return &ret;
}
diff --git a/crypto/ec/ecp_smpl.c b/crypto/ec/ecp_smpl.c
index f6a6cedb0ae3..e6e4c9d2cbb7 100644
--- a/crypto/ec/ecp_smpl.c
+++ b/crypto/ec/ecp_smpl.c
@@ -1,1689 +1,1687 @@
/*
* Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/err.h>
#include <openssl/symhacks.h>
#include "ec_lcl.h"
const EC_METHOD *EC_GFp_simple_method(void)
{
static const EC_METHOD ret = {
EC_FLAGS_DEFAULT_OCT,
NID_X9_62_prime_field,
ec_GFp_simple_group_init,
ec_GFp_simple_group_finish,
ec_GFp_simple_group_clear_finish,
ec_GFp_simple_group_copy,
ec_GFp_simple_group_set_curve,
ec_GFp_simple_group_get_curve,
ec_GFp_simple_group_get_degree,
ec_group_simple_order_bits,
ec_GFp_simple_group_check_discriminant,
ec_GFp_simple_point_init,
ec_GFp_simple_point_finish,
ec_GFp_simple_point_clear_finish,
ec_GFp_simple_point_copy,
ec_GFp_simple_point_set_to_infinity,
ec_GFp_simple_set_Jprojective_coordinates_GFp,
ec_GFp_simple_get_Jprojective_coordinates_GFp,
ec_GFp_simple_point_set_affine_coordinates,
ec_GFp_simple_point_get_affine_coordinates,
0, 0, 0,
ec_GFp_simple_add,
ec_GFp_simple_dbl,
ec_GFp_simple_invert,
ec_GFp_simple_is_at_infinity,
ec_GFp_simple_is_on_curve,
ec_GFp_simple_cmp,
ec_GFp_simple_make_affine,
ec_GFp_simple_points_make_affine,
0 /* mul */ ,
0 /* precompute_mult */ ,
0 /* have_precompute_mult */ ,
ec_GFp_simple_field_mul,
ec_GFp_simple_field_sqr,
0 /* field_div */ ,
ec_GFp_simple_field_inv,
0 /* field_encode */ ,
0 /* field_decode */ ,
0, /* field_set_to_one */
ec_key_simple_priv2oct,
ec_key_simple_oct2priv,
0, /* set private */
ec_key_simple_generate_key,
ec_key_simple_check_key,
ec_key_simple_generate_public_key,
0, /* keycopy */
0, /* keyfinish */
ecdh_simple_compute_key,
0, /* field_inverse_mod_ord */
ec_GFp_simple_blind_coordinates,
ec_GFp_simple_ladder_pre,
ec_GFp_simple_ladder_step,
ec_GFp_simple_ladder_post
};
return &ret;
}
/*
* Most method functions in this file are designed to work with
* non-trivial representations of field elements if necessary
* (see ecp_mont.c): while standard modular addition and subtraction
* are used, the field_mul and field_sqr methods will be used for
* multiplication, and field_encode and field_decode (if defined)
* will be used for converting between representations.
*
* Functions ec_GFp_simple_points_make_affine() and
* ec_GFp_simple_point_get_affine_coordinates() specifically assume
* that if a non-trivial representation is used, it is a Montgomery
* representation (i.e. 'encoding' means multiplying by some factor R).
*/
int ec_GFp_simple_group_init(EC_GROUP *group)
{
group->field = BN_new();
group->a = BN_new();
group->b = BN_new();
if (group->field == NULL || group->a == NULL || group->b == NULL) {
BN_free(group->field);
BN_free(group->a);
BN_free(group->b);
return 0;
}
group->a_is_minus3 = 0;
return 1;
}
void ec_GFp_simple_group_finish(EC_GROUP *group)
{
BN_free(group->field);
BN_free(group->a);
BN_free(group->b);
}
void ec_GFp_simple_group_clear_finish(EC_GROUP *group)
{
BN_clear_free(group->field);
BN_clear_free(group->a);
BN_clear_free(group->b);
}
int ec_GFp_simple_group_copy(EC_GROUP *dest, const EC_GROUP *src)
{
if (!BN_copy(dest->field, src->field))
return 0;
if (!BN_copy(dest->a, src->a))
return 0;
if (!BN_copy(dest->b, src->b))
return 0;
dest->a_is_minus3 = src->a_is_minus3;
return 1;
}
int ec_GFp_simple_group_set_curve(EC_GROUP *group,
const BIGNUM *p, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
int ret = 0;
BN_CTX *new_ctx = NULL;
BIGNUM *tmp_a;
/* p must be a prime > 3 */
if (BN_num_bits(p) <= 2 || !BN_is_odd(p)) {
ECerr(EC_F_EC_GFP_SIMPLE_GROUP_SET_CURVE, EC_R_INVALID_FIELD);
return 0;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
tmp_a = BN_CTX_get(ctx);
if (tmp_a == NULL)
goto err;
/* group->field */
if (!BN_copy(group->field, p))
goto err;
BN_set_negative(group->field, 0);
/* group->a */
if (!BN_nnmod(tmp_a, a, p, ctx))
goto err;
if (group->meth->field_encode) {
if (!group->meth->field_encode(group, group->a, tmp_a, ctx))
goto err;
} else if (!BN_copy(group->a, tmp_a))
goto err;
/* group->b */
if (!BN_nnmod(group->b, b, p, ctx))
goto err;
if (group->meth->field_encode)
if (!group->meth->field_encode(group, group->b, group->b, ctx))
goto err;
/* group->a_is_minus3 */
if (!BN_add_word(tmp_a, 3))
goto err;
group->a_is_minus3 = (0 == BN_cmp(tmp_a, group->field));
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_group_get_curve(const EC_GROUP *group, BIGNUM *p, BIGNUM *a,
BIGNUM *b, BN_CTX *ctx)
{
int ret = 0;
BN_CTX *new_ctx = NULL;
if (p != NULL) {
if (!BN_copy(p, group->field))
return 0;
}
if (a != NULL || b != NULL) {
if (group->meth->field_decode) {
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
if (a != NULL) {
if (!group->meth->field_decode(group, a, group->a, ctx))
goto err;
}
if (b != NULL) {
if (!group->meth->field_decode(group, b, group->b, ctx))
goto err;
}
} else {
if (a != NULL) {
if (!BN_copy(a, group->a))
goto err;
}
if (b != NULL) {
if (!BN_copy(b, group->b))
goto err;
}
}
}
ret = 1;
err:
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_group_get_degree(const EC_GROUP *group)
{
return BN_num_bits(group->field);
}
int ec_GFp_simple_group_check_discriminant(const EC_GROUP *group, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *a, *b, *order, *tmp_1, *tmp_2;
const BIGNUM *p = group->field;
BN_CTX *new_ctx = NULL;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL) {
ECerr(EC_F_EC_GFP_SIMPLE_GROUP_CHECK_DISCRIMINANT,
ERR_R_MALLOC_FAILURE);
goto err;
}
}
BN_CTX_start(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
tmp_1 = BN_CTX_get(ctx);
tmp_2 = BN_CTX_get(ctx);
order = BN_CTX_get(ctx);
if (order == NULL)
goto err;
if (group->meth->field_decode) {
if (!group->meth->field_decode(group, a, group->a, ctx))
goto err;
if (!group->meth->field_decode(group, b, group->b, ctx))
goto err;
} else {
if (!BN_copy(a, group->a))
goto err;
if (!BN_copy(b, group->b))
goto err;
}
/*-
* check the discriminant:
* y^2 = x^3 + a*x + b is an elliptic curve <=> 4*a^3 + 27*b^2 != 0 (mod p)
* 0 =< a, b < p
*/
if (BN_is_zero(a)) {
if (BN_is_zero(b))
goto err;
} else if (!BN_is_zero(b)) {
if (!BN_mod_sqr(tmp_1, a, p, ctx))
goto err;
if (!BN_mod_mul(tmp_2, tmp_1, a, p, ctx))
goto err;
if (!BN_lshift(tmp_1, tmp_2, 2))
goto err;
/* tmp_1 = 4*a^3 */
if (!BN_mod_sqr(tmp_2, b, p, ctx))
goto err;
if (!BN_mul_word(tmp_2, 27))
goto err;
/* tmp_2 = 27*b^2 */
if (!BN_mod_add(a, tmp_1, tmp_2, p, ctx))
goto err;
if (BN_is_zero(a))
goto err;
}
ret = 1;
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_point_init(EC_POINT *point)
{
point->X = BN_new();
point->Y = BN_new();
point->Z = BN_new();
point->Z_is_one = 0;
if (point->X == NULL || point->Y == NULL || point->Z == NULL) {
BN_free(point->X);
BN_free(point->Y);
BN_free(point->Z);
return 0;
}
return 1;
}
void ec_GFp_simple_point_finish(EC_POINT *point)
{
BN_free(point->X);
BN_free(point->Y);
BN_free(point->Z);
}
void ec_GFp_simple_point_clear_finish(EC_POINT *point)
{
BN_clear_free(point->X);
BN_clear_free(point->Y);
BN_clear_free(point->Z);
point->Z_is_one = 0;
}
int ec_GFp_simple_point_copy(EC_POINT *dest, const EC_POINT *src)
{
if (!BN_copy(dest->X, src->X))
return 0;
if (!BN_copy(dest->Y, src->Y))
return 0;
if (!BN_copy(dest->Z, src->Z))
return 0;
dest->Z_is_one = src->Z_is_one;
dest->curve_name = src->curve_name;
return 1;
}
int ec_GFp_simple_point_set_to_infinity(const EC_GROUP *group,
EC_POINT *point)
{
point->Z_is_one = 0;
BN_zero(point->Z);
return 1;
}
int ec_GFp_simple_set_Jprojective_coordinates_GFp(const EC_GROUP *group,
EC_POINT *point,
const BIGNUM *x,
const BIGNUM *y,
const BIGNUM *z,
BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
int ret = 0;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
if (x != NULL) {
if (!BN_nnmod(point->X, x, group->field, ctx))
goto err;
if (group->meth->field_encode) {
if (!group->meth->field_encode(group, point->X, point->X, ctx))
goto err;
}
}
if (y != NULL) {
if (!BN_nnmod(point->Y, y, group->field, ctx))
goto err;
if (group->meth->field_encode) {
if (!group->meth->field_encode(group, point->Y, point->Y, ctx))
goto err;
}
}
if (z != NULL) {
int Z_is_one;
if (!BN_nnmod(point->Z, z, group->field, ctx))
goto err;
Z_is_one = BN_is_one(point->Z);
if (group->meth->field_encode) {
if (Z_is_one && (group->meth->field_set_to_one != 0)) {
if (!group->meth->field_set_to_one(group, point->Z, ctx))
goto err;
} else {
if (!group->
meth->field_encode(group, point->Z, point->Z, ctx))
goto err;
}
}
point->Z_is_one = Z_is_one;
}
ret = 1;
err:
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_get_Jprojective_coordinates_GFp(const EC_GROUP *group,
const EC_POINT *point,
BIGNUM *x, BIGNUM *y,
BIGNUM *z, BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
int ret = 0;
if (group->meth->field_decode != 0) {
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
if (x != NULL) {
if (!group->meth->field_decode(group, x, point->X, ctx))
goto err;
}
if (y != NULL) {
if (!group->meth->field_decode(group, y, point->Y, ctx))
goto err;
}
if (z != NULL) {
if (!group->meth->field_decode(group, z, point->Z, ctx))
goto err;
}
} else {
if (x != NULL) {
if (!BN_copy(x, point->X))
goto err;
}
if (y != NULL) {
if (!BN_copy(y, point->Y))
goto err;
}
if (z != NULL) {
if (!BN_copy(z, point->Z))
goto err;
}
}
ret = 1;
err:
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_point_set_affine_coordinates(const EC_GROUP *group,
EC_POINT *point,
const BIGNUM *x,
const BIGNUM *y, BN_CTX *ctx)
{
if (x == NULL || y == NULL) {
/*
* unlike for projective coordinates, we do not tolerate this
*/
ECerr(EC_F_EC_GFP_SIMPLE_POINT_SET_AFFINE_COORDINATES,
ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
return EC_POINT_set_Jprojective_coordinates_GFp(group, point, x, y,
BN_value_one(), ctx);
}
int ec_GFp_simple_point_get_affine_coordinates(const EC_GROUP *group,
const EC_POINT *point,
BIGNUM *x, BIGNUM *y,
BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *Z, *Z_1, *Z_2, *Z_3;
const BIGNUM *Z_;
int ret = 0;
if (EC_POINT_is_at_infinity(group, point)) {
ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
EC_R_POINT_AT_INFINITY);
return 0;
}
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
Z = BN_CTX_get(ctx);
Z_1 = BN_CTX_get(ctx);
Z_2 = BN_CTX_get(ctx);
Z_3 = BN_CTX_get(ctx);
if (Z_3 == NULL)
goto err;
/* transform (X, Y, Z) into (x, y) := (X/Z^2, Y/Z^3) */
if (group->meth->field_decode) {
if (!group->meth->field_decode(group, Z, point->Z, ctx))
goto err;
Z_ = Z;
} else {
Z_ = point->Z;
}
if (BN_is_one(Z_)) {
if (group->meth->field_decode) {
if (x != NULL) {
if (!group->meth->field_decode(group, x, point->X, ctx))
goto err;
}
if (y != NULL) {
if (!group->meth->field_decode(group, y, point->Y, ctx))
goto err;
}
} else {
if (x != NULL) {
if (!BN_copy(x, point->X))
goto err;
}
if (y != NULL) {
if (!BN_copy(y, point->Y))
goto err;
}
}
} else {
if (!group->meth->field_inv(group, Z_1, Z_, ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_POINT_GET_AFFINE_COORDINATES,
ERR_R_BN_LIB);
goto err;
}
if (group->meth->field_encode == 0) {
/* field_sqr works on standard representation */
if (!group->meth->field_sqr(group, Z_2, Z_1, ctx))
goto err;
} else {
if (!BN_mod_sqr(Z_2, Z_1, group->field, ctx))
goto err;
}
if (x != NULL) {
/*
* in the Montgomery case, field_mul will cancel out Montgomery
* factor in X:
*/
if (!group->meth->field_mul(group, x, point->X, Z_2, ctx))
goto err;
}
if (y != NULL) {
if (group->meth->field_encode == 0) {
/*
* field_mul works on standard representation
*/
if (!group->meth->field_mul(group, Z_3, Z_2, Z_1, ctx))
goto err;
} else {
if (!BN_mod_mul(Z_3, Z_2, Z_1, group->field, ctx))
goto err;
}
/*
* in the Montgomery case, field_mul will cancel out Montgomery
* factor in Y:
*/
if (!group->meth->field_mul(group, y, point->Y, Z_3, ctx))
goto err;
}
}
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
const BIGNUM *p;
BN_CTX *new_ctx = NULL;
BIGNUM *n0, *n1, *n2, *n3, *n4, *n5, *n6;
int ret = 0;
if (a == b)
return EC_POINT_dbl(group, r, a, ctx);
if (EC_POINT_is_at_infinity(group, a))
return EC_POINT_copy(r, b);
if (EC_POINT_is_at_infinity(group, b))
return EC_POINT_copy(r, a);
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
p = group->field;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
n0 = BN_CTX_get(ctx);
n1 = BN_CTX_get(ctx);
n2 = BN_CTX_get(ctx);
n3 = BN_CTX_get(ctx);
n4 = BN_CTX_get(ctx);
n5 = BN_CTX_get(ctx);
n6 = BN_CTX_get(ctx);
if (n6 == NULL)
goto end;
/*
* Note that in this function we must not read components of 'a' or 'b'
* once we have written the corresponding components of 'r'. ('r' might
* be one of 'a' or 'b'.)
*/
/* n1, n2 */
if (b->Z_is_one) {
if (!BN_copy(n1, a->X))
goto end;
if (!BN_copy(n2, a->Y))
goto end;
/* n1 = X_a */
/* n2 = Y_a */
} else {
if (!field_sqr(group, n0, b->Z, ctx))
goto end;
if (!field_mul(group, n1, a->X, n0, ctx))
goto end;
/* n1 = X_a * Z_b^2 */
if (!field_mul(group, n0, n0, b->Z, ctx))
goto end;
if (!field_mul(group, n2, a->Y, n0, ctx))
goto end;
/* n2 = Y_a * Z_b^3 */
}
/* n3, n4 */
if (a->Z_is_one) {
if (!BN_copy(n3, b->X))
goto end;
if (!BN_copy(n4, b->Y))
goto end;
/* n3 = X_b */
/* n4 = Y_b */
} else {
if (!field_sqr(group, n0, a->Z, ctx))
goto end;
if (!field_mul(group, n3, b->X, n0, ctx))
goto end;
/* n3 = X_b * Z_a^2 */
if (!field_mul(group, n0, n0, a->Z, ctx))
goto end;
if (!field_mul(group, n4, b->Y, n0, ctx))
goto end;
/* n4 = Y_b * Z_a^3 */
}
/* n5, n6 */
if (!BN_mod_sub_quick(n5, n1, n3, p))
goto end;
if (!BN_mod_sub_quick(n6, n2, n4, p))
goto end;
/* n5 = n1 - n3 */
/* n6 = n2 - n4 */
if (BN_is_zero(n5)) {
if (BN_is_zero(n6)) {
/* a is the same point as b */
BN_CTX_end(ctx);
ret = EC_POINT_dbl(group, r, a, ctx);
ctx = NULL;
goto end;
} else {
/* a is the inverse of b */
BN_zero(r->Z);
r->Z_is_one = 0;
ret = 1;
goto end;
}
}
/* 'n7', 'n8' */
if (!BN_mod_add_quick(n1, n1, n3, p))
goto end;
if (!BN_mod_add_quick(n2, n2, n4, p))
goto end;
/* 'n7' = n1 + n3 */
/* 'n8' = n2 + n4 */
/* Z_r */
if (a->Z_is_one && b->Z_is_one) {
if (!BN_copy(r->Z, n5))
goto end;
} else {
if (a->Z_is_one) {
if (!BN_copy(n0, b->Z))
goto end;
} else if (b->Z_is_one) {
if (!BN_copy(n0, a->Z))
goto end;
} else {
if (!field_mul(group, n0, a->Z, b->Z, ctx))
goto end;
}
if (!field_mul(group, r->Z, n0, n5, ctx))
goto end;
}
r->Z_is_one = 0;
/* Z_r = Z_a * Z_b * n5 */
/* X_r */
if (!field_sqr(group, n0, n6, ctx))
goto end;
if (!field_sqr(group, n4, n5, ctx))
goto end;
if (!field_mul(group, n3, n1, n4, ctx))
goto end;
if (!BN_mod_sub_quick(r->X, n0, n3, p))
goto end;
/* X_r = n6^2 - n5^2 * 'n7' */
/* 'n9' */
if (!BN_mod_lshift1_quick(n0, r->X, p))
goto end;
if (!BN_mod_sub_quick(n0, n3, n0, p))
goto end;
/* n9 = n5^2 * 'n7' - 2 * X_r */
/* Y_r */
if (!field_mul(group, n0, n0, n6, ctx))
goto end;
if (!field_mul(group, n5, n4, n5, ctx))
goto end; /* now n5 is n5^3 */
if (!field_mul(group, n1, n2, n5, ctx))
goto end;
if (!BN_mod_sub_quick(n0, n0, n1, p))
goto end;
if (BN_is_odd(n0))
if (!BN_add(n0, n0, p))
goto end;
/* now 0 <= n0 < 2*p, and n0 is even */
if (!BN_rshift1(r->Y, n0))
goto end;
/* Y_r = (n6 * 'n9' - 'n8' * 'n5^3') / 2 */
ret = 1;
end:
- if (ctx) /* otherwise we already called BN_CTX_end */
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
BN_CTX *ctx)
{
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
const BIGNUM *p;
BN_CTX *new_ctx = NULL;
BIGNUM *n0, *n1, *n2, *n3;
int ret = 0;
if (EC_POINT_is_at_infinity(group, a)) {
BN_zero(r->Z);
r->Z_is_one = 0;
return 1;
}
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
p = group->field;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
n0 = BN_CTX_get(ctx);
n1 = BN_CTX_get(ctx);
n2 = BN_CTX_get(ctx);
n3 = BN_CTX_get(ctx);
if (n3 == NULL)
goto err;
/*
* Note that in this function we must not read components of 'a' once we
* have written the corresponding components of 'r'. ('r' might the same
* as 'a'.)
*/
/* n1 */
if (a->Z_is_one) {
if (!field_sqr(group, n0, a->X, ctx))
goto err;
if (!BN_mod_lshift1_quick(n1, n0, p))
goto err;
if (!BN_mod_add_quick(n0, n0, n1, p))
goto err;
if (!BN_mod_add_quick(n1, n0, group->a, p))
goto err;
/* n1 = 3 * X_a^2 + a_curve */
} else if (group->a_is_minus3) {
if (!field_sqr(group, n1, a->Z, ctx))
goto err;
if (!BN_mod_add_quick(n0, a->X, n1, p))
goto err;
if (!BN_mod_sub_quick(n2, a->X, n1, p))
goto err;
if (!field_mul(group, n1, n0, n2, ctx))
goto err;
if (!BN_mod_lshift1_quick(n0, n1, p))
goto err;
if (!BN_mod_add_quick(n1, n0, n1, p))
goto err;
/*-
* n1 = 3 * (X_a + Z_a^2) * (X_a - Z_a^2)
* = 3 * X_a^2 - 3 * Z_a^4
*/
} else {
if (!field_sqr(group, n0, a->X, ctx))
goto err;
if (!BN_mod_lshift1_quick(n1, n0, p))
goto err;
if (!BN_mod_add_quick(n0, n0, n1, p))
goto err;
if (!field_sqr(group, n1, a->Z, ctx))
goto err;
if (!field_sqr(group, n1, n1, ctx))
goto err;
if (!field_mul(group, n1, n1, group->a, ctx))
goto err;
if (!BN_mod_add_quick(n1, n1, n0, p))
goto err;
/* n1 = 3 * X_a^2 + a_curve * Z_a^4 */
}
/* Z_r */
if (a->Z_is_one) {
if (!BN_copy(n0, a->Y))
goto err;
} else {
if (!field_mul(group, n0, a->Y, a->Z, ctx))
goto err;
}
if (!BN_mod_lshift1_quick(r->Z, n0, p))
goto err;
r->Z_is_one = 0;
/* Z_r = 2 * Y_a * Z_a */
/* n2 */
if (!field_sqr(group, n3, a->Y, ctx))
goto err;
if (!field_mul(group, n2, a->X, n3, ctx))
goto err;
if (!BN_mod_lshift_quick(n2, n2, 2, p))
goto err;
/* n2 = 4 * X_a * Y_a^2 */
/* X_r */
if (!BN_mod_lshift1_quick(n0, n2, p))
goto err;
if (!field_sqr(group, r->X, n1, ctx))
goto err;
if (!BN_mod_sub_quick(r->X, r->X, n0, p))
goto err;
/* X_r = n1^2 - 2 * n2 */
/* n3 */
if (!field_sqr(group, n0, n3, ctx))
goto err;
if (!BN_mod_lshift_quick(n3, n0, 3, p))
goto err;
/* n3 = 8 * Y_a^4 */
/* Y_r */
if (!BN_mod_sub_quick(n0, n2, r->X, p))
goto err;
if (!field_mul(group, n0, n1, n0, ctx))
goto err;
if (!BN_mod_sub_quick(r->Y, n0, n3, p))
goto err;
/* Y_r = n1 * (n2 - X_r) - n3 */
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_invert(const EC_GROUP *group, EC_POINT *point, BN_CTX *ctx)
{
if (EC_POINT_is_at_infinity(group, point) || BN_is_zero(point->Y))
/* point is its own inverse */
return 1;
return BN_usub(point->Y, group->field, point->Y);
}
int ec_GFp_simple_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
{
return BN_is_zero(point->Z);
}
int ec_GFp_simple_is_on_curve(const EC_GROUP *group, const EC_POINT *point,
BN_CTX *ctx)
{
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
const BIGNUM *p;
BN_CTX *new_ctx = NULL;
BIGNUM *rh, *tmp, *Z4, *Z6;
int ret = -1;
if (EC_POINT_is_at_infinity(group, point))
return 1;
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
p = group->field;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return -1;
}
BN_CTX_start(ctx);
rh = BN_CTX_get(ctx);
tmp = BN_CTX_get(ctx);
Z4 = BN_CTX_get(ctx);
Z6 = BN_CTX_get(ctx);
if (Z6 == NULL)
goto err;
/*-
* We have a curve defined by a Weierstrass equation
* y^2 = x^3 + a*x + b.
* The point to consider is given in Jacobian projective coordinates
* where (X, Y, Z) represents (x, y) = (X/Z^2, Y/Z^3).
* Substituting this and multiplying by Z^6 transforms the above equation into
* Y^2 = X^3 + a*X*Z^4 + b*Z^6.
* To test this, we add up the right-hand side in 'rh'.
*/
/* rh := X^2 */
if (!field_sqr(group, rh, point->X, ctx))
goto err;
if (!point->Z_is_one) {
if (!field_sqr(group, tmp, point->Z, ctx))
goto err;
if (!field_sqr(group, Z4, tmp, ctx))
goto err;
if (!field_mul(group, Z6, Z4, tmp, ctx))
goto err;
/* rh := (rh + a*Z^4)*X */
if (group->a_is_minus3) {
if (!BN_mod_lshift1_quick(tmp, Z4, p))
goto err;
if (!BN_mod_add_quick(tmp, tmp, Z4, p))
goto err;
if (!BN_mod_sub_quick(rh, rh, tmp, p))
goto err;
if (!field_mul(group, rh, rh, point->X, ctx))
goto err;
} else {
if (!field_mul(group, tmp, Z4, group->a, ctx))
goto err;
if (!BN_mod_add_quick(rh, rh, tmp, p))
goto err;
if (!field_mul(group, rh, rh, point->X, ctx))
goto err;
}
/* rh := rh + b*Z^6 */
if (!field_mul(group, tmp, group->b, Z6, ctx))
goto err;
if (!BN_mod_add_quick(rh, rh, tmp, p))
goto err;
} else {
/* point->Z_is_one */
/* rh := (rh + a)*X */
if (!BN_mod_add_quick(rh, rh, group->a, p))
goto err;
if (!field_mul(group, rh, rh, point->X, ctx))
goto err;
/* rh := rh + b */
if (!BN_mod_add_quick(rh, rh, group->b, p))
goto err;
}
/* 'lh' := Y^2 */
if (!field_sqr(group, tmp, point->Y, ctx))
goto err;
ret = (0 == BN_ucmp(tmp, rh));
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_cmp(const EC_GROUP *group, const EC_POINT *a,
const EC_POINT *b, BN_CTX *ctx)
{
/*-
* return values:
* -1 error
* 0 equal (in affine coordinates)
* 1 not equal
*/
int (*field_mul) (const EC_GROUP *, BIGNUM *, const BIGNUM *,
const BIGNUM *, BN_CTX *);
int (*field_sqr) (const EC_GROUP *, BIGNUM *, const BIGNUM *, BN_CTX *);
BN_CTX *new_ctx = NULL;
BIGNUM *tmp1, *tmp2, *Za23, *Zb23;
const BIGNUM *tmp1_, *tmp2_;
int ret = -1;
if (EC_POINT_is_at_infinity(group, a)) {
return EC_POINT_is_at_infinity(group, b) ? 0 : 1;
}
if (EC_POINT_is_at_infinity(group, b))
return 1;
if (a->Z_is_one && b->Z_is_one) {
return ((BN_cmp(a->X, b->X) == 0) && BN_cmp(a->Y, b->Y) == 0) ? 0 : 1;
}
field_mul = group->meth->field_mul;
field_sqr = group->meth->field_sqr;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return -1;
}
BN_CTX_start(ctx);
tmp1 = BN_CTX_get(ctx);
tmp2 = BN_CTX_get(ctx);
Za23 = BN_CTX_get(ctx);
Zb23 = BN_CTX_get(ctx);
if (Zb23 == NULL)
goto end;
/*-
* We have to decide whether
* (X_a/Z_a^2, Y_a/Z_a^3) = (X_b/Z_b^2, Y_b/Z_b^3),
* or equivalently, whether
* (X_a*Z_b^2, Y_a*Z_b^3) = (X_b*Z_a^2, Y_b*Z_a^3).
*/
if (!b->Z_is_one) {
if (!field_sqr(group, Zb23, b->Z, ctx))
goto end;
if (!field_mul(group, tmp1, a->X, Zb23, ctx))
goto end;
tmp1_ = tmp1;
} else
tmp1_ = a->X;
if (!a->Z_is_one) {
if (!field_sqr(group, Za23, a->Z, ctx))
goto end;
if (!field_mul(group, tmp2, b->X, Za23, ctx))
goto end;
tmp2_ = tmp2;
} else
tmp2_ = b->X;
/* compare X_a*Z_b^2 with X_b*Z_a^2 */
if (BN_cmp(tmp1_, tmp2_) != 0) {
ret = 1; /* points differ */
goto end;
}
if (!b->Z_is_one) {
if (!field_mul(group, Zb23, Zb23, b->Z, ctx))
goto end;
if (!field_mul(group, tmp1, a->Y, Zb23, ctx))
goto end;
/* tmp1_ = tmp1 */
} else
tmp1_ = a->Y;
if (!a->Z_is_one) {
if (!field_mul(group, Za23, Za23, a->Z, ctx))
goto end;
if (!field_mul(group, tmp2, b->Y, Za23, ctx))
goto end;
/* tmp2_ = tmp2 */
} else
tmp2_ = b->Y;
/* compare Y_a*Z_b^3 with Y_b*Z_a^3 */
if (BN_cmp(tmp1_, tmp2_) != 0) {
ret = 1; /* points differ */
goto end;
}
/* points are equal */
ret = 0;
end:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_make_affine(const EC_GROUP *group, EC_POINT *point,
BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *x, *y;
int ret = 0;
if (point->Z_is_one || EC_POINT_is_at_infinity(group, point))
return 1;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
x = BN_CTX_get(ctx);
y = BN_CTX_get(ctx);
if (y == NULL)
goto err;
if (!EC_POINT_get_affine_coordinates(group, point, x, y, ctx))
goto err;
if (!EC_POINT_set_affine_coordinates(group, point, x, y, ctx))
goto err;
if (!point->Z_is_one) {
ECerr(EC_F_EC_GFP_SIMPLE_MAKE_AFFINE, ERR_R_INTERNAL_ERROR);
goto err;
}
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
int ec_GFp_simple_points_make_affine(const EC_GROUP *group, size_t num,
EC_POINT *points[], BN_CTX *ctx)
{
BN_CTX *new_ctx = NULL;
BIGNUM *tmp, *tmp_Z;
BIGNUM **prod_Z = NULL;
size_t i;
int ret = 0;
if (num == 0)
return 1;
if (ctx == NULL) {
ctx = new_ctx = BN_CTX_new();
if (ctx == NULL)
return 0;
}
BN_CTX_start(ctx);
tmp = BN_CTX_get(ctx);
tmp_Z = BN_CTX_get(ctx);
if (tmp_Z == NULL)
goto err;
prod_Z = OPENSSL_malloc(num * sizeof(prod_Z[0]));
if (prod_Z == NULL)
goto err;
for (i = 0; i < num; i++) {
prod_Z[i] = BN_new();
if (prod_Z[i] == NULL)
goto err;
}
/*
* Set each prod_Z[i] to the product of points[0]->Z .. points[i]->Z,
* skipping any zero-valued inputs (pretend that they're 1).
*/
if (!BN_is_zero(points[0]->Z)) {
if (!BN_copy(prod_Z[0], points[0]->Z))
goto err;
} else {
if (group->meth->field_set_to_one != 0) {
if (!group->meth->field_set_to_one(group, prod_Z[0], ctx))
goto err;
} else {
if (!BN_one(prod_Z[0]))
goto err;
}
}
for (i = 1; i < num; i++) {
if (!BN_is_zero(points[i]->Z)) {
if (!group->
meth->field_mul(group, prod_Z[i], prod_Z[i - 1], points[i]->Z,
ctx))
goto err;
} else {
if (!BN_copy(prod_Z[i], prod_Z[i - 1]))
goto err;
}
}
/*
* Now use a single explicit inversion to replace every non-zero
* points[i]->Z by its inverse.
*/
if (!group->meth->field_inv(group, tmp, prod_Z[num - 1], ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_POINTS_MAKE_AFFINE, ERR_R_BN_LIB);
goto err;
}
if (group->meth->field_encode != 0) {
/*
* In the Montgomery case, we just turned R*H (representing H) into
* 1/(R*H), but we need R*(1/H) (representing 1/H); i.e. we need to
* multiply by the Montgomery factor twice.
*/
if (!group->meth->field_encode(group, tmp, tmp, ctx))
goto err;
if (!group->meth->field_encode(group, tmp, tmp, ctx))
goto err;
}
for (i = num - 1; i > 0; --i) {
/*
* Loop invariant: tmp is the product of the inverses of points[0]->Z
* .. points[i]->Z (zero-valued inputs skipped).
*/
if (!BN_is_zero(points[i]->Z)) {
/*
* Set tmp_Z to the inverse of points[i]->Z (as product of Z
* inverses 0 .. i, Z values 0 .. i - 1).
*/
if (!group->
meth->field_mul(group, tmp_Z, prod_Z[i - 1], tmp, ctx))
goto err;
/*
* Update tmp to satisfy the loop invariant for i - 1.
*/
if (!group->meth->field_mul(group, tmp, tmp, points[i]->Z, ctx))
goto err;
/* Replace points[i]->Z by its inverse. */
if (!BN_copy(points[i]->Z, tmp_Z))
goto err;
}
}
if (!BN_is_zero(points[0]->Z)) {
/* Replace points[0]->Z by its inverse. */
if (!BN_copy(points[0]->Z, tmp))
goto err;
}
/* Finally, fix up the X and Y coordinates for all points. */
for (i = 0; i < num; i++) {
EC_POINT *p = points[i];
if (!BN_is_zero(p->Z)) {
/* turn (X, Y, 1/Z) into (X/Z^2, Y/Z^3, 1) */
if (!group->meth->field_sqr(group, tmp, p->Z, ctx))
goto err;
if (!group->meth->field_mul(group, p->X, p->X, tmp, ctx))
goto err;
if (!group->meth->field_mul(group, tmp, tmp, p->Z, ctx))
goto err;
if (!group->meth->field_mul(group, p->Y, p->Y, tmp, ctx))
goto err;
if (group->meth->field_set_to_one != 0) {
if (!group->meth->field_set_to_one(group, p->Z, ctx))
goto err;
} else {
if (!BN_one(p->Z))
goto err;
}
p->Z_is_one = 1;
}
}
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
if (prod_Z != NULL) {
for (i = 0; i < num; i++) {
if (prod_Z[i] == NULL)
break;
BN_clear_free(prod_Z[i]);
}
OPENSSL_free(prod_Z);
}
return ret;
}
int ec_GFp_simple_field_mul(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
const BIGNUM *b, BN_CTX *ctx)
{
return BN_mod_mul(r, a, b, group->field, ctx);
}
int ec_GFp_simple_field_sqr(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx)
{
return BN_mod_sqr(r, a, group->field, ctx);
}
/*-
* Computes the multiplicative inverse of a in GF(p), storing the result in r.
* If a is zero (or equivalent), you'll get a EC_R_CANNOT_INVERT error.
* Since we don't have a Mont structure here, SCA hardening is with blinding.
*/
int ec_GFp_simple_field_inv(const EC_GROUP *group, BIGNUM *r, const BIGNUM *a,
BN_CTX *ctx)
{
BIGNUM *e = NULL;
BN_CTX *new_ctx = NULL;
int ret = 0;
if (ctx == NULL && (ctx = new_ctx = BN_CTX_secure_new()) == NULL)
return 0;
BN_CTX_start(ctx);
if ((e = BN_CTX_get(ctx)) == NULL)
goto err;
do {
if (!BN_priv_rand_range(e, group->field))
goto err;
} while (BN_is_zero(e));
/* r := a * e */
if (!group->meth->field_mul(group, r, a, e, ctx))
goto err;
/* r := 1/(a * e) */
if (!BN_mod_inverse(r, r, group->field, ctx)) {
ECerr(EC_F_EC_GFP_SIMPLE_FIELD_INV, EC_R_CANNOT_INVERT);
goto err;
}
/* r := e/(a * e) = 1/a */
if (!group->meth->field_mul(group, r, r, e, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(new_ctx);
return ret;
}
/*-
* Apply randomization of EC point projective coordinates:
*
* (X, Y ,Z ) = (lambda^2*X, lambda^3*Y, lambda*Z)
* lambda = [1,group->field)
*
*/
int ec_GFp_simple_blind_coordinates(const EC_GROUP *group, EC_POINT *p,
BN_CTX *ctx)
{
int ret = 0;
BIGNUM *lambda = NULL;
BIGNUM *temp = NULL;
BN_CTX_start(ctx);
lambda = BN_CTX_get(ctx);
temp = BN_CTX_get(ctx);
if (temp == NULL) {
ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_MALLOC_FAILURE);
goto err;
}
/* make sure lambda is not zero */
do {
if (!BN_priv_rand_range(lambda, group->field)) {
ECerr(EC_F_EC_GFP_SIMPLE_BLIND_COORDINATES, ERR_R_BN_LIB);
goto err;
}
} while (BN_is_zero(lambda));
/* if field_encode defined convert between representations */
if (group->meth->field_encode != NULL
&& !group->meth->field_encode(group, lambda, lambda, ctx))
goto err;
if (!group->meth->field_mul(group, p->Z, p->Z, lambda, ctx))
goto err;
if (!group->meth->field_sqr(group, temp, lambda, ctx))
goto err;
if (!group->meth->field_mul(group, p->X, p->X, temp, ctx))
goto err;
if (!group->meth->field_mul(group, temp, temp, lambda, ctx))
goto err;
if (!group->meth->field_mul(group, p->Y, p->Y, temp, ctx))
goto err;
p->Z_is_one = 0;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*-
* Set s := p, r := 2p.
*
* For doubling we use Formula 3 from Izu-Takagi "A fast parallel elliptic curve
* multiplication resistant against side channel attacks" appendix, as described
* at
* https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#doubling-dbl-2002-it-2
*
* The input point p will be in randomized Jacobian projective coords:
* x = X/Z**2, y=Y/Z**3
*
* The output points p, s, and r are converted to standard (homogeneous)
* projective coords:
* x = X/Z, y=Y/Z
*/
int ec_GFp_simple_ladder_pre(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
EC_POINT *p, BN_CTX *ctx)
{
BIGNUM *t1, *t2, *t3, *t4, *t5, *t6 = NULL;
t1 = r->Z;
t2 = r->Y;
t3 = s->X;
t4 = r->X;
t5 = s->Y;
t6 = s->Z;
/* convert p: (X,Y,Z) -> (XZ,Y,Z**3) */
if (!group->meth->field_mul(group, p->X, p->X, p->Z, ctx)
|| !group->meth->field_sqr(group, t1, p->Z, ctx)
|| !group->meth->field_mul(group, p->Z, p->Z, t1, ctx)
/* r := 2p */
|| !group->meth->field_sqr(group, t2, p->X, ctx)
|| !group->meth->field_sqr(group, t3, p->Z, ctx)
|| !group->meth->field_mul(group, t4, t3, group->a, ctx)
|| !BN_mod_sub_quick(t5, t2, t4, group->field)
|| !BN_mod_add_quick(t2, t2, t4, group->field)
|| !group->meth->field_sqr(group, t5, t5, ctx)
|| !group->meth->field_mul(group, t6, t3, group->b, ctx)
|| !group->meth->field_mul(group, t1, p->X, p->Z, ctx)
|| !group->meth->field_mul(group, t4, t1, t6, ctx)
|| !BN_mod_lshift_quick(t4, t4, 3, group->field)
/* r->X coord output */
|| !BN_mod_sub_quick(r->X, t5, t4, group->field)
|| !group->meth->field_mul(group, t1, t1, t2, ctx)
|| !group->meth->field_mul(group, t2, t3, t6, ctx)
|| !BN_mod_add_quick(t1, t1, t2, group->field)
/* r->Z coord output */
|| !BN_mod_lshift_quick(r->Z, t1, 2, group->field)
|| !EC_POINT_copy(s, p))
return 0;
r->Z_is_one = 0;
s->Z_is_one = 0;
p->Z_is_one = 0;
return 1;
}
/*-
* Differential addition-and-doubling using Eq. (9) and (10) from Izu-Takagi
* "A fast parallel elliptic curve multiplication resistant against side channel
* attacks", as described at
* https://hyperelliptic.org/EFD/g1p/auto-shortw-xz.html#ladder-ladd-2002-it-4
*/
int ec_GFp_simple_ladder_step(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
EC_POINT *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6, *t7 = NULL;
BN_CTX_start(ctx);
t0 = BN_CTX_get(ctx);
t1 = BN_CTX_get(ctx);
t2 = BN_CTX_get(ctx);
t3 = BN_CTX_get(ctx);
t4 = BN_CTX_get(ctx);
t5 = BN_CTX_get(ctx);
t6 = BN_CTX_get(ctx);
t7 = BN_CTX_get(ctx);
if (t7 == NULL
|| !group->meth->field_mul(group, t0, r->X, s->X, ctx)
|| !group->meth->field_mul(group, t1, r->Z, s->Z, ctx)
|| !group->meth->field_mul(group, t2, r->X, s->Z, ctx)
|| !group->meth->field_mul(group, t3, r->Z, s->X, ctx)
|| !group->meth->field_mul(group, t4, group->a, t1, ctx)
|| !BN_mod_add_quick(t0, t0, t4, group->field)
|| !BN_mod_add_quick(t4, t3, t2, group->field)
|| !group->meth->field_mul(group, t0, t4, t0, ctx)
|| !group->meth->field_sqr(group, t1, t1, ctx)
|| !BN_mod_lshift_quick(t7, group->b, 2, group->field)
|| !group->meth->field_mul(group, t1, t7, t1, ctx)
|| !BN_mod_lshift1_quick(t0, t0, group->field)
|| !BN_mod_add_quick(t0, t1, t0, group->field)
|| !BN_mod_sub_quick(t1, t2, t3, group->field)
|| !group->meth->field_sqr(group, t1, t1, ctx)
|| !group->meth->field_mul(group, t3, t1, p->X, ctx)
|| !group->meth->field_mul(group, t0, p->Z, t0, ctx)
/* s->X coord output */
|| !BN_mod_sub_quick(s->X, t0, t3, group->field)
/* s->Z coord output */
|| !group->meth->field_mul(group, s->Z, p->Z, t1, ctx)
|| !group->meth->field_sqr(group, t3, r->X, ctx)
|| !group->meth->field_sqr(group, t2, r->Z, ctx)
|| !group->meth->field_mul(group, t4, t2, group->a, ctx)
|| !BN_mod_add_quick(t5, r->X, r->Z, group->field)
|| !group->meth->field_sqr(group, t5, t5, ctx)
|| !BN_mod_sub_quick(t5, t5, t3, group->field)
|| !BN_mod_sub_quick(t5, t5, t2, group->field)
|| !BN_mod_sub_quick(t6, t3, t4, group->field)
|| !group->meth->field_sqr(group, t6, t6, ctx)
|| !group->meth->field_mul(group, t0, t2, t5, ctx)
|| !group->meth->field_mul(group, t0, t7, t0, ctx)
/* r->X coord output */
|| !BN_mod_sub_quick(r->X, t6, t0, group->field)
|| !BN_mod_add_quick(t6, t3, t4, group->field)
|| !group->meth->field_sqr(group, t3, t2, ctx)
|| !group->meth->field_mul(group, t7, t3, t7, ctx)
|| !group->meth->field_mul(group, t5, t5, t6, ctx)
|| !BN_mod_lshift1_quick(t5, t5, group->field)
/* r->Z coord output */
|| !BN_mod_add_quick(r->Z, t7, t5, group->field))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
/*-
* Recovers the y-coordinate of r using Eq. (8) from Brier-Joye, "Weierstrass
* Elliptic Curves and Side-Channel Attacks", modified to work in projective
* coordinates and return r in Jacobian projective coordinates.
*
* X4 = two*Y1*X2*Z3*Z2*Z1;
* Y4 = two*b*Z3*SQR(Z2*Z1) + Z3*(a*Z2*Z1+X1*X2)*(X1*Z2+X2*Z1) - X3*SQR(X1*Z2-X2*Z1);
* Z4 = two*Y1*Z3*SQR(Z2)*Z1;
*
* Z4 != 0 because:
* - Z1==0 implies p is at infinity, which would have caused an early exit in
* the caller;
* - Z2==0 implies r is at infinity (handled by the BN_is_zero(r->Z) branch);
* - Z3==0 implies s is at infinity (handled by the BN_is_zero(s->Z) branch);
* - Y1==0 implies p has order 2, so either r or s are infinity and handled by
* one of the BN_is_zero(...) branches.
*/
int ec_GFp_simple_ladder_post(const EC_GROUP *group,
EC_POINT *r, EC_POINT *s,
EC_POINT *p, BN_CTX *ctx)
{
int ret = 0;
BIGNUM *t0, *t1, *t2, *t3, *t4, *t5, *t6 = NULL;
if (BN_is_zero(r->Z))
return EC_POINT_set_to_infinity(group, r);
if (BN_is_zero(s->Z)) {
/* (X,Y,Z) -> (XZ,YZ**2,Z) */
if (!group->meth->field_mul(group, r->X, p->X, p->Z, ctx)
|| !group->meth->field_sqr(group, r->Z, p->Z, ctx)
|| !group->meth->field_mul(group, r->Y, p->Y, r->Z, ctx)
|| !BN_copy(r->Z, p->Z)
|| !EC_POINT_invert(group, r, ctx))
return 0;
return 1;
}
BN_CTX_start(ctx);
t0 = BN_CTX_get(ctx);
t1 = BN_CTX_get(ctx);
t2 = BN_CTX_get(ctx);
t3 = BN_CTX_get(ctx);
t4 = BN_CTX_get(ctx);
t5 = BN_CTX_get(ctx);
t6 = BN_CTX_get(ctx);
if (t6 == NULL
|| !BN_mod_lshift1_quick(t0, p->Y, group->field)
|| !group->meth->field_mul(group, t1, r->X, p->Z, ctx)
|| !group->meth->field_mul(group, t2, r->Z, s->Z, ctx)
|| !group->meth->field_mul(group, t2, t1, t2, ctx)
|| !group->meth->field_mul(group, t3, t2, t0, ctx)
|| !group->meth->field_mul(group, t2, r->Z, p->Z, ctx)
|| !group->meth->field_sqr(group, t4, t2, ctx)
|| !BN_mod_lshift1_quick(t5, group->b, group->field)
|| !group->meth->field_mul(group, t4, t4, t5, ctx)
|| !group->meth->field_mul(group, t6, t2, group->a, ctx)
|| !group->meth->field_mul(group, t5, r->X, p->X, ctx)
|| !BN_mod_add_quick(t5, t6, t5, group->field)
|| !group->meth->field_mul(group, t6, r->Z, p->X, ctx)
|| !BN_mod_add_quick(t2, t6, t1, group->field)
|| !group->meth->field_mul(group, t5, t5, t2, ctx)
|| !BN_mod_sub_quick(t6, t6, t1, group->field)
|| !group->meth->field_sqr(group, t6, t6, ctx)
|| !group->meth->field_mul(group, t6, t6, s->X, ctx)
|| !BN_mod_add_quick(t4, t5, t4, group->field)
|| !group->meth->field_mul(group, t4, t4, s->Z, ctx)
|| !BN_mod_sub_quick(t4, t4, t6, group->field)
|| !group->meth->field_sqr(group, t5, r->Z, ctx)
|| !group->meth->field_mul(group, r->Z, p->Z, s->Z, ctx)
|| !group->meth->field_mul(group, r->Z, t5, r->Z, ctx)
|| !group->meth->field_mul(group, r->Z, r->Z, t0, ctx)
/* t3 := X, t4 := Y */
/* (X,Y,Z) -> (XZ,YZ**2,Z) */
|| !group->meth->field_mul(group, r->X, t3, r->Z, ctx)
|| !group->meth->field_sqr(group, t3, r->Z, ctx)
|| !group->meth->field_mul(group, r->Y, t4, t3, ctx))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
diff --git a/crypto/err/err.c b/crypto/err/err.c
index c737b2a9c3e6..eaf6712fdbd0 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -1,953 +1,950 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include "internal/cryptlib_int.h"
#include "internal/err.h"
#include "internal/err_int.h"
#include <openssl/err.h>
#include <openssl/crypto.h>
#include <openssl/buffer.h>
#include <openssl/bio.h>
#include <openssl/opensslconf.h>
#include "internal/thread_once.h"
#include "internal/ctype.h"
#include "internal/constant_time_locl.h"
#include "e_os.h"
static int err_load_strings(const ERR_STRING_DATA *str);
static void ERR_STATE_free(ERR_STATE *s);
#ifndef OPENSSL_NO_ERR
static ERR_STRING_DATA ERR_str_libraries[] = {
{ERR_PACK(ERR_LIB_NONE, 0, 0), "unknown library"},
{ERR_PACK(ERR_LIB_SYS, 0, 0), "system library"},
{ERR_PACK(ERR_LIB_BN, 0, 0), "bignum routines"},
{ERR_PACK(ERR_LIB_RSA, 0, 0), "rsa routines"},
{ERR_PACK(ERR_LIB_DH, 0, 0), "Diffie-Hellman routines"},
{ERR_PACK(ERR_LIB_EVP, 0, 0), "digital envelope routines"},
{ERR_PACK(ERR_LIB_BUF, 0, 0), "memory buffer routines"},
{ERR_PACK(ERR_LIB_OBJ, 0, 0), "object identifier routines"},
{ERR_PACK(ERR_LIB_PEM, 0, 0), "PEM routines"},
{ERR_PACK(ERR_LIB_DSA, 0, 0), "dsa routines"},
{ERR_PACK(ERR_LIB_X509, 0, 0), "x509 certificate routines"},
{ERR_PACK(ERR_LIB_ASN1, 0, 0), "asn1 encoding routines"},
{ERR_PACK(ERR_LIB_CONF, 0, 0), "configuration file routines"},
{ERR_PACK(ERR_LIB_CRYPTO, 0, 0), "common libcrypto routines"},
{ERR_PACK(ERR_LIB_EC, 0, 0), "elliptic curve routines"},
{ERR_PACK(ERR_LIB_ECDSA, 0, 0), "ECDSA routines"},
{ERR_PACK(ERR_LIB_ECDH, 0, 0), "ECDH routines"},
{ERR_PACK(ERR_LIB_SSL, 0, 0), "SSL routines"},
{ERR_PACK(ERR_LIB_BIO, 0, 0), "BIO routines"},
{ERR_PACK(ERR_LIB_PKCS7, 0, 0), "PKCS7 routines"},
{ERR_PACK(ERR_LIB_X509V3, 0, 0), "X509 V3 routines"},
{ERR_PACK(ERR_LIB_PKCS12, 0, 0), "PKCS12 routines"},
{ERR_PACK(ERR_LIB_RAND, 0, 0), "random number generator"},
{ERR_PACK(ERR_LIB_DSO, 0, 0), "DSO support routines"},
{ERR_PACK(ERR_LIB_TS, 0, 0), "time stamp routines"},
{ERR_PACK(ERR_LIB_ENGINE, 0, 0), "engine routines"},
{ERR_PACK(ERR_LIB_OCSP, 0, 0), "OCSP routines"},
{ERR_PACK(ERR_LIB_UI, 0, 0), "UI routines"},
{ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"},
{ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"},
{ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"},
{ERR_PACK(ERR_LIB_CT, 0, 0), "CT routines"},
{ERR_PACK(ERR_LIB_ASYNC, 0, 0), "ASYNC routines"},
{ERR_PACK(ERR_LIB_KDF, 0, 0), "KDF routines"},
{ERR_PACK(ERR_LIB_OSSL_STORE, 0, 0), "STORE routines"},
{ERR_PACK(ERR_LIB_SM2, 0, 0), "SM2 routines"},
{0, NULL},
};
static ERR_STRING_DATA ERR_str_functs[] = {
{ERR_PACK(0, SYS_F_FOPEN, 0), "fopen"},
{ERR_PACK(0, SYS_F_CONNECT, 0), "connect"},
{ERR_PACK(0, SYS_F_GETSERVBYNAME, 0), "getservbyname"},
{ERR_PACK(0, SYS_F_SOCKET, 0), "socket"},
{ERR_PACK(0, SYS_F_IOCTLSOCKET, 0), "ioctlsocket"},
{ERR_PACK(0, SYS_F_BIND, 0), "bind"},
{ERR_PACK(0, SYS_F_LISTEN, 0), "listen"},
{ERR_PACK(0, SYS_F_ACCEPT, 0), "accept"},
# ifdef OPENSSL_SYS_WINDOWS
{ERR_PACK(0, SYS_F_WSASTARTUP, 0), "WSAstartup"},
# endif
{ERR_PACK(0, SYS_F_OPENDIR, 0), "opendir"},
{ERR_PACK(0, SYS_F_FREAD, 0), "fread"},
{ERR_PACK(0, SYS_F_GETADDRINFO, 0), "getaddrinfo"},
{ERR_PACK(0, SYS_F_GETNAMEINFO, 0), "getnameinfo"},
{ERR_PACK(0, SYS_F_SETSOCKOPT, 0), "setsockopt"},
{ERR_PACK(0, SYS_F_GETSOCKOPT, 0), "getsockopt"},
{ERR_PACK(0, SYS_F_GETSOCKNAME, 0), "getsockname"},
{ERR_PACK(0, SYS_F_GETHOSTBYNAME, 0), "gethostbyname"},
{ERR_PACK(0, SYS_F_FFLUSH, 0), "fflush"},
{ERR_PACK(0, SYS_F_OPEN, 0), "open"},
{ERR_PACK(0, SYS_F_CLOSE, 0), "close"},
{ERR_PACK(0, SYS_F_IOCTL, 0), "ioctl"},
{ERR_PACK(0, SYS_F_STAT, 0), "stat"},
{ERR_PACK(0, SYS_F_FCNTL, 0), "fcntl"},
{ERR_PACK(0, SYS_F_FSTAT, 0), "fstat"},
{0, NULL},
};
static ERR_STRING_DATA ERR_str_reasons[] = {
{ERR_R_SYS_LIB, "system lib"},
{ERR_R_BN_LIB, "BN lib"},
{ERR_R_RSA_LIB, "RSA lib"},
{ERR_R_DH_LIB, "DH lib"},
{ERR_R_EVP_LIB, "EVP lib"},
{ERR_R_BUF_LIB, "BUF lib"},
{ERR_R_OBJ_LIB, "OBJ lib"},
{ERR_R_PEM_LIB, "PEM lib"},
{ERR_R_DSA_LIB, "DSA lib"},
{ERR_R_X509_LIB, "X509 lib"},
{ERR_R_ASN1_LIB, "ASN1 lib"},
{ERR_R_EC_LIB, "EC lib"},
{ERR_R_BIO_LIB, "BIO lib"},
{ERR_R_PKCS7_LIB, "PKCS7 lib"},
{ERR_R_X509V3_LIB, "X509V3 lib"},
{ERR_R_ENGINE_LIB, "ENGINE lib"},
{ERR_R_UI_LIB, "UI lib"},
{ERR_R_OSSL_STORE_LIB, "STORE lib"},
{ERR_R_ECDSA_LIB, "ECDSA lib"},
{ERR_R_NESTED_ASN1_ERROR, "nested asn1 error"},
{ERR_R_MISSING_ASN1_EOS, "missing asn1 eos"},
{ERR_R_FATAL, "fatal"},
{ERR_R_MALLOC_FAILURE, "malloc failure"},
{ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED,
"called a function you should not call"},
{ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"},
{ERR_R_INTERNAL_ERROR, "internal error"},
{ERR_R_DISABLED, "called a function that was disabled at compile-time"},
{ERR_R_INIT_FAIL, "init fail"},
{ERR_R_OPERATION_FAIL, "operation fail"},
{0, NULL},
};
#endif
static CRYPTO_ONCE err_init = CRYPTO_ONCE_STATIC_INIT;
static int set_err_thread_local;
static CRYPTO_THREAD_LOCAL err_thread_local;
static CRYPTO_ONCE err_string_init = CRYPTO_ONCE_STATIC_INIT;
static CRYPTO_RWLOCK *err_string_lock;
static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *);
/*
* The internal state
*/
static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL;
static int int_err_library_number = ERR_LIB_USER;
static unsigned long get_error_values(int inc, int top, const char **file,
int *line, const char **data,
int *flags);
static unsigned long err_string_data_hash(const ERR_STRING_DATA *a)
{
unsigned long ret, l;
l = a->error;
ret = l ^ ERR_GET_LIB(l) ^ ERR_GET_FUNC(l);
return (ret ^ ret % 19 * 13);
}
static int err_string_data_cmp(const ERR_STRING_DATA *a,
const ERR_STRING_DATA *b)
{
if (a->error == b->error)
return 0;
return a->error > b->error ? 1 : -1;
}
static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d)
{
ERR_STRING_DATA *p = NULL;
CRYPTO_THREAD_read_lock(err_string_lock);
p = lh_ERR_STRING_DATA_retrieve(int_error_hash, d);
CRYPTO_THREAD_unlock(err_string_lock);
return p;
}
#ifndef OPENSSL_NO_ERR
/* A measurement on Linux 2018-11-21 showed about 3.5kib */
# define SPACE_SYS_STR_REASONS 4 * 1024
# define NUM_SYS_STR_REASONS 127
static ERR_STRING_DATA SYS_str_reasons[NUM_SYS_STR_REASONS + 1];
/*
* SYS_str_reasons is filled with copies of strerror() results at
* initialization. 'errno' values up to 127 should cover all usual errors,
* others will be displayed numerically by ERR_error_string. It is crucial
* that we have something for each reason code that occurs in
* ERR_str_reasons, or bogus reason strings will be returned for SYSerr(),
* which always gets an errno value and never one of those 'standard' reason
* codes.
*/
static void build_SYS_str_reasons(void)
{
/* OPENSSL_malloc cannot be used here, use static storage instead */
static char strerror_pool[SPACE_SYS_STR_REASONS];
char *cur = strerror_pool;
size_t cnt = 0;
static int init = 1;
int i;
int saveerrno = get_last_sys_error();
CRYPTO_THREAD_write_lock(err_string_lock);
if (!init) {
CRYPTO_THREAD_unlock(err_string_lock);
return;
}
for (i = 1; i <= NUM_SYS_STR_REASONS; i++) {
ERR_STRING_DATA *str = &SYS_str_reasons[i - 1];
str->error = ERR_PACK(ERR_LIB_SYS, 0, i);
if (str->string == NULL) {
if (openssl_strerror_r(i, cur, sizeof(strerror_pool) - cnt)) {
size_t l = strlen(cur);
str->string = cur;
cnt += l;
if (cnt > sizeof(strerror_pool))
cnt = sizeof(strerror_pool);
cur += l;
/*
* VMS has an unusual quirk of adding spaces at the end of
* some (most? all?) messages. Lets trim them off.
*/
while (ossl_isspace(cur[-1])) {
cur--;
cnt--;
}
*cur++ = '\0';
cnt++;
}
}
if (str->string == NULL)
str->string = "unknown";
}
/*
* Now we still have SYS_str_reasons[NUM_SYS_STR_REASONS] = {0, NULL}, as
* required by ERR_load_strings.
*/
init = 0;
CRYPTO_THREAD_unlock(err_string_lock);
/* openssl_strerror_r could change errno, but we want to preserve it */
set_sys_error(saveerrno);
err_load_strings(SYS_str_reasons);
}
#endif
#define err_clear_data(p, i) \
do { \
if ((p)->err_data_flags[i] & ERR_TXT_MALLOCED) {\
OPENSSL_free((p)->err_data[i]); \
(p)->err_data[i] = NULL; \
} \
(p)->err_data_flags[i] = 0; \
} while (0)
#define err_clear(p, i) \
do { \
err_clear_data(p, i); \
(p)->err_flags[i] = 0; \
(p)->err_buffer[i] = 0; \
(p)->err_file[i] = NULL; \
(p)->err_line[i] = -1; \
} while (0)
static void ERR_STATE_free(ERR_STATE *s)
{
int i;
if (s == NULL)
return;
for (i = 0; i < ERR_NUM_ERRORS; i++) {
err_clear_data(s, i);
}
OPENSSL_free(s);
}
DEFINE_RUN_ONCE_STATIC(do_err_strings_init)
{
if (!OPENSSL_init_crypto(0, NULL))
return 0;
err_string_lock = CRYPTO_THREAD_lock_new();
if (err_string_lock == NULL)
return 0;
int_error_hash = lh_ERR_STRING_DATA_new(err_string_data_hash,
err_string_data_cmp);
if (int_error_hash == NULL) {
CRYPTO_THREAD_lock_free(err_string_lock);
err_string_lock = NULL;
return 0;
}
return 1;
}
void err_cleanup(void)
{
if (set_err_thread_local != 0)
CRYPTO_THREAD_cleanup_local(&err_thread_local);
CRYPTO_THREAD_lock_free(err_string_lock);
err_string_lock = NULL;
lh_ERR_STRING_DATA_free(int_error_hash);
int_error_hash = NULL;
}
/*
* Legacy; pack in the library.
*/
static void err_patch(int lib, ERR_STRING_DATA *str)
{
unsigned long plib = ERR_PACK(lib, 0, 0);
for (; str->error != 0; str++)
str->error |= plib;
}
/*
* Hash in |str| error strings. Assumes the URN_ONCE was done.
*/
static int err_load_strings(const ERR_STRING_DATA *str)
{
CRYPTO_THREAD_write_lock(err_string_lock);
for (; str->error; str++)
(void)lh_ERR_STRING_DATA_insert(int_error_hash,
(ERR_STRING_DATA *)str);
CRYPTO_THREAD_unlock(err_string_lock);
return 1;
}
int ERR_load_ERR_strings(void)
{
#ifndef OPENSSL_NO_ERR
if (!RUN_ONCE(&err_string_init, do_err_strings_init))
return 0;
err_load_strings(ERR_str_libraries);
err_load_strings(ERR_str_reasons);
err_patch(ERR_LIB_SYS, ERR_str_functs);
err_load_strings(ERR_str_functs);
build_SYS_str_reasons();
#endif
return 1;
}
int ERR_load_strings(int lib, ERR_STRING_DATA *str)
{
if (ERR_load_ERR_strings() == 0)
return 0;
err_patch(lib, str);
err_load_strings(str);
return 1;
}
int ERR_load_strings_const(const ERR_STRING_DATA *str)
{
if (ERR_load_ERR_strings() == 0)
return 0;
err_load_strings(str);
return 1;
}
int ERR_unload_strings(int lib, ERR_STRING_DATA *str)
{
if (!RUN_ONCE(&err_string_init, do_err_strings_init))
return 0;
CRYPTO_THREAD_write_lock(err_string_lock);
/*
* We don't need to ERR_PACK the lib, since that was done (to
* the table) when it was loaded.
*/
for (; str->error; str++)
(void)lh_ERR_STRING_DATA_delete(int_error_hash, str);
CRYPTO_THREAD_unlock(err_string_lock);
return 1;
}
void err_free_strings_int(void)
{
if (!RUN_ONCE(&err_string_init, do_err_strings_init))
return;
}
/********************************************************/
void ERR_put_error(int lib, int func, int reason, const char *file, int line)
{
ERR_STATE *es;
#ifdef _OSD_POSIX
/*
* In the BS2000-OSD POSIX subsystem, the compiler generates path names
* in the form "*POSIX(/etc/passwd)". This dirty hack strips them to
* something sensible. @@@ We shouldn't modify a const string, though.
*/
if (strncmp(file, "*POSIX(", sizeof("*POSIX(") - 1) == 0) {
char *end;
/* Skip the "*POSIX(" prefix */
file += sizeof("*POSIX(") - 1;
end = &file[strlen(file) - 1];
if (*end == ')')
*end = '\0';
/* Optional: use the basename of the path only. */
if ((end = strrchr(file, '/')) != NULL)
file = &end[1];
}
#endif
es = ERR_get_state();
if (es == NULL)
return;
es->top = (es->top + 1) % ERR_NUM_ERRORS;
if (es->top == es->bottom)
es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
es->err_flags[es->top] = 0;
es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
es->err_file[es->top] = file;
es->err_line[es->top] = line;
err_clear_data(es, es->top);
}
void ERR_clear_error(void)
{
int i;
ERR_STATE *es;
es = ERR_get_state();
if (es == NULL)
return;
for (i = 0; i < ERR_NUM_ERRORS; i++) {
err_clear(es, i);
}
es->top = es->bottom = 0;
}
unsigned long ERR_get_error(void)
{
return get_error_values(1, 0, NULL, NULL, NULL, NULL);
}
unsigned long ERR_get_error_line(const char **file, int *line)
{
return get_error_values(1, 0, file, line, NULL, NULL);
}
unsigned long ERR_get_error_line_data(const char **file, int *line,
const char **data, int *flags)
{
return get_error_values(1, 0, file, line, data, flags);
}
unsigned long ERR_peek_error(void)
{
return get_error_values(0, 0, NULL, NULL, NULL, NULL);
}
unsigned long ERR_peek_error_line(const char **file, int *line)
{
return get_error_values(0, 0, file, line, NULL, NULL);
}
unsigned long ERR_peek_error_line_data(const char **file, int *line,
const char **data, int *flags)
{
return get_error_values(0, 0, file, line, data, flags);
}
unsigned long ERR_peek_last_error(void)
{
return get_error_values(0, 1, NULL, NULL, NULL, NULL);
}
unsigned long ERR_peek_last_error_line(const char **file, int *line)
{
return get_error_values(0, 1, file, line, NULL, NULL);
}
unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
const char **data, int *flags)
{
return get_error_values(0, 1, file, line, data, flags);
}
static unsigned long get_error_values(int inc, int top, const char **file,
int *line, const char **data,
int *flags)
{
int i = 0;
ERR_STATE *es;
unsigned long ret;
es = ERR_get_state();
if (es == NULL)
return 0;
if (inc && top) {
if (file)
*file = "";
if (line)
*line = 0;
if (data)
*data = "";
if (flags)
*flags = 0;
return ERR_R_INTERNAL_ERROR;
}
+ while (es->bottom != es->top) {
+ if (es->err_flags[es->top] & ERR_FLAG_CLEAR) {
+ err_clear(es, es->top);
+ es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1;
+ continue;
+ }
+ i = (es->bottom + 1) % ERR_NUM_ERRORS;
+ if (es->err_flags[i] & ERR_FLAG_CLEAR) {
+ es->bottom = i;
+ err_clear(es, es->bottom);
+ continue;
+ }
+ break;
+ }
+
if (es->bottom == es->top)
return 0;
+
if (top)
i = es->top; /* last error */
else
i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
ret = es->err_buffer[i];
if (inc) {
es->bottom = i;
es->err_buffer[i] = 0;
}
if (file != NULL && line != NULL) {
if (es->err_file[i] == NULL) {
*file = "NA";
*line = 0;
} else {
*file = es->err_file[i];
*line = es->err_line[i];
}
}
if (data == NULL) {
if (inc) {
err_clear_data(es, i);
}
} else {
if (es->err_data[i] == NULL) {
*data = "";
if (flags != NULL)
*flags = 0;
} else {
*data = es->err_data[i];
if (flags != NULL)
*flags = es->err_data_flags[i];
}
}
return ret;
}
void ERR_error_string_n(unsigned long e, char *buf, size_t len)
{
char lsbuf[64], fsbuf[64], rsbuf[64];
const char *ls, *fs, *rs;
unsigned long l, f, r;
if (len == 0)
return;
l = ERR_GET_LIB(e);
ls = ERR_lib_error_string(e);
if (ls == NULL) {
BIO_snprintf(lsbuf, sizeof(lsbuf), "lib(%lu)", l);
ls = lsbuf;
}
fs = ERR_func_error_string(e);
f = ERR_GET_FUNC(e);
if (fs == NULL) {
BIO_snprintf(fsbuf, sizeof(fsbuf), "func(%lu)", f);
fs = fsbuf;
}
rs = ERR_reason_error_string(e);
r = ERR_GET_REASON(e);
if (rs == NULL) {
BIO_snprintf(rsbuf, sizeof(rsbuf), "reason(%lu)", r);
rs = rsbuf;
}
BIO_snprintf(buf, len, "error:%08lX:%s:%s:%s", e, ls, fs, rs);
if (strlen(buf) == len - 1) {
/* Didn't fit; use a minimal format. */
BIO_snprintf(buf, len, "err:%lx:%lx:%lx:%lx", e, l, f, r);
}
}
/*
* ERR_error_string_n should be used instead for ret != NULL as
* ERR_error_string cannot know how large the buffer is
*/
char *ERR_error_string(unsigned long e, char *ret)
{
static char buf[256];
if (ret == NULL)
ret = buf;
ERR_error_string_n(e, ret, (int)sizeof(buf));
return ret;
}
const char *ERR_lib_error_string(unsigned long e)
{
ERR_STRING_DATA d, *p;
unsigned long l;
if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
return NULL;
}
l = ERR_GET_LIB(e);
d.error = ERR_PACK(l, 0, 0);
p = int_err_get_item(&d);
return ((p == NULL) ? NULL : p->string);
}
const char *ERR_func_error_string(unsigned long e)
{
ERR_STRING_DATA d, *p;
unsigned long l, f;
if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
return NULL;
}
l = ERR_GET_LIB(e);
f = ERR_GET_FUNC(e);
d.error = ERR_PACK(l, f, 0);
p = int_err_get_item(&d);
return ((p == NULL) ? NULL : p->string);
}
const char *ERR_reason_error_string(unsigned long e)
{
ERR_STRING_DATA d, *p = NULL;
unsigned long l, r;
if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
return NULL;
}
l = ERR_GET_LIB(e);
r = ERR_GET_REASON(e);
d.error = ERR_PACK(l, 0, r);
p = int_err_get_item(&d);
if (!p) {
d.error = ERR_PACK(0, 0, r);
p = int_err_get_item(&d);
}
return ((p == NULL) ? NULL : p->string);
}
void err_delete_thread_state(void)
{
ERR_STATE *state = CRYPTO_THREAD_get_local(&err_thread_local);
if (state == NULL)
return;
CRYPTO_THREAD_set_local(&err_thread_local, NULL);
ERR_STATE_free(state);
}
#if OPENSSL_API_COMPAT < 0x10100000L
void ERR_remove_thread_state(void *dummy)
{
}
#endif
#if OPENSSL_API_COMPAT < 0x10000000L
void ERR_remove_state(unsigned long pid)
{
}
#endif
DEFINE_RUN_ONCE_STATIC(err_do_init)
{
set_err_thread_local = 1;
return CRYPTO_THREAD_init_local(&err_thread_local, NULL);
}
ERR_STATE *ERR_get_state(void)
{
ERR_STATE *state;
int saveerrno = get_last_sys_error();
if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
return NULL;
if (!RUN_ONCE(&err_init, err_do_init))
return NULL;
state = CRYPTO_THREAD_get_local(&err_thread_local);
if (state == (ERR_STATE*)-1)
return NULL;
if (state == NULL) {
if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1))
return NULL;
if ((state = OPENSSL_zalloc(sizeof(*state))) == NULL) {
CRYPTO_THREAD_set_local(&err_thread_local, NULL);
return NULL;
}
if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ERR_STATE)
|| !CRYPTO_THREAD_set_local(&err_thread_local, state)) {
ERR_STATE_free(state);
CRYPTO_THREAD_set_local(&err_thread_local, NULL);
return NULL;
}
/* Ignore failures from these */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
}
set_sys_error(saveerrno);
return state;
}
/*
* err_shelve_state returns the current thread local error state
* and freezes the error module until err_unshelve_state is called.
*/
int err_shelve_state(void **state)
{
int saveerrno = get_last_sys_error();
/*
* Note, at present our only caller is OPENSSL_init_crypto(), indirectly
* via ossl_init_load_crypto_nodelete(), by which point the requested
* "base" initialization has already been performed, so the below call is a
* NOOP, that re-enters OPENSSL_init_crypto() only to quickly return.
*
* If are no other valid callers of this function, the call below can be
* removed, avoiding the re-entry into OPENSSL_init_crypto(). If there are
* potential uses that are not from inside OPENSSL_init_crypto(), then this
* call is needed, but some care is required to make sure that the re-entry
* remains a NOOP.
*/
if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
return 0;
if (!RUN_ONCE(&err_init, err_do_init))
return 0;
*state = CRYPTO_THREAD_get_local(&err_thread_local);
if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1))
return 0;
set_sys_error(saveerrno);
return 1;
}
/*
* err_unshelve_state restores the error state that was returned
* by err_shelve_state previously.
*/
void err_unshelve_state(void* state)
{
if (state != (void*)-1)
CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)state);
}
int ERR_get_next_error_library(void)
{
int ret;
if (!RUN_ONCE(&err_string_init, do_err_strings_init))
return 0;
CRYPTO_THREAD_write_lock(err_string_lock);
ret = int_err_library_number++;
CRYPTO_THREAD_unlock(err_string_lock);
return ret;
}
static int err_set_error_data_int(char *data, int flags)
{
ERR_STATE *es;
int i;
es = ERR_get_state();
if (es == NULL)
return 0;
i = es->top;
err_clear_data(es, i);
es->err_data[i] = data;
es->err_data_flags[i] = flags;
return 1;
}
void ERR_set_error_data(char *data, int flags)
{
/*
* This function is void so we cannot propagate the error return. Since it
* is also in the public API we can't change the return type.
*/
err_set_error_data_int(data, flags);
}
void ERR_add_error_data(int num, ...)
{
va_list args;
va_start(args, num);
ERR_add_error_vdata(num, args);
va_end(args);
}
void ERR_add_error_vdata(int num, va_list args)
{
int i, n, s;
char *str, *p, *a;
s = 80;
if ((str = OPENSSL_malloc(s + 1)) == NULL) {
/* ERRerr(ERR_F_ERR_ADD_ERROR_VDATA, ERR_R_MALLOC_FAILURE); */
return;
}
str[0] = '\0';
n = 0;
for (i = 0; i < num; i++) {
a = va_arg(args, char *);
if (a == NULL)
a = "<NULL>";
n += strlen(a);
if (n > s) {
s = n + 20;
p = OPENSSL_realloc(str, s + 1);
if (p == NULL) {
OPENSSL_free(str);
return;
}
str = p;
}
OPENSSL_strlcat(str, a, (size_t)s + 1);
}
if (!err_set_error_data_int(str, ERR_TXT_MALLOCED | ERR_TXT_STRING))
OPENSSL_free(str);
}
int ERR_set_mark(void)
{
ERR_STATE *es;
es = ERR_get_state();
if (es == NULL)
return 0;
if (es->bottom == es->top)
return 0;
es->err_flags[es->top] |= ERR_FLAG_MARK;
return 1;
}
int ERR_pop_to_mark(void)
{
ERR_STATE *es;
es = ERR_get_state();
if (es == NULL)
return 0;
while (es->bottom != es->top
&& (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
err_clear(es, es->top);
es->top = es->top > 0 ? es->top - 1 : ERR_NUM_ERRORS - 1;
}
if (es->bottom == es->top)
return 0;
es->err_flags[es->top] &= ~ERR_FLAG_MARK;
return 1;
}
int ERR_clear_last_mark(void)
{
ERR_STATE *es;
int top;
es = ERR_get_state();
if (es == NULL)
return 0;
top = es->top;
while (es->bottom != top
&& (es->err_flags[top] & ERR_FLAG_MARK) == 0) {
top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
}
if (es->bottom == top)
return 0;
es->err_flags[top] &= ~ERR_FLAG_MARK;
return 1;
}
-#ifdef UINTPTR_T
-# undef UINTPTR_T
-#endif
-/*
- * uintptr_t is the answer, but unfortunately C89, current "least common
- * denominator" doesn't define it. Most legacy platforms typedef it anyway,
- * so that attempt to fill the gaps means that one would have to identify
- * that track these gaps, which would be undesirable. Macro it is...
- */
-#if defined(__VMS) && __INITIAL_POINTER_SIZE==64
-/*
- * But we can't use size_t on VMS, because it adheres to sizeof(size_t)==4
- * even in 64-bit builds, which means that it won't work as mask.
- */
-# define UINTPTR_T unsigned long long
-#else
-# define UINTPTR_T size_t
-#endif
-
void err_clear_last_constant_time(int clear)
{
ERR_STATE *es;
int top;
es = ERR_get_state();
if (es == NULL)
return;
top = es->top;
- es->err_flags[top] &= ~(0 - clear);
- es->err_buffer[top] &= ~(0UL - clear);
- es->err_file[top] = (const char *)((UINTPTR_T)es->err_file[top] &
- ~((UINTPTR_T)0 - clear));
- es->err_line[top] |= 0 - clear;
-
- es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS;
+ /*
+ * Flag error as cleared but remove it elsewhere to avoid two errors
+ * accessing the same error stack location, revealing timing information.
+ */
+ clear = constant_time_select_int(constant_time_eq_int(clear, 0),
+ 0, ERR_FLAG_CLEAR);
+ es->err_flags[top] |= clear;
}
diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c
index f78dab767865..6693f270b694 100644
--- a/crypto/evp/digest.c
+++ b/crypto/evp/digest.c
@@ -1,298 +1,301 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/engine.h>
#include "internal/evp_int.h"
#include "evp_locl.h"
/* This call frees resources associated with the context */
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx)
{
if (ctx == NULL)
return 1;
/*
* Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because
* sometimes only copies of the context are ever finalised.
*/
if (ctx->digest && ctx->digest->cleanup
&& !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED))
ctx->digest->cleanup(ctx);
if (ctx->digest && ctx->digest->ctx_size && ctx->md_data
&& !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) {
OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
}
/*
* pctx should be freed by the user of EVP_MD_CTX
* if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set
*/
if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX))
EVP_PKEY_CTX_free(ctx->pctx);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(ctx->engine);
#endif
OPENSSL_cleanse(ctx, sizeof(*ctx));
return 1;
}
EVP_MD_CTX *EVP_MD_CTX_new(void)
{
return OPENSSL_zalloc(sizeof(EVP_MD_CTX));
}
void EVP_MD_CTX_free(EVP_MD_CTX *ctx)
{
EVP_MD_CTX_reset(ctx);
OPENSSL_free(ctx);
}
int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type)
{
EVP_MD_CTX_reset(ctx);
return EVP_DigestInit_ex(ctx, type, NULL);
}
int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl)
{
EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
#ifndef OPENSSL_NO_ENGINE
/*
* Whether it's nice or not, "Inits" can be used on "Final"'d contexts so
* this context may already have an ENGINE! Try to avoid releasing the
* previous handle, re-querying for an ENGINE, and having a
* reinitialisation, when it may all be unnecessary.
*/
if (ctx->engine && ctx->digest &&
(type == NULL || (type->type == ctx->digest->type)))
goto skip_to_init;
if (type) {
/*
* Ensure an ENGINE left lying around from last time is cleared (the
* previous check attempted to avoid this if the same ENGINE and
* EVP_MD could be used).
*/
ENGINE_finish(ctx->engine);
if (impl != NULL) {
if (!ENGINE_init(impl)) {
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
return 0;
}
} else {
/* Ask if an ENGINE is reserved for this job */
impl = ENGINE_get_digest_engine(type->type);
}
if (impl != NULL) {
/* There's an ENGINE for this job ... (apparently) */
const EVP_MD *d = ENGINE_get_digest(impl, type->type);
if (d == NULL) {
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR);
ENGINE_finish(impl);
return 0;
}
/* We'll use the ENGINE's private digest definition */
type = d;
/*
* Store the ENGINE functional reference so we know 'type' came
* from an ENGINE and we need to release it when done.
*/
ctx->engine = impl;
} else
ctx->engine = NULL;
} else {
if (!ctx->digest) {
EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_NO_DIGEST_SET);
return 0;
}
type = ctx->digest;
}
#endif
if (ctx->digest != type) {
if (ctx->digest && ctx->digest->ctx_size) {
OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size);
ctx->md_data = NULL;
}
ctx->digest = type;
if (!(ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) && type->ctx_size) {
ctx->update = type->update;
ctx->md_data = OPENSSL_zalloc(type->ctx_size);
if (ctx->md_data == NULL) {
EVPerr(EVP_F_EVP_DIGESTINIT_EX, ERR_R_MALLOC_FAILURE);
return 0;
}
}
}
#ifndef OPENSSL_NO_ENGINE
skip_to_init:
#endif
if (ctx->pctx) {
int r;
r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG,
EVP_PKEY_CTRL_DIGESTINIT, 0, ctx);
if (r <= 0 && (r != -2))
return 0;
}
if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT)
return 1;
return ctx->digest->init(ctx);
}
int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *data, size_t count)
{
+ if (count == 0)
+ return 1;
+
return ctx->update(ctx, data, count);
}
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
{
int ret;
ret = EVP_DigestFinal_ex(ctx, md, size);
EVP_MD_CTX_reset(ctx);
return ret;
}
/* The caller can assume that this removes any secret data from the context */
int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *size)
{
int ret;
OPENSSL_assert(ctx->digest->md_size <= EVP_MAX_MD_SIZE);
ret = ctx->digest->final(ctx, md);
if (size != NULL)
*size = ctx->digest->md_size;
if (ctx->digest->cleanup) {
ctx->digest->cleanup(ctx);
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
}
OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
return ret;
}
int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t size)
{
int ret = 0;
if (ctx->digest->flags & EVP_MD_FLAG_XOF
&& size <= INT_MAX
&& ctx->digest->md_ctrl(ctx, EVP_MD_CTRL_XOF_LEN, (int)size, NULL)) {
ret = ctx->digest->final(ctx, md);
if (ctx->digest->cleanup != NULL) {
ctx->digest->cleanup(ctx);
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_CLEANED);
}
OPENSSL_cleanse(ctx->md_data, ctx->digest->ctx_size);
} else {
EVPerr(EVP_F_EVP_DIGESTFINALXOF, EVP_R_NOT_XOF_OR_INVALID_LENGTH);
}
return ret;
}
int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in)
{
EVP_MD_CTX_reset(out);
return EVP_MD_CTX_copy_ex(out, in);
}
int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
{
unsigned char *tmp_buf;
if ((in == NULL) || (in->digest == NULL)) {
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, EVP_R_INPUT_NOT_INITIALIZED);
return 0;
}
#ifndef OPENSSL_NO_ENGINE
/* Make sure it's safe to copy a digest context using an ENGINE */
if (in->engine && !ENGINE_init(in->engine)) {
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_ENGINE_LIB);
return 0;
}
#endif
if (out->digest == in->digest) {
tmp_buf = out->md_data;
EVP_MD_CTX_set_flags(out, EVP_MD_CTX_FLAG_REUSE);
} else
tmp_buf = NULL;
EVP_MD_CTX_reset(out);
memcpy(out, in, sizeof(*out));
/* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */
EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX);
/* Null these variables, since they are getting fixed up
* properly below. Anything else may cause a memleak and/or
* double free if any of the memory allocations below fail
*/
out->md_data = NULL;
out->pctx = NULL;
if (in->md_data && out->digest->ctx_size) {
if (tmp_buf)
out->md_data = tmp_buf;
else {
out->md_data = OPENSSL_malloc(out->digest->ctx_size);
if (out->md_data == NULL) {
EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_MALLOC_FAILURE);
return 0;
}
}
memcpy(out->md_data, in->md_data, out->digest->ctx_size);
}
out->update = in->update;
if (in->pctx) {
out->pctx = EVP_PKEY_CTX_dup(in->pctx);
if (!out->pctx) {
EVP_MD_CTX_reset(out);
return 0;
}
}
if (out->digest->copy)
return out->digest->copy(out, in);
return 1;
}
int EVP_Digest(const void *data, size_t count,
unsigned char *md, unsigned int *size, const EVP_MD *type,
ENGINE *impl)
{
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
int ret;
if (ctx == NULL)
return 0;
EVP_MD_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_ONESHOT);
ret = EVP_DigestInit_ex(ctx, type, impl)
&& EVP_DigestUpdate(ctx, data, count)
&& EVP_DigestFinal_ex(ctx, md, size);
EVP_MD_CTX_free(ctx);
return ret;
}
int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2)
{
if (ctx->digest && ctx->digest->md_ctrl) {
int ret = ctx->digest->md_ctrl(ctx, cmd, p1, p2);
if (ret <= 0)
return 0;
return 1;
}
return 0;
}
diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c
index 39eb4f379a99..68322e1982b8 100644
--- a/crypto/evp/e_aes.c
+++ b/crypto/evp/e_aes.c
@@ -1,4210 +1,4214 @@
/*
- * Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <assert.h>
#include <openssl/aes.h>
#include "internal/evp_int.h"
#include "modes_lcl.h"
#include <openssl/rand.h>
#include "evp_locl.h"
typedef struct {
union {
double align;
AES_KEY ks;
} ks;
block128_f block;
union {
cbc128_f cbc;
ctr128_f ctr;
} stream;
} EVP_AES_KEY;
typedef struct {
union {
double align;
AES_KEY ks;
} ks; /* AES key schedule to use */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
GCM128_CONTEXT gcm;
unsigned char *iv; /* Temporary IV store */
int ivlen; /* IV length */
int taglen;
int iv_gen; /* It is OK to generate IVs */
int tls_aad_len; /* TLS AAD length */
ctr128_f ctr;
} EVP_AES_GCM_CTX;
typedef struct {
union {
double align;
AES_KEY ks;
} ks1, ks2; /* AES key schedules to use */
XTS128_CONTEXT xts;
void (*stream) (const unsigned char *in,
unsigned char *out, size_t length,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
} EVP_AES_XTS_CTX;
typedef struct {
union {
double align;
AES_KEY ks;
} ks; /* AES key schedule to use */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
int tag_set; /* Set if tag is valid */
int len_set; /* Set if message length set */
int L, M; /* L and M parameters from RFC3610 */
int tls_aad_len; /* TLS AAD length */
CCM128_CONTEXT ccm;
ccm128_f str;
} EVP_AES_CCM_CTX;
#ifndef OPENSSL_NO_OCB
typedef struct {
union {
double align;
AES_KEY ks;
} ksenc; /* AES key schedule to use for encryption */
union {
double align;
AES_KEY ks;
} ksdec; /* AES key schedule to use for decryption */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
OCB128_CONTEXT ocb;
unsigned char *iv; /* Temporary IV store */
unsigned char tag[16];
unsigned char data_buf[16]; /* Store partial data blocks */
unsigned char aad_buf[16]; /* Store partial AAD blocks */
int data_buf_len;
int aad_buf_len;
int ivlen; /* IV length */
int taglen;
} EVP_AES_OCB_CTX;
#endif
#define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4))
#ifdef VPAES_ASM
int vpaes_set_encrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
int vpaes_set_decrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
void vpaes_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void vpaes_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void vpaes_cbc_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key, unsigned char *ivec, int enc);
#endif
#ifdef BSAES_ASM
void bsaes_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char ivec[16], int enc);
void bsaes_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
const unsigned char ivec[16]);
void bsaes_xts_encrypt(const unsigned char *inp, unsigned char *out,
size_t len, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char iv[16]);
void bsaes_xts_decrypt(const unsigned char *inp, unsigned char *out,
size_t len, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char iv[16]);
#endif
#ifdef AES_CTR_ASM
void AES_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
const unsigned char ivec[AES_BLOCK_SIZE]);
#endif
#ifdef AES_XTS_ASM
void AES_xts_encrypt(const unsigned char *inp, unsigned char *out, size_t len,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
void AES_xts_decrypt(const unsigned char *inp, unsigned char *out, size_t len,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
#endif
/* increment counter (64-bit int) by 1 */
static void ctr64_inc(unsigned char *counter)
{
int n = 8;
unsigned char c;
do {
--n;
c = counter[n];
++c;
counter[n] = c;
if (c)
return;
} while (n);
}
#if defined(OPENSSL_CPUID_OBJ) && (defined(__powerpc__) || defined(__ppc__) || defined(_ARCH_PPC))
# include "ppc_arch.h"
# ifdef VPAES_ASM
# define VPAES_CAPABLE (OPENSSL_ppccap_P & PPC_ALTIVEC)
# endif
# define HWAES_CAPABLE (OPENSSL_ppccap_P & PPC_CRYPTO207)
# define HWAES_set_encrypt_key aes_p8_set_encrypt_key
# define HWAES_set_decrypt_key aes_p8_set_decrypt_key
# define HWAES_encrypt aes_p8_encrypt
# define HWAES_decrypt aes_p8_decrypt
# define HWAES_cbc_encrypt aes_p8_cbc_encrypt
# define HWAES_ctr32_encrypt_blocks aes_p8_ctr32_encrypt_blocks
# define HWAES_xts_encrypt aes_p8_xts_encrypt
# define HWAES_xts_decrypt aes_p8_xts_decrypt
#endif
#if defined(AES_ASM) && !defined(I386_ONLY) && ( \
((defined(__i386) || defined(__i386__) || \
defined(_M_IX86)) && defined(OPENSSL_IA32_SSE2))|| \
defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64) )
extern unsigned int OPENSSL_ia32cap_P[];
# ifdef VPAES_ASM
# define VPAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
# endif
# ifdef BSAES_ASM
# define BSAES_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(41-32)))
# endif
/*
* AES-NI section
*/
# define AESNI_CAPABLE (OPENSSL_ia32cap_P[1]&(1<<(57-32)))
int aesni_set_encrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
AES_KEY *key);
void aesni_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void aesni_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void aesni_ecb_encrypt(const unsigned char *in,
unsigned char *out,
size_t length, const AES_KEY *key, int enc);
void aesni_cbc_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key, unsigned char *ivec, int enc);
void aesni_ctr32_encrypt_blocks(const unsigned char *in,
unsigned char *out,
size_t blocks,
const void *key, const unsigned char *ivec);
void aesni_xts_encrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
void aesni_xts_decrypt(const unsigned char *in,
unsigned char *out,
size_t length,
const AES_KEY *key1, const AES_KEY *key2,
const unsigned char iv[16]);
void aesni_ccm64_encrypt_blocks(const unsigned char *in,
unsigned char *out,
size_t blocks,
const void *key,
const unsigned char ivec[16],
unsigned char cmac[16]);
void aesni_ccm64_decrypt_blocks(const unsigned char *in,
unsigned char *out,
size_t blocks,
const void *key,
const unsigned char ivec[16],
unsigned char cmac[16]);
# if defined(__x86_64) || defined(__x86_64__) || defined(_M_AMD64) || defined(_M_X64)
size_t aesni_gcm_encrypt(const unsigned char *in,
unsigned char *out,
size_t len,
const void *key, unsigned char ivec[16], u64 *Xi);
# define AES_gcm_encrypt aesni_gcm_encrypt
size_t aesni_gcm_decrypt(const unsigned char *in,
unsigned char *out,
size_t len,
const void *key, unsigned char ivec[16], u64 *Xi);
# define AES_gcm_decrypt aesni_gcm_decrypt
void gcm_ghash_avx(u64 Xi[2], const u128 Htable[16], const u8 *in,
size_t len);
# define AES_GCM_ASM(gctx) (gctx->ctr==aesni_ctr32_encrypt_blocks && \
gctx->gcm.ghash==gcm_ghash_avx)
# define AES_GCM_ASM2(gctx) (gctx->gcm.block==(block128_f)aesni_encrypt && \
gctx->gcm.ghash==gcm_ghash_avx)
# undef AES_GCM_ASM2 /* minor size optimization */
# endif
static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret, mode;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
mode = EVP_CIPHER_CTX_mode(ctx);
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
ret = aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) aesni_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aesni_cbc_encrypt : NULL;
} else {
ret = aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) aesni_encrypt;
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
else
dat->stream.cbc = NULL;
}
if (ret < 0) {
EVPerr(EVP_F_AESNI_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static int aesni_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
aesni_cbc_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_encrypting(ctx));
return 1;
}
static int aesni_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
size_t bl = EVP_CIPHER_CTX_block_size(ctx);
if (len < bl)
return 1;
aesni_ecb_encrypt(in, out, len, &EVP_C_DATA(EVP_AES_KEY,ctx)->ks.ks,
EVP_CIPHER_CTX_encrypting(ctx));
return 1;
}
# define aesni_ofb_cipher aes_ofb_cipher
static int aesni_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aesni_cfb_cipher aes_cfb_cipher
static int aesni_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aesni_cfb8_cipher aes_cfb8_cipher
static int aesni_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aesni_cfb1_cipher aes_cfb1_cipher
static int aesni_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aesni_ctr_cipher aes_ctr_cipher
static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt);
gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks;
/*
* If we have an iv can set it directly, otherwise use saved IV.
*/
if (iv == NULL && gctx->iv_set)
iv = gctx->iv;
if (iv) {
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
gctx->iv_set = 1;
}
gctx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (gctx->key_set)
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
else
memcpy(gctx->iv, iv, gctx->ivlen);
gctx->iv_set = 1;
gctx->iv_gen = 0;
}
return 1;
}
# define aesni_gcm_cipher aes_gcm_cipher
static int aesni_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
/* key_len is two AES keys */
if (enc) {
aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aesni_encrypt;
xctx->stream = aesni_xts_encrypt;
} else {
aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aesni_decrypt;
xctx->stream = aesni_xts_decrypt;
}
aesni_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks2.ks);
xctx->xts.block2 = (block128_f) aesni_encrypt;
xctx->xts.key1 = &xctx->ks1;
}
if (iv) {
xctx->xts.key2 = &xctx->ks2;
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16);
}
return 1;
}
# define aesni_xts_cipher aes_xts_cipher
static int aesni_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) aesni_encrypt);
cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks :
(ccm128_f) aesni_ccm64_decrypt_blocks;
cctx->key_set = 1;
}
if (iv) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
}
# define aesni_ccm_cipher aes_ccm_cipher
static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# ifndef OPENSSL_NO_OCB
void aesni_ocb_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const void *key,
size_t start_block_num,
unsigned char offset_i[16],
const unsigned char L_[][16],
unsigned char checksum[16]);
void aesni_ocb_decrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const void *key,
size_t start_block_num,
unsigned char offset_i[16],
const unsigned char L_[][16],
unsigned char checksum[16]);
static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
do {
/*
* We set both the encrypt and decrypt key here because decrypt
* needs both. We could possibly optimise to remove setting the
* decrypt for an encryption operation.
*/
aesni_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksenc.ks);
aesni_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
(block128_f) aesni_encrypt,
(block128_f) aesni_decrypt,
enc ? aesni_ocb_encrypt
: aesni_ocb_decrypt))
return 0;
}
while (0);
/*
* If we have an iv we can set it directly, otherwise use saved IV.
*/
if (iv == NULL && octx->iv_set)
iv = octx->iv;
if (iv) {
if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
!= 1)
return 0;
octx->iv_set = 1;
}
octx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (octx->key_set)
CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
else
memcpy(octx->iv, iv, octx->ivlen);
octx->iv_set = 1;
}
return 1;
}
# define aesni_ocb_cipher aes_ocb_cipher
static int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# endif /* OPENSSL_NO_OCB */
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aesni_init_key, \
aesni_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize, \
keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aesni_##mode##_init_key, \
aesni_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return AESNI_CAPABLE?&aesni_##keylen##_##mode:&aes_##keylen##_##mode; }
#elif defined(AES_ASM) && (defined(__sparc) || defined(__sparc__))
# include "sparc_arch.h"
extern unsigned int OPENSSL_sparcv9cap_P[];
/*
* Initial Fujitsu SPARC64 X support
*/
# define HWAES_CAPABLE (OPENSSL_sparcv9cap_P[0] & SPARCV9_FJAESX)
# define HWAES_set_encrypt_key aes_fx_set_encrypt_key
# define HWAES_set_decrypt_key aes_fx_set_decrypt_key
# define HWAES_encrypt aes_fx_encrypt
# define HWAES_decrypt aes_fx_decrypt
# define HWAES_cbc_encrypt aes_fx_cbc_encrypt
# define HWAES_ctr32_encrypt_blocks aes_fx_ctr32_encrypt_blocks
# define SPARC_AES_CAPABLE (OPENSSL_sparcv9cap_P[1] & CFR_AES)
void aes_t4_set_encrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
void aes_t4_set_decrypt_key(const unsigned char *key, int bits, AES_KEY *ks);
void aes_t4_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void aes_t4_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
/*
* Key-length specific subroutines were chosen for following reason.
* Each SPARC T4 core can execute up to 8 threads which share core's
* resources. Loading as much key material to registers allows to
* minimize references to shared memory interface, as well as amount
* of instructions in inner loops [much needed on T4]. But then having
* non-key-length specific routines would require conditional branches
* either in inner loops or on subroutines' entries. Former is hardly
* acceptable, while latter means code size increase to size occupied
* by multiple key-length specific subroutines, so why fight?
*/
void aes128_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes128_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_cbc_decrypt(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
unsigned char *ivec);
void aes128_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
void aes192_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
void aes256_t4_ctr32_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key,
unsigned char *ivec);
void aes128_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char *ivec);
void aes128_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char *ivec);
void aes256_t4_xts_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char *ivec);
void aes256_t4_xts_decrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char *ivec);
static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret, mode, bits;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
mode = EVP_CIPHER_CTX_mode(ctx);
bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
ret = 0;
aes_t4_set_decrypt_key(key, bits, &dat->ks.ks);
dat->block = (block128_f) aes_t4_decrypt;
switch (bits) {
case 128:
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes128_t4_cbc_decrypt : NULL;
break;
case 192:
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes192_t4_cbc_decrypt : NULL;
break;
case 256:
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) aes256_t4_cbc_decrypt : NULL;
break;
default:
ret = -1;
}
} else {
ret = 0;
aes_t4_set_encrypt_key(key, bits, &dat->ks.ks);
dat->block = (block128_f) aes_t4_encrypt;
switch (bits) {
case 128:
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aes128_t4_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 192:
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aes192_t4_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
case 256:
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) aes256_t4_cbc_encrypt;
else if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
else
dat->stream.cbc = NULL;
break;
default:
ret = -1;
}
}
if (ret < 0) {
EVPerr(EVP_F_AES_T4_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
# define aes_t4_cbc_cipher aes_cbc_cipher
static int aes_t4_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_ecb_cipher aes_ecb_cipher
static int aes_t4_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_ofb_cipher aes_ofb_cipher
static int aes_t4_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_cfb_cipher aes_cfb_cipher
static int aes_t4_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_cfb8_cipher aes_cfb8_cipher
static int aes_t4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_cfb1_cipher aes_cfb1_cipher
static int aes_t4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define aes_t4_ctr_cipher aes_ctr_cipher
static int aes_t4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
int bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) aes_t4_encrypt);
switch (bits) {
case 128:
gctx->ctr = (ctr128_f) aes128_t4_ctr32_encrypt;
break;
case 192:
gctx->ctr = (ctr128_f) aes192_t4_ctr32_encrypt;
break;
case 256:
gctx->ctr = (ctr128_f) aes256_t4_ctr32_encrypt;
break;
default:
return 0;
}
/*
* If we have an iv can set it directly, otherwise use saved IV.
*/
if (iv == NULL && gctx->iv_set)
iv = gctx->iv;
if (iv) {
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
gctx->iv_set = 1;
}
gctx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (gctx->key_set)
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
else
memcpy(gctx->iv, iv, gctx->ivlen);
gctx->iv_set = 1;
gctx->iv_gen = 0;
}
return 1;
}
# define aes_t4_gcm_cipher aes_gcm_cipher
static int aes_t4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
int bits = EVP_CIPHER_CTX_key_length(ctx) * 4;
xctx->stream = NULL;
/* key_len is two AES keys */
if (enc) {
aes_t4_set_encrypt_key(key, bits, &xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aes_t4_encrypt;
switch (bits) {
case 128:
xctx->stream = aes128_t4_xts_encrypt;
break;
case 256:
xctx->stream = aes256_t4_xts_encrypt;
break;
default:
return 0;
}
} else {
aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) aes_t4_decrypt;
switch (bits) {
case 128:
xctx->stream = aes128_t4_xts_decrypt;
break;
case 256:
xctx->stream = aes256_t4_xts_decrypt;
break;
default:
return 0;
}
}
aes_t4_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks2.ks);
xctx->xts.block2 = (block128_f) aes_t4_encrypt;
xctx->xts.key1 = &xctx->ks1;
}
if (iv) {
xctx->xts.key2 = &xctx->ks2;
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16);
}
return 1;
}
# define aes_t4_xts_cipher aes_xts_cipher
static int aes_t4_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
int bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) aes_t4_encrypt);
cctx->str = NULL;
cctx->key_set = 1;
}
if (iv) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
}
# define aes_t4_ccm_cipher aes_ccm_cipher
static int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# ifndef OPENSSL_NO_OCB
static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
do {
/*
* We set both the encrypt and decrypt key here because decrypt
* needs both. We could possibly optimise to remove setting the
* decrypt for an encryption operation.
*/
aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksenc.ks);
aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
(block128_f) aes_t4_encrypt,
(block128_f) aes_t4_decrypt,
NULL))
return 0;
}
while (0);
/*
* If we have an iv we can set it directly, otherwise use saved IV.
*/
if (iv == NULL && octx->iv_set)
iv = octx->iv;
if (iv) {
if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
!= 1)
return 0;
octx->iv_set = 1;
}
octx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (octx->key_set)
CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
else
memcpy(octx->iv, iv, octx->ivlen);
octx->iv_set = 1;
}
return 1;
}
# define aes_t4_ocb_cipher aes_ocb_cipher
static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# endif /* OPENSSL_NO_OCB */
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_t4_init_key, \
aes_t4_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize, \
keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_t4_##mode##_init_key, \
aes_t4_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return SPARC_AES_CAPABLE?&aes_t4_##keylen##_##mode:&aes_##keylen##_##mode; }
#elif defined(OPENSSL_CPUID_OBJ) && defined(__s390__)
/*
* IBM S390X support
*/
# include "s390x_arch.h"
typedef struct {
union {
double align;
/*-
* KM-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-06)
*/
struct {
unsigned char k[32];
} param;
/* KM-AES parameter block - end */
} km;
unsigned int fc;
} S390X_AES_ECB_CTX;
typedef struct {
union {
double align;
/*-
* KMO-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-08)
*/
struct {
unsigned char cv[16];
unsigned char k[32];
} param;
/* KMO-AES parameter block - end */
} kmo;
unsigned int fc;
int res;
} S390X_AES_OFB_CTX;
typedef struct {
union {
double align;
/*-
* KMF-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-08)
*/
struct {
unsigned char cv[16];
unsigned char k[32];
} param;
/* KMF-AES parameter block - end */
} kmf;
unsigned int fc;
int res;
} S390X_AES_CFB_CTX;
typedef struct {
union {
double align;
/*-
* KMA-GCM-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-11)
*/
struct {
unsigned char reserved[12];
union {
unsigned int w;
unsigned char b[4];
} cv;
union {
unsigned long long g[2];
unsigned char b[16];
} t;
unsigned char h[16];
unsigned long long taadl;
unsigned long long tpcl;
union {
unsigned long long g[2];
unsigned int w[4];
} j0;
unsigned char k[32];
} param;
/* KMA-GCM-AES parameter block - end */
} kma;
unsigned int fc;
int key_set;
unsigned char *iv;
int ivlen;
int iv_set;
int iv_gen;
int taglen;
unsigned char ares[16];
unsigned char mres[16];
unsigned char kres[16];
int areslen;
int mreslen;
int kreslen;
int tls_aad_len;
} S390X_AES_GCM_CTX;
typedef struct {
union {
double align;
/*-
* Padding is chosen so that ccm.kmac_param.k overlaps with key.k and
* ccm.fc with key.k.rounds. Remember that on s390x, an AES_KEY's
* rounds field is used to store the function code and that the key
* schedule is not stored (if aes hardware support is detected).
*/
struct {
unsigned char pad[16];
AES_KEY k;
} key;
struct {
/*-
* KMAC-AES parameter block - begin
* (see z/Architecture Principles of Operation >= SA22-7832-08)
*/
struct {
union {
unsigned long long g[2];
unsigned char b[16];
} icv;
unsigned char k[32];
} kmac_param;
/* KMAC-AES paramater block - end */
union {
unsigned long long g[2];
unsigned char b[16];
} nonce;
union {
unsigned long long g[2];
unsigned char b[16];
} buf;
unsigned long long blocks;
int l;
int m;
int tls_aad_len;
int iv_set;
int tag_set;
int len_set;
int key_set;
unsigned char pad[140];
unsigned int fc;
} ccm;
} aes;
} S390X_AES_CCM_CTX;
/* Convert key size to function code: [16,24,32] -> [18,19,20]. */
# define S390X_AES_FC(keylen) (S390X_AES_128 + ((((keylen) << 3) - 128) >> 6))
/* Most modes of operation need km for partial block processing. */
# define S390X_aes_128_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
S390X_CAPBIT(S390X_AES_128))
# define S390X_aes_192_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
S390X_CAPBIT(S390X_AES_192))
# define S390X_aes_256_CAPABLE (OPENSSL_s390xcap_P.km[0] & \
S390X_CAPBIT(S390X_AES_256))
# define s390x_aes_init_key aes_init_key
static int s390x_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
# define S390X_aes_128_cbc_CAPABLE 1 /* checked by callee */
# define S390X_aes_192_cbc_CAPABLE 1
# define S390X_aes_256_cbc_CAPABLE 1
# define S390X_AES_CBC_CTX EVP_AES_KEY
# define s390x_aes_cbc_init_key aes_init_key
# define s390x_aes_cbc_cipher aes_cbc_cipher
static int s390x_aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define S390X_aes_128_ecb_CAPABLE S390X_aes_128_CAPABLE
# define S390X_aes_192_ecb_CAPABLE S390X_aes_192_CAPABLE
# define S390X_aes_256_ecb_CAPABLE S390X_aes_256_CAPABLE
static int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv, int enc)
{
S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);
const int keylen = EVP_CIPHER_CTX_key_length(ctx);
cctx->fc = S390X_AES_FC(keylen);
if (!enc)
cctx->fc |= S390X_DECRYPT;
memcpy(cctx->km.param.k, key, keylen);
return 1;
}
static int s390x_aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx);
s390x_km(in, len, out, cctx->fc, &cctx->km.param);
return 1;
}
# define S390X_aes_128_ofb_CAPABLE (S390X_aes_128_CAPABLE && \
(OPENSSL_s390xcap_P.kmo[0] & \
S390X_CAPBIT(S390X_AES_128)))
# define S390X_aes_192_ofb_CAPABLE (S390X_aes_192_CAPABLE && \
(OPENSSL_s390xcap_P.kmo[0] & \
S390X_CAPBIT(S390X_AES_192)))
# define S390X_aes_256_ofb_CAPABLE (S390X_aes_256_CAPABLE && \
(OPENSSL_s390xcap_P.kmo[0] & \
S390X_CAPBIT(S390X_AES_256)))
static int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *ivec, int enc)
{
S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx);
const int keylen = EVP_CIPHER_CTX_key_length(ctx);
const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
memcpy(cctx->kmo.param.cv, iv, ivlen);
memcpy(cctx->kmo.param.k, key, keylen);
cctx->fc = S390X_AES_FC(keylen);
cctx->res = 0;
return 1;
}
static int s390x_aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_OFB_CTX *cctx = EVP_C_DATA(S390X_AES_OFB_CTX, ctx);
int n = cctx->res;
int rem;
while (n && len) {
*out = *in ^ cctx->kmo.param.cv[n];
n = (n + 1) & 0xf;
--len;
++in;
++out;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kmo(in, len, out, cctx->fc, &cctx->kmo.param);
out += len;
in += len;
}
if (rem) {
s390x_km(cctx->kmo.param.cv, 16, cctx->kmo.param.cv, cctx->fc,
cctx->kmo.param.k);
while (rem--) {
out[n] = in[n] ^ cctx->kmo.param.cv[n];
++n;
}
}
cctx->res = n;
return 1;
}
# define S390X_aes_128_cfb_CAPABLE (S390X_aes_128_CAPABLE && \
(OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_128)))
# define S390X_aes_192_cfb_CAPABLE (S390X_aes_192_CAPABLE && \
(OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_192)))
# define S390X_aes_256_cfb_CAPABLE (S390X_aes_256_CAPABLE && \
(OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_256)))
static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *ivec, int enc)
{
S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx);
const int keylen = EVP_CIPHER_CTX_key_length(ctx);
const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
cctx->fc = S390X_AES_FC(keylen);
cctx->fc |= 16 << 24; /* 16 bytes cipher feedback */
if (!enc)
cctx->fc |= S390X_DECRYPT;
cctx->res = 0;
memcpy(cctx->kmf.param.cv, iv, ivlen);
memcpy(cctx->kmf.param.k, key, keylen);
return 1;
}
static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
const int keylen = EVP_CIPHER_CTX_key_length(ctx);
const int enc = EVP_CIPHER_CTX_encrypting(ctx);
int n = cctx->res;
int rem;
unsigned char tmp;
while (n && len) {
tmp = *in;
*out = cctx->kmf.param.cv[n] ^ tmp;
cctx->kmf.param.cv[n] = enc ? *out : tmp;
n = (n + 1) & 0xf;
--len;
++in;
++out;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param);
out += len;
in += len;
}
if (rem) {
s390x_km(cctx->kmf.param.cv, 16, cctx->kmf.param.cv,
S390X_AES_FC(keylen), cctx->kmf.param.k);
while (rem--) {
tmp = in[n];
out[n] = cctx->kmf.param.cv[n] ^ tmp;
cctx->kmf.param.cv[n] = enc ? out[n] : tmp;
++n;
}
}
cctx->res = n;
return 1;
}
# define S390X_aes_128_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_128))
# define S390X_aes_192_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_192))
# define S390X_aes_256_cfb8_CAPABLE (OPENSSL_s390xcap_P.kmf[0] & \
S390X_CAPBIT(S390X_AES_256))
static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *ivec, int enc)
{
S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
const unsigned char *iv = EVP_CIPHER_CTX_original_iv(ctx);
const int keylen = EVP_CIPHER_CTX_key_length(ctx);
const int ivlen = EVP_CIPHER_CTX_iv_length(ctx);
cctx->fc = S390X_AES_FC(keylen);
cctx->fc |= 1 << 24; /* 1 byte cipher feedback */
if (!enc)
cctx->fc |= S390X_DECRYPT;
memcpy(cctx->kmf.param.cv, iv, ivlen);
memcpy(cctx->kmf.param.k, key, keylen);
return 1;
}
static int s390x_aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_CFB_CTX *cctx = EVP_C_DATA(S390X_AES_CFB_CTX, ctx);
s390x_kmf(in, len, out, cctx->fc, &cctx->kmf.param);
return 1;
}
# define S390X_aes_128_cfb1_CAPABLE 0
# define S390X_aes_192_cfb1_CAPABLE 0
# define S390X_aes_256_cfb1_CAPABLE 0
# define s390x_aes_cfb1_init_key aes_init_key
# define s390x_aes_cfb1_cipher aes_cfb1_cipher
static int s390x_aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define S390X_aes_128_ctr_CAPABLE 1 /* checked by callee */
# define S390X_aes_192_ctr_CAPABLE 1
# define S390X_aes_256_ctr_CAPABLE 1
# define S390X_AES_CTR_CTX EVP_AES_KEY
# define s390x_aes_ctr_init_key aes_init_key
# define s390x_aes_ctr_cipher aes_ctr_cipher
static int s390x_aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define S390X_aes_128_gcm_CAPABLE (S390X_aes_128_CAPABLE && \
(OPENSSL_s390xcap_P.kma[0] & \
S390X_CAPBIT(S390X_AES_128)))
# define S390X_aes_192_gcm_CAPABLE (S390X_aes_192_CAPABLE && \
(OPENSSL_s390xcap_P.kma[0] & \
S390X_CAPBIT(S390X_AES_192)))
# define S390X_aes_256_gcm_CAPABLE (S390X_aes_256_CAPABLE && \
(OPENSSL_s390xcap_P.kma[0] & \
S390X_CAPBIT(S390X_AES_256)))
/* iv + padding length for iv lenghts != 12 */
# define S390X_gcm_ivpadlen(i) ((((i) + 15) >> 4 << 4) + 16)
/*-
* Process additional authenticated data. Returns 0 on success. Code is
* big-endian.
*/
static int s390x_aes_gcm_aad(S390X_AES_GCM_CTX *ctx, const unsigned char *aad,
size_t len)
{
unsigned long long alen;
int n, rem;
if (ctx->kma.param.tpcl)
return -2;
alen = ctx->kma.param.taadl + len;
if (alen > (U64(1) << 61) || (sizeof(len) == 8 && alen < len))
return -1;
ctx->kma.param.taadl = alen;
n = ctx->areslen;
if (n) {
while (n && len) {
ctx->ares[n] = *aad;
n = (n + 1) & 0xf;
++aad;
--len;
}
/* ctx->ares contains a complete block if offset has wrapped around */
if (!n) {
s390x_kma(ctx->ares, 16, NULL, 0, NULL, ctx->fc, &ctx->kma.param);
ctx->fc |= S390X_KMA_HS;
}
ctx->areslen = n;
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kma(aad, len, NULL, 0, NULL, ctx->fc, &ctx->kma.param);
aad += len;
ctx->fc |= S390X_KMA_HS;
}
if (rem) {
ctx->areslen = rem;
do {
--rem;
ctx->ares[rem] = aad[rem];
} while (rem);
}
return 0;
}
/*-
* En/de-crypt plain/cipher-text and authenticate ciphertext. Returns 0 for
* success. Code is big-endian.
*/
static int s390x_aes_gcm(S390X_AES_GCM_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len)
{
const unsigned char *inptr;
unsigned long long mlen;
union {
unsigned int w[4];
unsigned char b[16];
} buf;
size_t inlen;
int n, rem, i;
mlen = ctx->kma.param.tpcl + len;
if (mlen > ((U64(1) << 36) - 32) || (sizeof(len) == 8 && mlen < len))
return -1;
ctx->kma.param.tpcl = mlen;
n = ctx->mreslen;
if (n) {
inptr = in;
inlen = len;
while (n && inlen) {
ctx->mres[n] = *inptr;
n = (n + 1) & 0xf;
++inptr;
--inlen;
}
/* ctx->mres contains a complete block if offset has wrapped around */
if (!n) {
s390x_kma(ctx->ares, ctx->areslen, ctx->mres, 16, buf.b,
ctx->fc | S390X_KMA_LAAD, &ctx->kma.param);
ctx->fc |= S390X_KMA_HS;
ctx->areslen = 0;
/* previous call already encrypted/decrypted its remainder,
* see comment below */
n = ctx->mreslen;
while (n) {
*out = buf.b[n];
n = (n + 1) & 0xf;
++out;
++in;
--len;
}
ctx->mreslen = 0;
}
}
rem = len & 0xf;
len &= ~(size_t)0xf;
if (len) {
s390x_kma(ctx->ares, ctx->areslen, in, len, out,
ctx->fc | S390X_KMA_LAAD, &ctx->kma.param);
in += len;
out += len;
ctx->fc |= S390X_KMA_HS;
ctx->areslen = 0;
}
/*-
* If there is a remainder, it has to be saved such that it can be
* processed by kma later. However, we also have to do the for-now
* unauthenticated encryption/decryption part here and now...
*/
if (rem) {
if (!ctx->mreslen) {
buf.w[0] = ctx->kma.param.j0.w[0];
buf.w[1] = ctx->kma.param.j0.w[1];
buf.w[2] = ctx->kma.param.j0.w[2];
buf.w[3] = ctx->kma.param.cv.w + 1;
s390x_km(buf.b, 16, ctx->kres, ctx->fc & 0x1f, &ctx->kma.param.k);
}
n = ctx->mreslen;
for (i = 0; i < rem; i++) {
ctx->mres[n + i] = in[i];
out[i] = in[i] ^ ctx->kres[n + i];
}
ctx->mreslen += rem;
}
return 0;
}
/*-
* Initialize context structure. Code is big-endian.
*/
static void s390x_aes_gcm_setiv(S390X_AES_GCM_CTX *ctx,
const unsigned char *iv)
{
ctx->kma.param.t.g[0] = 0;
ctx->kma.param.t.g[1] = 0;
ctx->kma.param.tpcl = 0;
ctx->kma.param.taadl = 0;
ctx->mreslen = 0;
ctx->areslen = 0;
ctx->kreslen = 0;
if (ctx->ivlen == 12) {
memcpy(&ctx->kma.param.j0, iv, ctx->ivlen);
ctx->kma.param.j0.w[3] = 1;
ctx->kma.param.cv.w = 1;
} else {
/* ctx->iv has the right size and is already padded. */
memcpy(ctx->iv, iv, ctx->ivlen);
s390x_kma(ctx->iv, S390X_gcm_ivpadlen(ctx->ivlen), NULL, 0, NULL,
ctx->fc, &ctx->kma.param);
ctx->fc |= S390X_KMA_HS;
ctx->kma.param.j0.g[0] = ctx->kma.param.t.g[0];
ctx->kma.param.j0.g[1] = ctx->kma.param.t.g[1];
ctx->kma.param.cv.w = ctx->kma.param.j0.w[3];
ctx->kma.param.t.g[0] = 0;
ctx->kma.param.t.g[1] = 0;
}
}
/*-
* Performs various operations on the context structure depending on control
* type. Returns 1 for success, 0 for failure and -1 for unknown control type.
* Code is big-endian.
*/
static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c);
S390X_AES_GCM_CTX *gctx_out;
EVP_CIPHER_CTX *out;
unsigned char *buf, *iv;
int ivlen, enc, len;
switch (type) {
case EVP_CTRL_INIT:
ivlen = EVP_CIPHER_CTX_iv_length(c);
iv = EVP_CIPHER_CTX_iv_noconst(c);
gctx->key_set = 0;
gctx->iv_set = 0;
gctx->ivlen = ivlen;
gctx->iv = iv;
gctx->taglen = -1;
gctx->iv_gen = 0;
gctx->tls_aad_len = -1;
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
if (arg <= 0)
return 0;
if (arg != 12) {
iv = EVP_CIPHER_CTX_iv_noconst(c);
len = S390X_gcm_ivpadlen(arg);
/* Allocate memory for iv if needed. */
if (gctx->ivlen == 12 || len > S390X_gcm_ivpadlen(gctx->ivlen)) {
if (gctx->iv != iv)
OPENSSL_free(gctx->iv);
if ((gctx->iv = OPENSSL_malloc(len)) == NULL) {
EVPerr(EVP_F_S390X_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
/* Add padding. */
memset(gctx->iv + arg, 0, len - arg - 8);
*((unsigned long long *)(gctx->iv + len - 8)) = arg << 3;
}
gctx->ivlen = arg;
return 1;
case EVP_CTRL_AEAD_SET_TAG:
buf = EVP_CIPHER_CTX_buf_noconst(c);
enc = EVP_CIPHER_CTX_encrypting(c);
if (arg <= 0 || arg > 16 || enc)
return 0;
memcpy(buf, ptr, arg);
gctx->taglen = arg;
return 1;
case EVP_CTRL_AEAD_GET_TAG:
enc = EVP_CIPHER_CTX_encrypting(c);
if (arg <= 0 || arg > 16 || !enc || gctx->taglen < 0)
return 0;
memcpy(ptr, gctx->kma.param.t.b, arg);
return 1;
case EVP_CTRL_GCM_SET_IV_FIXED:
/* Special case: -1 length restores whole iv */
if (arg == -1) {
memcpy(gctx->iv, ptr, gctx->ivlen);
gctx->iv_gen = 1;
return 1;
}
/*
* Fixed field must be at least 4 bytes and invocation field at least
* 8.
*/
if ((arg < 4) || (gctx->ivlen - arg) < 8)
return 0;
if (arg)
memcpy(gctx->iv, ptr, arg);
enc = EVP_CIPHER_CTX_encrypting(c);
if (enc && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
return 0;
gctx->iv_gen = 1;
return 1;
case EVP_CTRL_GCM_IV_GEN:
if (gctx->iv_gen == 0 || gctx->key_set == 0)
return 0;
s390x_aes_gcm_setiv(gctx, gctx->iv);
if (arg <= 0 || arg > gctx->ivlen)
arg = gctx->ivlen;
memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
/*
* Invocation field will be at least 8 bytes in size and so no need
* to check wrap around or increment more than last 8 bytes.
*/
ctr64_inc(gctx->iv + gctx->ivlen - 8);
gctx->iv_set = 1;
return 1;
case EVP_CTRL_GCM_SET_IV_INV:
enc = EVP_CIPHER_CTX_encrypting(c);
if (gctx->iv_gen == 0 || gctx->key_set == 0 || enc)
return 0;
memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
s390x_aes_gcm_setiv(gctx, gctx->iv);
gctx->iv_set = 1;
return 1;
case EVP_CTRL_AEAD_TLS1_AAD:
/* Save the aad for later use. */
if (arg != EVP_AEAD_TLS1_AAD_LEN)
return 0;
buf = EVP_CIPHER_CTX_buf_noconst(c);
memcpy(buf, ptr, arg);
gctx->tls_aad_len = arg;
len = buf[arg - 2] << 8 | buf[arg - 1];
/* Correct length for explicit iv. */
if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
return 0;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too. */
enc = EVP_CIPHER_CTX_encrypting(c);
if (!enc) {
if (len < EVP_GCM_TLS_TAG_LEN)
return 0;
len -= EVP_GCM_TLS_TAG_LEN;
}
buf[arg - 2] = len >> 8;
buf[arg - 1] = len & 0xff;
/* Extra padding: tag appended to record. */
return EVP_GCM_TLS_TAG_LEN;
case EVP_CTRL_COPY:
out = ptr;
gctx_out = EVP_C_DATA(S390X_AES_GCM_CTX, out);
iv = EVP_CIPHER_CTX_iv_noconst(c);
if (gctx->iv == iv) {
gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out);
} else {
len = S390X_gcm_ivpadlen(gctx->ivlen);
if ((gctx_out->iv = OPENSSL_malloc(len)) == NULL) {
EVPerr(EVP_F_S390X_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(gctx_out->iv, gctx->iv, len);
}
return 1;
default:
return -1;
}
}
/*-
* Set key and/or iv. Returns 1 on success. Otherwise 0 is returned.
*/
static int s390x_aes_gcm_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv, int enc)
{
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
int keylen;
if (iv == NULL && key == NULL)
return 1;
if (key != NULL) {
keylen = EVP_CIPHER_CTX_key_length(ctx);
memcpy(&gctx->kma.param.k, key, keylen);
gctx->fc = S390X_AES_FC(keylen);
if (!enc)
gctx->fc |= S390X_DECRYPT;
if (iv == NULL && gctx->iv_set)
iv = gctx->iv;
if (iv != NULL) {
s390x_aes_gcm_setiv(gctx, iv);
gctx->iv_set = 1;
}
gctx->key_set = 1;
} else {
if (gctx->key_set)
s390x_aes_gcm_setiv(gctx, iv);
else
memcpy(gctx->iv, iv, gctx->ivlen);
gctx->iv_set = 1;
gctx->iv_gen = 0;
}
return 1;
}
/*-
* En/de-crypt and authenticate TLS packet. Returns the number of bytes written
* if successful. Otherwise -1 is returned. Code is big-endian.
*/
static int s390x_aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
const unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
const int enc = EVP_CIPHER_CTX_encrypting(ctx);
int rv = -1;
if (out != in || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
return -1;
if (EVP_CIPHER_CTX_ctrl(ctx, enc ? EVP_CTRL_GCM_IV_GEN
: EVP_CTRL_GCM_SET_IV_INV,
EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
goto err;
in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
gctx->kma.param.taadl = gctx->tls_aad_len << 3;
gctx->kma.param.tpcl = len << 3;
s390x_kma(buf, gctx->tls_aad_len, in, len, out,
gctx->fc | S390X_KMA_LAAD | S390X_KMA_LPC, &gctx->kma.param);
if (enc) {
memcpy(out + len, gctx->kma.param.t.b, EVP_GCM_TLS_TAG_LEN);
rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
} else {
if (CRYPTO_memcmp(gctx->kma.param.t.b, in + len,
EVP_GCM_TLS_TAG_LEN)) {
OPENSSL_cleanse(out, len);
goto err;
}
rv = len;
}
err:
gctx->iv_set = 0;
gctx->tls_aad_len = -1;
return rv;
}
/*-
* Called from EVP layer to initialize context, process additional
* authenticated data, en/de-crypt plain/cipher-text and authenticate
* ciphertext or process a TLS packet, depending on context. Returns bytes
* written on success. Otherwise -1 is returned. Code is big-endian.
*/
static int s390x_aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, ctx);
unsigned char *buf, tmp[16];
int enc;
if (!gctx->key_set)
return -1;
if (gctx->tls_aad_len >= 0)
return s390x_aes_gcm_tls_cipher(ctx, out, in, len);
if (!gctx->iv_set)
return -1;
if (in != NULL) {
if (out == NULL) {
if (s390x_aes_gcm_aad(gctx, in, len))
return -1;
} else {
if (s390x_aes_gcm(gctx, in, out, len))
return -1;
}
return len;
} else {
gctx->kma.param.taadl <<= 3;
gctx->kma.param.tpcl <<= 3;
s390x_kma(gctx->ares, gctx->areslen, gctx->mres, gctx->mreslen, tmp,
gctx->fc | S390X_KMA_LAAD | S390X_KMA_LPC, &gctx->kma.param);
/* recall that we already did en-/decrypt gctx->mres
* and returned it to caller... */
OPENSSL_cleanse(tmp, gctx->mreslen);
gctx->iv_set = 0;
enc = EVP_CIPHER_CTX_encrypting(ctx);
if (enc) {
gctx->taglen = 16;
} else {
if (gctx->taglen < 0)
return -1;
buf = EVP_CIPHER_CTX_buf_noconst(ctx);
if (CRYPTO_memcmp(buf, gctx->kma.param.t.b, gctx->taglen))
return -1;
}
return 0;
}
}
static int s390x_aes_gcm_cleanup(EVP_CIPHER_CTX *c)
{
S390X_AES_GCM_CTX *gctx = EVP_C_DATA(S390X_AES_GCM_CTX, c);
const unsigned char *iv;
if (gctx == NULL)
return 0;
iv = EVP_CIPHER_CTX_iv(c);
if (iv != gctx->iv)
OPENSSL_free(gctx->iv);
OPENSSL_cleanse(gctx, sizeof(*gctx));
return 1;
}
# define S390X_AES_XTS_CTX EVP_AES_XTS_CTX
# define S390X_aes_128_xts_CAPABLE 1 /* checked by callee */
# define S390X_aes_256_xts_CAPABLE 1
# define s390x_aes_xts_init_key aes_xts_init_key
static int s390x_aes_xts_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv, int enc);
# define s390x_aes_xts_cipher aes_xts_cipher
static int s390x_aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define s390x_aes_xts_ctrl aes_xts_ctrl
static int s390x_aes_xts_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
# define s390x_aes_xts_cleanup aes_xts_cleanup
# define S390X_aes_128_ccm_CAPABLE (S390X_aes_128_CAPABLE && \
(OPENSSL_s390xcap_P.kmac[0] & \
S390X_CAPBIT(S390X_AES_128)))
# define S390X_aes_192_ccm_CAPABLE (S390X_aes_192_CAPABLE && \
(OPENSSL_s390xcap_P.kmac[0] & \
S390X_CAPBIT(S390X_AES_192)))
# define S390X_aes_256_ccm_CAPABLE (S390X_aes_256_CAPABLE && \
(OPENSSL_s390xcap_P.kmac[0] & \
S390X_CAPBIT(S390X_AES_256)))
# define S390X_CCM_AAD_FLAG 0x40
/*-
* Set nonce and length fields. Code is big-endian.
*/
static inline void s390x_aes_ccm_setiv(S390X_AES_CCM_CTX *ctx,
const unsigned char *nonce,
size_t mlen)
{
ctx->aes.ccm.nonce.b[0] &= ~S390X_CCM_AAD_FLAG;
ctx->aes.ccm.nonce.g[1] = mlen;
memcpy(ctx->aes.ccm.nonce.b + 1, nonce, 15 - ctx->aes.ccm.l);
}
/*-
* Process additional authenticated data. Code is big-endian.
*/
static void s390x_aes_ccm_aad(S390X_AES_CCM_CTX *ctx, const unsigned char *aad,
size_t alen)
{
unsigned char *ptr;
int i, rem;
if (!alen)
return;
ctx->aes.ccm.nonce.b[0] |= S390X_CCM_AAD_FLAG;
/* Suppress 'type-punned pointer dereference' warning. */
ptr = ctx->aes.ccm.buf.b;
if (alen < ((1 << 16) - (1 << 8))) {
*(uint16_t *)ptr = alen;
i = 2;
} else if (sizeof(alen) == 8
&& alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
*(uint16_t *)ptr = 0xffff;
*(uint64_t *)(ptr + 2) = alen;
i = 10;
} else {
*(uint16_t *)ptr = 0xfffe;
*(uint32_t *)(ptr + 2) = alen;
i = 6;
}
while (i < 16 && alen) {
ctx->aes.ccm.buf.b[i] = *aad;
++aad;
--alen;
++i;
}
while (i < 16) {
ctx->aes.ccm.buf.b[i] = 0;
++i;
}
ctx->aes.ccm.kmac_param.icv.g[0] = 0;
ctx->aes.ccm.kmac_param.icv.g[1] = 0;
s390x_kmac(ctx->aes.ccm.nonce.b, 32, ctx->aes.ccm.fc,
&ctx->aes.ccm.kmac_param);
ctx->aes.ccm.blocks += 2;
rem = alen & 0xf;
alen &= ~(size_t)0xf;
if (alen) {
s390x_kmac(aad, alen, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
ctx->aes.ccm.blocks += alen >> 4;
aad += alen;
}
if (rem) {
for (i = 0; i < rem; i++)
ctx->aes.ccm.kmac_param.icv.b[i] ^= aad[i];
s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
ctx->aes.ccm.kmac_param.k);
ctx->aes.ccm.blocks++;
}
}
/*-
* En/de-crypt plain/cipher-text. Compute tag from plaintext. Returns 0 for
* success.
*/
static int s390x_aes_ccm(S390X_AES_CCM_CTX *ctx, const unsigned char *in,
unsigned char *out, size_t len, int enc)
{
size_t n, rem;
unsigned int i, l, num;
unsigned char flags;
flags = ctx->aes.ccm.nonce.b[0];
if (!(flags & S390X_CCM_AAD_FLAG)) {
s390x_km(ctx->aes.ccm.nonce.b, 16, ctx->aes.ccm.kmac_param.icv.b,
ctx->aes.ccm.fc, ctx->aes.ccm.kmac_param.k);
ctx->aes.ccm.blocks++;
}
l = flags & 0x7;
ctx->aes.ccm.nonce.b[0] = l;
/*-
* Reconstruct length from encoded length field
* and initialize it with counter value.
*/
n = 0;
for (i = 15 - l; i < 15; i++) {
n |= ctx->aes.ccm.nonce.b[i];
ctx->aes.ccm.nonce.b[i] = 0;
n <<= 8;
}
n |= ctx->aes.ccm.nonce.b[15];
ctx->aes.ccm.nonce.b[15] = 1;
if (n != len)
return -1; /* length mismatch */
if (enc) {
/* Two operations per block plus one for tag encryption */
ctx->aes.ccm.blocks += (((len + 15) >> 4) << 1) + 1;
if (ctx->aes.ccm.blocks > (1ULL << 61))
return -2; /* too much data */
}
num = 0;
rem = len & 0xf;
len &= ~(size_t)0xf;
if (enc) {
/* mac-then-encrypt */
if (len)
s390x_kmac(in, len, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
if (rem) {
for (i = 0; i < rem; i++)
ctx->aes.ccm.kmac_param.icv.b[i] ^= in[len + i];
s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
ctx->aes.ccm.kmac_param.k);
}
CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &ctx->aes.key.k,
ctx->aes.ccm.nonce.b, ctx->aes.ccm.buf.b,
&num, (ctr128_f)AES_ctr32_encrypt);
} else {
/* decrypt-then-mac */
CRYPTO_ctr128_encrypt_ctr32(in, out, len + rem, &ctx->aes.key.k,
ctx->aes.ccm.nonce.b, ctx->aes.ccm.buf.b,
&num, (ctr128_f)AES_ctr32_encrypt);
if (len)
s390x_kmac(out, len, ctx->aes.ccm.fc, &ctx->aes.ccm.kmac_param);
if (rem) {
for (i = 0; i < rem; i++)
ctx->aes.ccm.kmac_param.icv.b[i] ^= out[len + i];
s390x_km(ctx->aes.ccm.kmac_param.icv.b, 16,
ctx->aes.ccm.kmac_param.icv.b, ctx->aes.ccm.fc,
ctx->aes.ccm.kmac_param.k);
}
}
/* encrypt tag */
for (i = 15 - l; i < 16; i++)
ctx->aes.ccm.nonce.b[i] = 0;
s390x_km(ctx->aes.ccm.nonce.b, 16, ctx->aes.ccm.buf.b, ctx->aes.ccm.fc,
ctx->aes.ccm.kmac_param.k);
ctx->aes.ccm.kmac_param.icv.g[0] ^= ctx->aes.ccm.buf.g[0];
ctx->aes.ccm.kmac_param.icv.g[1] ^= ctx->aes.ccm.buf.g[1];
ctx->aes.ccm.nonce.b[0] = flags; /* restore flags field */
return 0;
}
/*-
* En/de-crypt and authenticate TLS packet. Returns the number of bytes written
* if successful. Otherwise -1 is returned.
*/
static int s390x_aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
unsigned char *ivec = EVP_CIPHER_CTX_iv_noconst(ctx);
unsigned char *buf = EVP_CIPHER_CTX_buf_noconst(ctx);
const int enc = EVP_CIPHER_CTX_encrypting(ctx);
if (out != in
|| len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->aes.ccm.m))
return -1;
if (enc) {
/* Set explicit iv (sequence number). */
memcpy(out, buf, EVP_CCM_TLS_EXPLICIT_IV_LEN);
}
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->aes.ccm.m;
/*-
* Get explicit iv (sequence number). We already have fixed iv
* (server/client_write_iv) here.
*/
memcpy(ivec + EVP_CCM_TLS_FIXED_IV_LEN, in, EVP_CCM_TLS_EXPLICIT_IV_LEN);
s390x_aes_ccm_setiv(cctx, ivec, len);
/* Process aad (sequence number|type|version|length) */
s390x_aes_ccm_aad(cctx, buf, cctx->aes.ccm.tls_aad_len);
in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
if (enc) {
if (s390x_aes_ccm(cctx, in, out, len, enc))
return -1;
memcpy(out + len, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m);
return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->aes.ccm.m;
} else {
if (!s390x_aes_ccm(cctx, in, out, len, enc)) {
if (!CRYPTO_memcmp(cctx->aes.ccm.kmac_param.icv.b, in + len,
cctx->aes.ccm.m))
return len;
}
OPENSSL_cleanse(out, len);
return -1;
}
}
/*-
* Set key and flag field and/or iv. Returns 1 if successful. Otherwise 0 is
* returned.
*/
static int s390x_aes_ccm_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv, int enc)
{
S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
unsigned char *ivec;
int keylen;
if (iv == NULL && key == NULL)
return 1;
if (key != NULL) {
keylen = EVP_CIPHER_CTX_key_length(ctx);
cctx->aes.ccm.fc = S390X_AES_FC(keylen);
memcpy(cctx->aes.ccm.kmac_param.k, key, keylen);
/* Store encoded m and l. */
cctx->aes.ccm.nonce.b[0] = ((cctx->aes.ccm.l - 1) & 0x7)
| (((cctx->aes.ccm.m - 2) >> 1) & 0x7) << 3;
memset(cctx->aes.ccm.nonce.b + 1, 0,
sizeof(cctx->aes.ccm.nonce.b));
cctx->aes.ccm.blocks = 0;
cctx->aes.ccm.key_set = 1;
}
if (iv != NULL) {
ivec = EVP_CIPHER_CTX_iv_noconst(ctx);
memcpy(ivec, iv, 15 - cctx->aes.ccm.l);
cctx->aes.ccm.iv_set = 1;
}
return 1;
}
/*-
* Called from EVP layer to initialize context, process additional
* authenticated data, en/de-crypt plain/cipher-text and authenticate
* plaintext or process a TLS packet, depending on context. Returns bytes
* written on success. Otherwise -1 is returned.
*/
static int s390x_aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, ctx);
const int enc = EVP_CIPHER_CTX_encrypting(ctx);
int rv;
unsigned char *buf, *ivec;
if (!cctx->aes.ccm.key_set)
return -1;
if (cctx->aes.ccm.tls_aad_len >= 0)
return s390x_aes_ccm_tls_cipher(ctx, out, in, len);
/*-
* Final(): Does not return any data. Recall that ccm is mac-then-encrypt
* so integrity must be checked already at Update() i.e., before
* potentially corrupted data is output.
*/
if (in == NULL && out != NULL)
return 0;
if (!cctx->aes.ccm.iv_set)
return -1;
- if (!enc && !cctx->aes.ccm.tag_set)
- return -1;
-
if (out == NULL) {
/* Update(): Pass message length. */
if (in == NULL) {
ivec = EVP_CIPHER_CTX_iv_noconst(ctx);
s390x_aes_ccm_setiv(cctx, ivec, len);
cctx->aes.ccm.len_set = 1;
return len;
}
/* Update(): Process aad. */
if (!cctx->aes.ccm.len_set && len)
return -1;
s390x_aes_ccm_aad(cctx, in, len);
return len;
}
+ /* The tag must be set before actually decrypting data */
+ if (!enc && !cctx->aes.ccm.tag_set)
+ return -1;
+
/* Update(): Process message. */
if (!cctx->aes.ccm.len_set) {
/*-
* In case message length was not previously set explicitly via
* Update(), set it now.
*/
ivec = EVP_CIPHER_CTX_iv_noconst(ctx);
s390x_aes_ccm_setiv(cctx, ivec, len);
cctx->aes.ccm.len_set = 1;
}
if (enc) {
if (s390x_aes_ccm(cctx, in, out, len, enc))
return -1;
cctx->aes.ccm.tag_set = 1;
return len;
} else {
rv = -1;
if (!s390x_aes_ccm(cctx, in, out, len, enc)) {
buf = EVP_CIPHER_CTX_buf_noconst(ctx);
if (!CRYPTO_memcmp(cctx->aes.ccm.kmac_param.icv.b, buf,
cctx->aes.ccm.m))
rv = len;
}
if (rv == -1)
OPENSSL_cleanse(out, len);
cctx->aes.ccm.iv_set = 0;
cctx->aes.ccm.tag_set = 0;
cctx->aes.ccm.len_set = 0;
return rv;
}
}
/*-
* Performs various operations on the context structure depending on control
* type. Returns 1 for success, 0 for failure and -1 for unknown control type.
* Code is big-endian.
*/
static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
S390X_AES_CCM_CTX *cctx = EVP_C_DATA(S390X_AES_CCM_CTX, c);
unsigned char *buf, *iv;
int enc, len;
switch (type) {
case EVP_CTRL_INIT:
cctx->aes.ccm.key_set = 0;
cctx->aes.ccm.iv_set = 0;
cctx->aes.ccm.l = 8;
cctx->aes.ccm.m = 12;
cctx->aes.ccm.tag_set = 0;
cctx->aes.ccm.len_set = 0;
cctx->aes.ccm.tls_aad_len = -1;
return 1;
case EVP_CTRL_AEAD_TLS1_AAD:
if (arg != EVP_AEAD_TLS1_AAD_LEN)
return 0;
/* Save the aad for later use. */
buf = EVP_CIPHER_CTX_buf_noconst(c);
memcpy(buf, ptr, arg);
cctx->aes.ccm.tls_aad_len = arg;
len = buf[arg - 2] << 8 | buf[arg - 1];
if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
return 0;
/* Correct length for explicit iv. */
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
enc = EVP_CIPHER_CTX_encrypting(c);
if (!enc) {
if (len < cctx->aes.ccm.m)
return 0;
/* Correct length for tag. */
len -= cctx->aes.ccm.m;
}
buf[arg - 2] = len >> 8;
buf[arg - 1] = len & 0xff;
/* Extra padding: tag appended to record. */
return cctx->aes.ccm.m;
case EVP_CTRL_CCM_SET_IV_FIXED:
if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
return 0;
/* Copy to first part of the iv. */
iv = EVP_CIPHER_CTX_iv_noconst(c);
memcpy(iv, ptr, arg);
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
arg = 15 - arg;
/* fall-through */
case EVP_CTRL_CCM_SET_L:
if (arg < 2 || arg > 8)
return 0;
cctx->aes.ccm.l = arg;
return 1;
case EVP_CTRL_AEAD_SET_TAG:
if ((arg & 1) || arg < 4 || arg > 16)
return 0;
enc = EVP_CIPHER_CTX_encrypting(c);
if (enc && ptr)
return 0;
if (ptr) {
cctx->aes.ccm.tag_set = 1;
buf = EVP_CIPHER_CTX_buf_noconst(c);
memcpy(buf, ptr, arg);
}
cctx->aes.ccm.m = arg;
return 1;
case EVP_CTRL_AEAD_GET_TAG:
enc = EVP_CIPHER_CTX_encrypting(c);
if (!enc || !cctx->aes.ccm.tag_set)
return 0;
if(arg < cctx->aes.ccm.m)
return 0;
memcpy(ptr, cctx->aes.ccm.kmac_param.icv.b, cctx->aes.ccm.m);
cctx->aes.ccm.tag_set = 0;
cctx->aes.ccm.iv_set = 0;
cctx->aes.ccm.len_set = 0;
return 1;
case EVP_CTRL_COPY:
return 1;
default:
return -1;
}
}
# define s390x_aes_ccm_cleanup aes_ccm_cleanup
# ifndef OPENSSL_NO_OCB
# define S390X_AES_OCB_CTX EVP_AES_OCB_CTX
# define S390X_aes_128_ocb_CAPABLE 0
# define S390X_aes_192_ocb_CAPABLE 0
# define S390X_aes_256_ocb_CAPABLE 0
# define s390x_aes_ocb_init_key aes_ocb_init_key
static int s390x_aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
# define s390x_aes_ocb_cipher aes_ocb_cipher
static int s390x_aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len);
# define s390x_aes_ocb_cleanup aes_ocb_cleanup
static int s390x_aes_ocb_cleanup(EVP_CIPHER_CTX *);
# define s390x_aes_ocb_ctrl aes_ocb_ctrl
static int s390x_aes_ocb_ctrl(EVP_CIPHER_CTX *, int type, int arg, void *ptr);
# endif
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode, \
MODE,flags) \
static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize, \
keylen / 8, \
ivlen, \
flags | EVP_CIPH_##MODE##_MODE, \
s390x_aes_##mode##_init_key, \
s390x_aes_##mode##_cipher, \
NULL, \
sizeof(S390X_AES_##MODE##_CTX), \
NULL, \
NULL, \
NULL, \
NULL \
}; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode, \
blocksize, \
keylen / 8, \
ivlen, \
flags | EVP_CIPH_##MODE##_MODE, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL, \
NULL, \
NULL, \
NULL \
}; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ \
return S390X_aes_##keylen##_##mode##_CAPABLE ? \
&s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode; \
}
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags)\
static const EVP_CIPHER s390x_aes_##keylen##_##mode = { \
nid##_##keylen##_##mode, \
blocksize, \
(EVP_CIPH_##MODE##_MODE == EVP_CIPH_XTS_MODE ? 2 : 1) * keylen / 8, \
ivlen, \
flags | EVP_CIPH_##MODE##_MODE, \
s390x_aes_##mode##_init_key, \
s390x_aes_##mode##_cipher, \
s390x_aes_##mode##_cleanup, \
sizeof(S390X_AES_##MODE##_CTX), \
NULL, \
NULL, \
s390x_aes_##mode##_ctrl, \
NULL \
}; \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE == EVP_CIPH_XTS_MODE ? 2 : 1) * keylen / 8, \
ivlen, \
flags | EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL, \
NULL, \
aes_##mode##_ctrl, \
NULL \
}; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ \
return S390X_aes_##keylen##_##mode##_CAPABLE ? \
&s390x_aes_##keylen##_##mode : &aes_##keylen##_##mode; \
}
#else
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_init_key, \
aes_##mode##_cipher, \
NULL, \
sizeof(EVP_AES_KEY), \
NULL,NULL,NULL,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return &aes_##keylen##_##mode; }
# define BLOCK_CIPHER_custom(nid,keylen,blocksize,ivlen,mode,MODE,flags) \
static const EVP_CIPHER aes_##keylen##_##mode = { \
nid##_##keylen##_##mode,blocksize, \
(EVP_CIPH_##MODE##_MODE==EVP_CIPH_XTS_MODE?2:1)*keylen/8, ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aes_##mode##_init_key, \
aes_##mode##_cipher, \
aes_##mode##_cleanup, \
sizeof(EVP_AES_##MODE##_CTX), \
NULL,NULL,aes_##mode##_ctrl,NULL }; \
const EVP_CIPHER *EVP_aes_##keylen##_##mode(void) \
{ return &aes_##keylen##_##mode; }
#endif
#if defined(OPENSSL_CPUID_OBJ) && (defined(__arm__) || defined(__arm) || defined(__aarch64__))
# include "arm_arch.h"
# if __ARM_MAX_ARCH__>=7
# if defined(BSAES_ASM)
# define BSAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
# endif
# if defined(VPAES_ASM)
# define VPAES_CAPABLE (OPENSSL_armcap_P & ARMV7_NEON)
# endif
# define HWAES_CAPABLE (OPENSSL_armcap_P & ARMV8_AES)
# define HWAES_set_encrypt_key aes_v8_set_encrypt_key
# define HWAES_set_decrypt_key aes_v8_set_decrypt_key
# define HWAES_encrypt aes_v8_encrypt
# define HWAES_decrypt aes_v8_decrypt
# define HWAES_cbc_encrypt aes_v8_cbc_encrypt
# define HWAES_ctr32_encrypt_blocks aes_v8_ctr32_encrypt_blocks
# endif
#endif
#if defined(HWAES_CAPABLE)
int HWAES_set_encrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
int HWAES_set_decrypt_key(const unsigned char *userKey, const int bits,
AES_KEY *key);
void HWAES_encrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void HWAES_decrypt(const unsigned char *in, unsigned char *out,
const AES_KEY *key);
void HWAES_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const AES_KEY *key,
unsigned char *ivec, const int enc);
void HWAES_ctr32_encrypt_blocks(const unsigned char *in, unsigned char *out,
size_t len, const AES_KEY *key,
const unsigned char ivec[16]);
void HWAES_xts_encrypt(const unsigned char *inp, unsigned char *out,
size_t len, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char iv[16]);
void HWAES_xts_decrypt(const unsigned char *inp, unsigned char *out,
size_t len, const AES_KEY *key1,
const AES_KEY *key2, const unsigned char iv[16]);
#endif
#define BLOCK_CIPHER_generic_pack(nid,keylen,flags) \
BLOCK_CIPHER_generic(nid,keylen,16,16,cbc,cbc,CBC,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,16,0,ecb,ecb,ECB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,1,16,ofb128,ofb,OFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,1,16,cfb128,cfb,CFB,flags|EVP_CIPH_FLAG_DEFAULT_ASN1) \
BLOCK_CIPHER_generic(nid,keylen,1,16,cfb1,cfb1,CFB,flags) \
BLOCK_CIPHER_generic(nid,keylen,1,16,cfb8,cfb8,CFB,flags) \
BLOCK_CIPHER_generic(nid,keylen,1,16,ctr,ctr,CTR,flags)
static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret, mode;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
mode = EVP_CIPHER_CTX_mode(ctx);
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc) {
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
ret = HWAES_set_decrypt_key(key,
EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) HWAES_decrypt;
dat->stream.cbc = NULL;
# ifdef HWAES_cbc_encrypt
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt;
# endif
} else
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) {
ret = AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_decrypt;
dat->stream.cbc = (cbc128_f) bsaes_cbc_encrypt;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
ret = vpaes_set_decrypt_key(key,
EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) vpaes_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) vpaes_cbc_encrypt : NULL;
} else
#endif
{
ret = AES_set_decrypt_key(key,
EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_decrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) AES_cbc_encrypt : NULL;
}
} else
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
ret = HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) HWAES_encrypt;
dat->stream.cbc = NULL;
# ifdef HWAES_cbc_encrypt
if (mode == EVP_CIPH_CBC_MODE)
dat->stream.cbc = (cbc128_f) HWAES_cbc_encrypt;
else
# endif
# ifdef HWAES_ctr32_encrypt_blocks
if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks;
else
# endif
(void)0; /* terminate potentially open 'else' */
} else
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) {
ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_encrypt;
dat->stream.ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
ret = vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) vpaes_encrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) vpaes_cbc_encrypt : NULL;
} else
#endif
{
ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&dat->ks.ks);
dat->block = (block128_f) AES_encrypt;
dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ?
(cbc128_f) AES_cbc_encrypt : NULL;
#ifdef AES_CTR_ASM
if (mode == EVP_CIPH_CTR_MODE)
dat->stream.ctr = (ctr128_f) AES_ctr32_encrypt;
#endif
}
if (ret < 0) {
EVPerr(EVP_F_AES_INIT_KEY, EVP_R_AES_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static int aes_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
if (dat->stream.cbc)
(*dat->stream.cbc) (in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_encrypting(ctx));
else if (EVP_CIPHER_CTX_encrypting(ctx))
CRYPTO_cbc128_encrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
else
CRYPTO_cbc128_decrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), dat->block);
return 1;
}
static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
size_t bl = EVP_CIPHER_CTX_block_size(ctx);
size_t i;
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
if (len < bl)
return 1;
for (i = 0, len -= bl; i <= len; i += bl)
(*dat->block) (in + i, out + i, &dat->ks);
return 1;
}
static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
int num = EVP_CIPHER_CTX_num(ctx);
CRYPTO_ofb128_encrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), &num, dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
static int aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
int num = EVP_CIPHER_CTX_num(ctx);
CRYPTO_cfb128_encrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), &num,
EVP_CIPHER_CTX_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
static int aes_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
int num = EVP_CIPHER_CTX_num(ctx);
CRYPTO_cfb128_8_encrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), &num,
EVP_CIPHER_CTX_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
static int aes_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
if (EVP_CIPHER_CTX_test_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS)) {
int num = EVP_CIPHER_CTX_num(ctx);
CRYPTO_cfb128_1_encrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), &num,
EVP_CIPHER_CTX_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
while (len >= MAXBITCHUNK) {
int num = EVP_CIPHER_CTX_num(ctx);
CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), &num,
EVP_CIPHER_CTX_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
len -= MAXBITCHUNK;
out += MAXBITCHUNK;
in += MAXBITCHUNK;
}
if (len) {
int num = EVP_CIPHER_CTX_num(ctx);
CRYPTO_cfb128_1_encrypt(in, out, len * 8, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx), &num,
EVP_CIPHER_CTX_encrypting(ctx), dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
}
return 1;
}
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
unsigned int num = EVP_CIPHER_CTX_num(ctx);
EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx);
if (dat->stream.ctr)
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_buf_noconst(ctx),
&num, dat->stream.ctr);
else
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
dat->block);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
BLOCK_CIPHER_generic_pack(NID_aes, 128, 0)
BLOCK_CIPHER_generic_pack(NID_aes, 192, 0)
BLOCK_CIPHER_generic_pack(NID_aes, 256, 0)
static int aes_gcm_cleanup(EVP_CIPHER_CTX *c)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c);
if (gctx == NULL)
return 0;
OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm));
if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c))
OPENSSL_free(gctx->iv);
return 1;
}
static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,c);
switch (type) {
case EVP_CTRL_INIT:
gctx->key_set = 0;
gctx->iv_set = 0;
gctx->ivlen = c->cipher->iv_len;
gctx->iv = c->iv;
gctx->taglen = -1;
gctx->iv_gen = 0;
gctx->tls_aad_len = -1;
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
if (arg <= 0)
return 0;
/* Allocate memory for IV if needed */
if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) {
if (gctx->iv != c->iv)
OPENSSL_free(gctx->iv);
if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) {
EVPerr(EVP_F_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
gctx->ivlen = arg;
return 1;
case EVP_CTRL_AEAD_SET_TAG:
if (arg <= 0 || arg > 16 || c->encrypt)
return 0;
memcpy(c->buf, ptr, arg);
gctx->taglen = arg;
return 1;
case EVP_CTRL_AEAD_GET_TAG:
if (arg <= 0 || arg > 16 || !c->encrypt
|| gctx->taglen < 0)
return 0;
memcpy(ptr, c->buf, arg);
return 1;
case EVP_CTRL_GCM_SET_IV_FIXED:
/* Special case: -1 length restores whole IV */
if (arg == -1) {
memcpy(gctx->iv, ptr, gctx->ivlen);
gctx->iv_gen = 1;
return 1;
}
/*
* Fixed field must be at least 4 bytes and invocation field at least
* 8.
*/
if ((arg < 4) || (gctx->ivlen - arg) < 8)
return 0;
if (arg)
memcpy(gctx->iv, ptr, arg);
if (c->encrypt && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
return 0;
gctx->iv_gen = 1;
return 1;
case EVP_CTRL_GCM_IV_GEN:
if (gctx->iv_gen == 0 || gctx->key_set == 0)
return 0;
CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
if (arg <= 0 || arg > gctx->ivlen)
arg = gctx->ivlen;
memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
/*
* Invocation field will be at least 8 bytes in size and so no need
* to check wrap around or increment more than last 8 bytes.
*/
ctr64_inc(gctx->iv + gctx->ivlen - 8);
gctx->iv_set = 1;
return 1;
case EVP_CTRL_GCM_SET_IV_INV:
if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt)
return 0;
memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
gctx->iv_set = 1;
return 1;
case EVP_CTRL_AEAD_TLS1_AAD:
/* Save the AAD for later use */
if (arg != EVP_AEAD_TLS1_AAD_LEN)
return 0;
memcpy(c->buf, ptr, arg);
gctx->tls_aad_len = arg;
{
unsigned int len = c->buf[arg - 2] << 8 | c->buf[arg - 1];
/* Correct length for explicit IV */
if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
return 0;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too */
if (!c->encrypt) {
if (len < EVP_GCM_TLS_TAG_LEN)
return 0;
len -= EVP_GCM_TLS_TAG_LEN;
}
c->buf[arg - 2] = len >> 8;
c->buf[arg - 1] = len & 0xff;
}
/* Extra padding: tag appended to record */
return EVP_GCM_TLS_TAG_LEN;
case EVP_CTRL_COPY:
{
EVP_CIPHER_CTX *out = ptr;
EVP_AES_GCM_CTX *gctx_out = EVP_C_DATA(EVP_AES_GCM_CTX,out);
if (gctx->gcm.key) {
if (gctx->gcm.key != &gctx->ks)
return 0;
gctx_out->gcm.key = &gctx_out->ks;
}
if (gctx->iv == c->iv)
gctx_out->iv = out->iv;
else {
if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) {
EVPerr(EVP_F_AES_GCM_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
}
return 1;
}
default:
return -1;
}
}
static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
do {
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
HWAES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) HWAES_encrypt);
# ifdef HWAES_ctr32_encrypt_blocks
gctx->ctr = (ctr128_f) HWAES_ctr32_encrypt_blocks;
# else
gctx->ctr = NULL;
# endif
break;
} else
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE) {
AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) AES_encrypt);
gctx->ctr = (ctr128_f) bsaes_ctr32_encrypt_blocks;
break;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) vpaes_encrypt);
gctx->ctr = NULL;
break;
} else
#endif
(void)0; /* terminate potentially open 'else' */
AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) AES_encrypt);
#ifdef AES_CTR_ASM
gctx->ctr = (ctr128_f) AES_ctr32_encrypt;
#else
gctx->ctr = NULL;
#endif
} while (0);
/*
* If we have an iv can set it directly, otherwise use saved IV.
*/
if (iv == NULL && gctx->iv_set)
iv = gctx->iv;
if (iv) {
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
gctx->iv_set = 1;
}
gctx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (gctx->key_set)
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
else
memcpy(gctx->iv, iv, gctx->ivlen);
gctx->iv_set = 1;
gctx->iv_gen = 0;
}
return 1;
}
/*
* Handle TLS GCM packet format. This consists of the last portion of the IV
* followed by the payload and finally the tag. On encrypt generate IV,
* encrypt payload and write the tag. On verify retrieve IV, decrypt payload
* and verify tag.
*/
static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
int rv = -1;
/* Encrypt/decrypt must be performed in place */
if (out != in
|| len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
return -1;
/*
* Set IV from start of buffer or generate IV and write to start of
* buffer.
*/
if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ? EVP_CTRL_GCM_IV_GEN
: EVP_CTRL_GCM_SET_IV_INV,
EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
goto err;
/* Use saved AAD */
if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
goto err;
/* Fix buffer and length to point to payload */
in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
if (ctx->encrypt) {
/* Encrypt payload */
if (gctx->ctr) {
size_t bulk = 0;
#if defined(AES_GCM_ASM)
if (len >= 32 && AES_GCM_ASM(gctx)) {
if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0))
return -1;
bulk = AES_gcm_encrypt(in, out, len,
gctx->gcm.key,
gctx->gcm.Yi.c, gctx->gcm.Xi.u);
gctx->gcm.len.u[1] += bulk;
}
#endif
if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
in + bulk,
out + bulk,
len - bulk, gctx->ctr))
goto err;
} else {
size_t bulk = 0;
#if defined(AES_GCM_ASM2)
if (len >= 32 && AES_GCM_ASM2(gctx)) {
if (CRYPTO_gcm128_encrypt(&gctx->gcm, NULL, NULL, 0))
return -1;
bulk = AES_gcm_encrypt(in, out, len,
gctx->gcm.key,
gctx->gcm.Yi.c, gctx->gcm.Xi.u);
gctx->gcm.len.u[1] += bulk;
}
#endif
if (CRYPTO_gcm128_encrypt(&gctx->gcm,
in + bulk, out + bulk, len - bulk))
goto err;
}
out += len;
/* Finally write tag */
CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
} else {
/* Decrypt */
if (gctx->ctr) {
size_t bulk = 0;
#if defined(AES_GCM_ASM)
if (len >= 16 && AES_GCM_ASM(gctx)) {
if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0))
return -1;
bulk = AES_gcm_decrypt(in, out, len,
gctx->gcm.key,
gctx->gcm.Yi.c, gctx->gcm.Xi.u);
gctx->gcm.len.u[1] += bulk;
}
#endif
if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
in + bulk,
out + bulk,
len - bulk, gctx->ctr))
goto err;
} else {
size_t bulk = 0;
#if defined(AES_GCM_ASM2)
if (len >= 16 && AES_GCM_ASM2(gctx)) {
if (CRYPTO_gcm128_decrypt(&gctx->gcm, NULL, NULL, 0))
return -1;
bulk = AES_gcm_decrypt(in, out, len,
gctx->gcm.key,
gctx->gcm.Yi.c, gctx->gcm.Xi.u);
gctx->gcm.len.u[1] += bulk;
}
#endif
if (CRYPTO_gcm128_decrypt(&gctx->gcm,
in + bulk, out + bulk, len - bulk))
goto err;
}
/* Retrieve tag */
CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, EVP_GCM_TLS_TAG_LEN);
/* If tag mismatch wipe buffer */
if (CRYPTO_memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN)) {
OPENSSL_cleanse(out, len);
goto err;
}
rv = len;
}
err:
gctx->iv_set = 0;
gctx->tls_aad_len = -1;
return rv;
}
static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx);
/* If not set up, return error */
if (!gctx->key_set)
return -1;
if (gctx->tls_aad_len >= 0)
return aes_gcm_tls_cipher(ctx, out, in, len);
if (!gctx->iv_set)
return -1;
if (in) {
if (out == NULL) {
if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
return -1;
} else if (ctx->encrypt) {
if (gctx->ctr) {
size_t bulk = 0;
#if defined(AES_GCM_ASM)
if (len >= 32 && AES_GCM_ASM(gctx)) {
size_t res = (16 - gctx->gcm.mres) % 16;
if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res))
return -1;
bulk = AES_gcm_encrypt(in + res,
out + res, len - res,
gctx->gcm.key, gctx->gcm.Yi.c,
gctx->gcm.Xi.u);
gctx->gcm.len.u[1] += bulk;
bulk += res;
}
#endif
if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm,
in + bulk,
out + bulk,
len - bulk, gctx->ctr))
return -1;
} else {
size_t bulk = 0;
#if defined(AES_GCM_ASM2)
if (len >= 32 && AES_GCM_ASM2(gctx)) {
size_t res = (16 - gctx->gcm.mres) % 16;
if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, res))
return -1;
bulk = AES_gcm_encrypt(in + res,
out + res, len - res,
gctx->gcm.key, gctx->gcm.Yi.c,
gctx->gcm.Xi.u);
gctx->gcm.len.u[1] += bulk;
bulk += res;
}
#endif
if (CRYPTO_gcm128_encrypt(&gctx->gcm,
in + bulk, out + bulk, len - bulk))
return -1;
}
} else {
if (gctx->ctr) {
size_t bulk = 0;
#if defined(AES_GCM_ASM)
if (len >= 16 && AES_GCM_ASM(gctx)) {
size_t res = (16 - gctx->gcm.mres) % 16;
if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res))
return -1;
bulk = AES_gcm_decrypt(in + res,
out + res, len - res,
gctx->gcm.key,
gctx->gcm.Yi.c, gctx->gcm.Xi.u);
gctx->gcm.len.u[1] += bulk;
bulk += res;
}
#endif
if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm,
in + bulk,
out + bulk,
len - bulk, gctx->ctr))
return -1;
} else {
size_t bulk = 0;
#if defined(AES_GCM_ASM2)
if (len >= 16 && AES_GCM_ASM2(gctx)) {
size_t res = (16 - gctx->gcm.mres) % 16;
if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, res))
return -1;
bulk = AES_gcm_decrypt(in + res,
out + res, len - res,
gctx->gcm.key,
gctx->gcm.Yi.c, gctx->gcm.Xi.u);
gctx->gcm.len.u[1] += bulk;
bulk += res;
}
#endif
if (CRYPTO_gcm128_decrypt(&gctx->gcm,
in + bulk, out + bulk, len - bulk))
return -1;
}
}
return len;
} else {
if (!ctx->encrypt) {
if (gctx->taglen < 0)
return -1;
if (CRYPTO_gcm128_finish(&gctx->gcm, ctx->buf, gctx->taglen) != 0)
return -1;
gctx->iv_set = 0;
return 0;
}
CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf, 16);
gctx->taglen = 16;
/* Don't reuse the IV */
gctx->iv_set = 0;
return 0;
}
}
#define CUSTOM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
| EVP_CIPH_CUSTOM_COPY)
BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, gcm, GCM,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, gcm, GCM,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, gcm, GCM,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,c);
if (type == EVP_CTRL_COPY) {
EVP_CIPHER_CTX *out = ptr;
EVP_AES_XTS_CTX *xctx_out = EVP_C_DATA(EVP_AES_XTS_CTX,out);
if (xctx->xts.key1) {
if (xctx->xts.key1 != &xctx->ks1)
return 0;
xctx_out->xts.key1 = &xctx_out->ks1;
}
if (xctx->xts.key2) {
if (xctx->xts.key2 != &xctx->ks2)
return 0;
xctx_out->xts.key2 = &xctx_out->ks2;
}
return 1;
} else if (type != EVP_CTRL_INIT)
return -1;
/* key1 and key2 are used as an indicator both key and IV are set */
xctx->xts.key1 = NULL;
xctx->xts.key2 = NULL;
return 1;
}
static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
if (!iv && !key)
return 1;
if (key)
do {
#ifdef AES_XTS_ASM
xctx->stream = enc ? AES_xts_encrypt : AES_xts_decrypt;
#else
xctx->stream = NULL;
#endif
/* key_len is two AES keys */
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
if (enc) {
HWAES_set_encrypt_key(key,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) HWAES_encrypt;
# ifdef HWAES_xts_encrypt
xctx->stream = HWAES_xts_encrypt;
# endif
} else {
HWAES_set_decrypt_key(key,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) HWAES_decrypt;
# ifdef HWAES_xts_decrypt
xctx->stream = HWAES_xts_decrypt;
#endif
}
HWAES_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks2.ks);
xctx->xts.block2 = (block128_f) HWAES_encrypt;
xctx->xts.key1 = &xctx->ks1;
break;
} else
#endif
#ifdef BSAES_CAPABLE
if (BSAES_CAPABLE)
xctx->stream = enc ? bsaes_xts_encrypt : bsaes_xts_decrypt;
else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
if (enc) {
vpaes_set_encrypt_key(key,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) vpaes_encrypt;
} else {
vpaes_set_decrypt_key(key,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) vpaes_decrypt;
}
vpaes_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks2.ks);
xctx->xts.block2 = (block128_f) vpaes_encrypt;
xctx->xts.key1 = &xctx->ks1;
break;
} else
#endif
(void)0; /* terminate potentially open 'else' */
if (enc) {
AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) AES_encrypt;
} else {
AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks1.ks);
xctx->xts.block1 = (block128_f) AES_decrypt;
}
AES_set_encrypt_key(key + EVP_CIPHER_CTX_key_length(ctx) / 2,
EVP_CIPHER_CTX_key_length(ctx) * 4,
&xctx->ks2.ks);
xctx->xts.block2 = (block128_f) AES_encrypt;
xctx->xts.key1 = &xctx->ks1;
} while (0);
if (iv) {
xctx->xts.key2 = &xctx->ks2;
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16);
}
return 1;
}
static int aes_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx);
if (!xctx->xts.key1 || !xctx->xts.key2)
return 0;
if (!out || !in || len < AES_BLOCK_SIZE)
return 0;
if (xctx->stream)
(*xctx->stream) (in, out, len,
xctx->xts.key1, xctx->xts.key2,
EVP_CIPHER_CTX_iv_noconst(ctx));
else if (CRYPTO_xts128_encrypt(&xctx->xts, EVP_CIPHER_CTX_iv_noconst(ctx),
in, out, len,
EVP_CIPHER_CTX_encrypting(ctx)))
return 0;
return 1;
}
#define aes_xts_cleanup NULL
#define XTS_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
| EVP_CIPH_CUSTOM_COPY)
BLOCK_CIPHER_custom(NID_aes, 128, 1, 16, xts, XTS, XTS_FLAGS)
BLOCK_CIPHER_custom(NID_aes, 256, 1, 16, xts, XTS, XTS_FLAGS)
static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,c);
switch (type) {
case EVP_CTRL_INIT:
cctx->key_set = 0;
cctx->iv_set = 0;
cctx->L = 8;
cctx->M = 12;
cctx->tag_set = 0;
cctx->len_set = 0;
cctx->tls_aad_len = -1;
return 1;
case EVP_CTRL_AEAD_TLS1_AAD:
/* Save the AAD for later use */
if (arg != EVP_AEAD_TLS1_AAD_LEN)
return 0;
memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
cctx->tls_aad_len = arg;
{
uint16_t len =
EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8
| EVP_CIPHER_CTX_buf_noconst(c)[arg - 1];
/* Correct length for explicit IV */
if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
return 0;
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too */
if (!EVP_CIPHER_CTX_encrypting(c)) {
if (len < cctx->M)
return 0;
len -= cctx->M;
}
EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8;
EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff;
}
/* Extra padding: tag appended to record */
return cctx->M;
case EVP_CTRL_CCM_SET_IV_FIXED:
/* Sanity check length */
if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
return 0;
/* Just copy to first part of IV */
memcpy(EVP_CIPHER_CTX_iv_noconst(c), ptr, arg);
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
arg = 15 - arg;
/* fall thru */
case EVP_CTRL_CCM_SET_L:
if (arg < 2 || arg > 8)
return 0;
cctx->L = arg;
return 1;
case EVP_CTRL_AEAD_SET_TAG:
if ((arg & 1) || arg < 4 || arg > 16)
return 0;
if (EVP_CIPHER_CTX_encrypting(c) && ptr)
return 0;
if (ptr) {
cctx->tag_set = 1;
memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
}
cctx->M = arg;
return 1;
case EVP_CTRL_AEAD_GET_TAG:
if (!EVP_CIPHER_CTX_encrypting(c) || !cctx->tag_set)
return 0;
if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg))
return 0;
cctx->tag_set = 0;
cctx->iv_set = 0;
cctx->len_set = 0;
return 1;
case EVP_CTRL_COPY:
{
EVP_CIPHER_CTX *out = ptr;
EVP_AES_CCM_CTX *cctx_out = EVP_C_DATA(EVP_AES_CCM_CTX,out);
if (cctx->ccm.key) {
if (cctx->ccm.key != &cctx->ks)
return 0;
cctx_out->ccm.key = &cctx_out->ks;
}
return 1;
}
default:
return -1;
}
}
static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key)
do {
#ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) HWAES_encrypt);
cctx->str = NULL;
cctx->key_set = 1;
break;
} else
#endif
#ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) vpaes_encrypt);
cctx->str = NULL;
cctx->key_set = 1;
break;
}
#endif
AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) AES_encrypt);
cctx->str = NULL;
cctx->key_set = 1;
} while (0);
if (iv) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
}
static int aes_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
CCM128_CONTEXT *ccm = &cctx->ccm;
/* Encrypt/decrypt must be performed in place */
if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M))
return -1;
/* If encrypting set explicit IV from sequence number (start of AAD) */
if (EVP_CIPHER_CTX_encrypting(ctx))
memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx),
EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Get rest of IV from explicit IV */
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx) + EVP_CCM_TLS_FIXED_IV_LEN, in,
EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Correct length value */
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), 15 - cctx->L,
len))
return -1;
/* Use saved AAD */
CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx), cctx->tls_aad_len);
/* Fix buffer to point to payload */
in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
if (EVP_CIPHER_CTX_encrypting(ctx)) {
if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
cctx->str) :
CRYPTO_ccm128_encrypt(ccm, in, out, len))
return -1;
if (!CRYPTO_ccm128_tag(ccm, out + len, cctx->M))
return -1;
return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
} else {
if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
cctx->str) :
!CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
unsigned char tag[16];
if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
if (!CRYPTO_memcmp(tag, in + len, cctx->M))
return len;
}
}
OPENSSL_cleanse(out, len);
return -1;
}
}
static int aes_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx);
CCM128_CONTEXT *ccm = &cctx->ccm;
/* If not set up, return error */
if (!cctx->key_set)
return -1;
if (cctx->tls_aad_len >= 0)
return aes_ccm_tls_cipher(ctx, out, in, len);
/* EVP_*Final() doesn't return any data */
if (in == NULL && out != NULL)
return 0;
if (!cctx->iv_set)
return -1;
- if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
- return -1;
if (!out) {
if (!in) {
if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
15 - cctx->L, len))
return -1;
cctx->len_set = 1;
return len;
}
/* If have AAD need message length */
if (!cctx->len_set && len)
return -1;
CRYPTO_ccm128_aad(ccm, in, len);
return len;
}
+
+ /* The tag must be set before actually decrypting data */
+ if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
+ return -1;
+
/* If not set length yet do it */
if (!cctx->len_set) {
if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
15 - cctx->L, len))
return -1;
cctx->len_set = 1;
}
if (EVP_CIPHER_CTX_encrypting(ctx)) {
if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len,
cctx->str) :
CRYPTO_ccm128_encrypt(ccm, in, out, len))
return -1;
cctx->tag_set = 1;
return len;
} else {
int rv = -1;
if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
cctx->str) :
!CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
unsigned char tag[16];
if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
if (!CRYPTO_memcmp(tag, EVP_CIPHER_CTX_buf_noconst(ctx),
cctx->M))
rv = len;
}
}
if (rv == -1)
OPENSSL_cleanse(out, len);
cctx->iv_set = 0;
cctx->tag_set = 0;
cctx->len_set = 0;
return rv;
}
}
#define aes_ccm_cleanup NULL
BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, ccm, CCM,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes, 192, 1, 12, ccm, CCM,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes, 256, 1, 12, ccm, CCM,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
typedef struct {
union {
double align;
AES_KEY ks;
} ks;
/* Indicates if IV has been set */
unsigned char *iv;
} EVP_AES_WRAP_CTX;
static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
if (EVP_CIPHER_CTX_encrypting(ctx))
AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&wctx->ks.ks);
else
AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&wctx->ks.ks);
if (!iv)
wctx->iv = NULL;
}
if (iv) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, EVP_CIPHER_CTX_iv_length(ctx));
wctx->iv = EVP_CIPHER_CTX_iv_noconst(ctx);
}
return 1;
}
static int aes_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t inlen)
{
EVP_AES_WRAP_CTX *wctx = EVP_C_DATA(EVP_AES_WRAP_CTX,ctx);
size_t rv;
/* AES wrap with padding has IV length of 4, without padding 8 */
int pad = EVP_CIPHER_CTX_iv_length(ctx) == 4;
/* No final operation so always return zero length */
if (!in)
return 0;
/* Input length must always be non-zero */
if (!inlen)
return -1;
/* If decrypting need at least 16 bytes and multiple of 8 */
if (!EVP_CIPHER_CTX_encrypting(ctx) && (inlen < 16 || inlen & 0x7))
return -1;
/* If not padding input must be multiple of 8 */
if (!pad && inlen & 0x7)
return -1;
if (is_partially_overlapping(out, in, inlen)) {
EVPerr(EVP_F_AES_WRAP_CIPHER, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
if (!out) {
if (EVP_CIPHER_CTX_encrypting(ctx)) {
/* If padding round up to multiple of 8 */
if (pad)
inlen = (inlen + 7) / 8 * 8;
/* 8 byte prefix */
return inlen + 8;
} else {
/*
* If not padding output will be exactly 8 bytes smaller than
* input. If padding it will be at least 8 bytes smaller but we
* don't know how much.
*/
return inlen - 8;
}
}
if (pad) {
if (EVP_CIPHER_CTX_encrypting(ctx))
rv = CRYPTO_128_wrap_pad(&wctx->ks.ks, wctx->iv,
out, in, inlen,
(block128_f) AES_encrypt);
else
rv = CRYPTO_128_unwrap_pad(&wctx->ks.ks, wctx->iv,
out, in, inlen,
(block128_f) AES_decrypt);
} else {
if (EVP_CIPHER_CTX_encrypting(ctx))
rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv,
out, in, inlen, (block128_f) AES_encrypt);
else
rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv,
out, in, inlen, (block128_f) AES_decrypt);
}
return rv ? (int)rv : -1;
}
#define WRAP_FLAGS (EVP_CIPH_WRAP_MODE \
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1)
static const EVP_CIPHER aes_128_wrap = {
NID_id_aes128_wrap,
8, 16, 8, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL, NULL, NULL, NULL
};
const EVP_CIPHER *EVP_aes_128_wrap(void)
{
return &aes_128_wrap;
}
static const EVP_CIPHER aes_192_wrap = {
NID_id_aes192_wrap,
8, 24, 8, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL, NULL, NULL, NULL
};
const EVP_CIPHER *EVP_aes_192_wrap(void)
{
return &aes_192_wrap;
}
static const EVP_CIPHER aes_256_wrap = {
NID_id_aes256_wrap,
8, 32, 8, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL, NULL, NULL, NULL
};
const EVP_CIPHER *EVP_aes_256_wrap(void)
{
return &aes_256_wrap;
}
static const EVP_CIPHER aes_128_wrap_pad = {
NID_id_aes128_wrap_pad,
8, 16, 4, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL, NULL, NULL, NULL
};
const EVP_CIPHER *EVP_aes_128_wrap_pad(void)
{
return &aes_128_wrap_pad;
}
static const EVP_CIPHER aes_192_wrap_pad = {
NID_id_aes192_wrap_pad,
8, 24, 4, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL, NULL, NULL, NULL
};
const EVP_CIPHER *EVP_aes_192_wrap_pad(void)
{
return &aes_192_wrap_pad;
}
static const EVP_CIPHER aes_256_wrap_pad = {
NID_id_aes256_wrap_pad,
8, 32, 4, WRAP_FLAGS,
aes_wrap_init_key, aes_wrap_cipher,
NULL,
sizeof(EVP_AES_WRAP_CTX),
NULL, NULL, NULL, NULL
};
const EVP_CIPHER *EVP_aes_256_wrap_pad(void)
{
return &aes_256_wrap_pad;
}
#ifndef OPENSSL_NO_OCB
static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c);
EVP_CIPHER_CTX *newc;
EVP_AES_OCB_CTX *new_octx;
switch (type) {
case EVP_CTRL_INIT:
octx->key_set = 0;
octx->iv_set = 0;
octx->ivlen = EVP_CIPHER_CTX_iv_length(c);
octx->iv = EVP_CIPHER_CTX_iv_noconst(c);
octx->taglen = 16;
octx->data_buf_len = 0;
octx->aad_buf_len = 0;
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
/* IV len must be 1 to 15 */
if (arg <= 0 || arg > 15)
return 0;
octx->ivlen = arg;
return 1;
case EVP_CTRL_AEAD_SET_TAG:
if (!ptr) {
/* Tag len must be 0 to 16 */
if (arg < 0 || arg > 16)
return 0;
octx->taglen = arg;
return 1;
}
if (arg != octx->taglen || EVP_CIPHER_CTX_encrypting(c))
return 0;
memcpy(octx->tag, ptr, arg);
return 1;
case EVP_CTRL_AEAD_GET_TAG:
if (arg != octx->taglen || !EVP_CIPHER_CTX_encrypting(c))
return 0;
memcpy(ptr, octx->tag, arg);
return 1;
case EVP_CTRL_COPY:
newc = (EVP_CIPHER_CTX *)ptr;
new_octx = EVP_C_DATA(EVP_AES_OCB_CTX,newc);
return CRYPTO_ocb128_copy_ctx(&new_octx->ocb, &octx->ocb,
&new_octx->ksenc.ks,
&new_octx->ksdec.ks);
default:
return -1;
}
}
# ifdef HWAES_CAPABLE
# ifdef HWAES_ocb_encrypt
void HWAES_ocb_encrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const void *key,
size_t start_block_num,
unsigned char offset_i[16],
const unsigned char L_[][16],
unsigned char checksum[16]);
# else
# define HWAES_ocb_encrypt ((ocb128_f)NULL)
# endif
# ifdef HWAES_ocb_decrypt
void HWAES_ocb_decrypt(const unsigned char *in, unsigned char *out,
size_t blocks, const void *key,
size_t start_block_num,
unsigned char offset_i[16],
const unsigned char L_[][16],
unsigned char checksum[16]);
# else
# define HWAES_ocb_decrypt ((ocb128_f)NULL)
# endif
# endif
static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
do {
/*
* We set both the encrypt and decrypt key here because decrypt
* needs both. We could possibly optimise to remove setting the
* decrypt for an encryption operation.
*/
# ifdef HWAES_CAPABLE
if (HWAES_CAPABLE) {
HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksenc.ks);
HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
(block128_f) HWAES_encrypt,
(block128_f) HWAES_decrypt,
enc ? HWAES_ocb_encrypt
: HWAES_ocb_decrypt))
return 0;
break;
}
# endif
# ifdef VPAES_CAPABLE
if (VPAES_CAPABLE) {
vpaes_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksenc.ks);
vpaes_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
(block128_f) vpaes_encrypt,
(block128_f) vpaes_decrypt,
NULL))
return 0;
break;
}
# endif
AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksenc.ks);
AES_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&octx->ksdec.ks);
if (!CRYPTO_ocb128_init(&octx->ocb,
&octx->ksenc.ks, &octx->ksdec.ks,
(block128_f) AES_encrypt,
(block128_f) AES_decrypt,
NULL))
return 0;
}
while (0);
/*
* If we have an iv we can set it directly, otherwise use saved IV.
*/
if (iv == NULL && octx->iv_set)
iv = octx->iv;
if (iv) {
if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen)
!= 1)
return 0;
octx->iv_set = 1;
}
octx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (octx->key_set)
CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
else
memcpy(octx->iv, iv, octx->ivlen);
octx->iv_set = 1;
}
return 1;
}
static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
unsigned char *buf;
int *buf_len;
int written_len = 0;
size_t trailing_len;
EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx);
/* If IV or Key not set then return error */
if (!octx->iv_set)
return -1;
if (!octx->key_set)
return -1;
if (in != NULL) {
/*
* Need to ensure we are only passing full blocks to low level OCB
* routines. We do it here rather than in EVP_EncryptUpdate/
* EVP_DecryptUpdate because we need to pass full blocks of AAD too
* and those routines don't support that
*/
/* Are we dealing with AAD or normal data here? */
if (out == NULL) {
buf = octx->aad_buf;
buf_len = &(octx->aad_buf_len);
} else {
buf = octx->data_buf;
buf_len = &(octx->data_buf_len);
if (is_partially_overlapping(out + *buf_len, in, len)) {
EVPerr(EVP_F_AES_OCB_CIPHER, EVP_R_PARTIALLY_OVERLAPPING);
return 0;
}
}
/*
* If we've got a partially filled buffer from a previous call then
* use that data first
*/
if (*buf_len > 0) {
unsigned int remaining;
remaining = AES_BLOCK_SIZE - (*buf_len);
if (remaining > len) {
memcpy(buf + (*buf_len), in, len);
*(buf_len) += len;
return 0;
}
memcpy(buf + (*buf_len), in, remaining);
/*
* If we get here we've filled the buffer, so process it
*/
len -= remaining;
in += remaining;
if (out == NULL) {
if (!CRYPTO_ocb128_aad(&octx->ocb, buf, AES_BLOCK_SIZE))
return -1;
} else if (EVP_CIPHER_CTX_encrypting(ctx)) {
if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out,
AES_BLOCK_SIZE))
return -1;
} else {
if (!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out,
AES_BLOCK_SIZE))
return -1;
}
written_len = AES_BLOCK_SIZE;
*buf_len = 0;
if (out != NULL)
out += AES_BLOCK_SIZE;
}
/* Do we have a partial block to handle at the end? */
trailing_len = len % AES_BLOCK_SIZE;
/*
* If we've got some full blocks to handle, then process these first
*/
if (len != trailing_len) {
if (out == NULL) {
if (!CRYPTO_ocb128_aad(&octx->ocb, in, len - trailing_len))
return -1;
} else if (EVP_CIPHER_CTX_encrypting(ctx)) {
if (!CRYPTO_ocb128_encrypt
(&octx->ocb, in, out, len - trailing_len))
return -1;
} else {
if (!CRYPTO_ocb128_decrypt
(&octx->ocb, in, out, len - trailing_len))
return -1;
}
written_len += len - trailing_len;
in += len - trailing_len;
}
/* Handle any trailing partial block */
if (trailing_len > 0) {
memcpy(buf, in, trailing_len);
*buf_len = trailing_len;
}
return written_len;
} else {
/*
* First of all empty the buffer of any partial block that we might
* have been provided - both for data and AAD
*/
if (octx->data_buf_len > 0) {
if (EVP_CIPHER_CTX_encrypting(ctx)) {
if (!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out,
octx->data_buf_len))
return -1;
} else {
if (!CRYPTO_ocb128_decrypt(&octx->ocb, octx->data_buf, out,
octx->data_buf_len))
return -1;
}
written_len = octx->data_buf_len;
octx->data_buf_len = 0;
}
if (octx->aad_buf_len > 0) {
if (!CRYPTO_ocb128_aad
(&octx->ocb, octx->aad_buf, octx->aad_buf_len))
return -1;
octx->aad_buf_len = 0;
}
/* If decrypting then verify */
if (!EVP_CIPHER_CTX_encrypting(ctx)) {
if (octx->taglen < 0)
return -1;
if (CRYPTO_ocb128_finish(&octx->ocb,
octx->tag, octx->taglen) != 0)
return -1;
octx->iv_set = 0;
return written_len;
}
/* If encrypting then just get the tag */
if (CRYPTO_ocb128_tag(&octx->ocb, octx->tag, 16) != 1)
return -1;
/* Don't reuse the IV */
octx->iv_set = 0;
return written_len;
}
}
static int aes_ocb_cleanup(EVP_CIPHER_CTX *c)
{
EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,c);
CRYPTO_ocb128_cleanup(&octx->ocb);
return 1;
}
BLOCK_CIPHER_custom(NID_aes, 128, 16, 12, ocb, OCB,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes, 192, 16, 12, ocb, OCB,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes, 256, 16, 12, ocb, OCB,
EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS)
#endif /* OPENSSL_NO_OCB */
diff --git a/crypto/evp/e_aria.c b/crypto/evp/e_aria.c
index 81c8a7eaf1d3..100573f5fc7f 100644
--- a/crypto/evp/e_aria.c
+++ b/crypto/evp/e_aria.c
@@ -1,756 +1,768 @@
/*
- * Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
#ifndef OPENSSL_NO_ARIA
# include <openssl/evp.h>
# include <openssl/modes.h>
# include <openssl/rand.h>
# include <openssl/rand_drbg.h>
# include "internal/aria.h"
# include "internal/evp_int.h"
# include "modes_lcl.h"
# include "evp_locl.h"
/* ARIA subkey Structure */
typedef struct {
ARIA_KEY ks;
} EVP_ARIA_KEY;
/* ARIA GCM context */
typedef struct {
union {
double align;
ARIA_KEY ks;
} ks; /* ARIA subkey to use */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
GCM128_CONTEXT gcm;
unsigned char *iv; /* Temporary IV store */
int ivlen; /* IV length */
int taglen;
int iv_gen; /* It is OK to generate IVs */
int tls_aad_len; /* TLS AAD length */
} EVP_ARIA_GCM_CTX;
/* ARIA CCM context */
typedef struct {
union {
double align;
ARIA_KEY ks;
} ks; /* ARIA key schedule to use */
int key_set; /* Set if key initialised */
int iv_set; /* Set if an iv is set */
int tag_set; /* Set if tag is valid */
int len_set; /* Set if message length set */
int L, M; /* L and M parameters from RFC3610 */
int tls_aad_len; /* TLS AAD length */
CCM128_CONTEXT ccm;
ccm128_f str;
} EVP_ARIA_CCM_CTX;
/* The subkey for ARIA is generated. */
static int aria_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret;
int mode = EVP_CIPHER_CTX_mode(ctx);
if (enc || (mode != EVP_CIPH_ECB_MODE && mode != EVP_CIPH_CBC_MODE))
ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
EVP_CIPHER_CTX_get_cipher_data(ctx));
else
ret = aria_set_decrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
EVP_CIPHER_CTX_get_cipher_data(ctx));
if (ret < 0) {
EVPerr(EVP_F_ARIA_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);
return 0;
}
return 1;
}
static void aria_cbc_encrypt(const unsigned char *in, unsigned char *out,
size_t len, const ARIA_KEY *key,
unsigned char *ivec, const int enc)
{
if (enc)
CRYPTO_cbc128_encrypt(in, out, len, key, ivec,
(block128_f) aria_encrypt);
else
CRYPTO_cbc128_decrypt(in, out, len, key, ivec,
(block128_f) aria_encrypt);
}
static void aria_cfb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const ARIA_KEY *key,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_encrypt(in, out, length, key, ivec, num, enc,
(block128_f) aria_encrypt);
}
static void aria_cfb1_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const ARIA_KEY *key,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_1_encrypt(in, out, length, key, ivec, num, enc,
(block128_f) aria_encrypt);
}
static void aria_cfb8_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const ARIA_KEY *key,
unsigned char *ivec, int *num, const int enc)
{
CRYPTO_cfb128_8_encrypt(in, out, length, key, ivec, num, enc,
(block128_f) aria_encrypt);
}
static void aria_ecb_encrypt(const unsigned char *in, unsigned char *out,
const ARIA_KEY *key, const int enc)
{
aria_encrypt(in, out, key);
}
static void aria_ofb128_encrypt(const unsigned char *in, unsigned char *out,
size_t length, const ARIA_KEY *key,
unsigned char *ivec, int *num)
{
CRYPTO_ofb128_encrypt(in, out, length, key, ivec, num,
(block128_f) aria_encrypt);
}
IMPLEMENT_BLOCK_CIPHER(aria_128, ks, aria, EVP_ARIA_KEY,
NID_aria_128, 16, 16, 16, 128,
0, aria_init_key, NULL,
EVP_CIPHER_set_asn1_iv,
EVP_CIPHER_get_asn1_iv,
NULL)
IMPLEMENT_BLOCK_CIPHER(aria_192, ks, aria, EVP_ARIA_KEY,
NID_aria_192, 16, 24, 16, 128,
0, aria_init_key, NULL,
EVP_CIPHER_set_asn1_iv,
EVP_CIPHER_get_asn1_iv,
NULL)
IMPLEMENT_BLOCK_CIPHER(aria_256, ks, aria, EVP_ARIA_KEY,
NID_aria_256, 16, 32, 16, 128,
0, aria_init_key, NULL,
EVP_CIPHER_set_asn1_iv,
EVP_CIPHER_get_asn1_iv,
NULL)
# define IMPLEMENT_ARIA_CFBR(ksize,cbits) \
IMPLEMENT_CFBR(aria,aria,EVP_ARIA_KEY,ks,ksize,cbits,16,0)
IMPLEMENT_ARIA_CFBR(128,1)
IMPLEMENT_ARIA_CFBR(192,1)
IMPLEMENT_ARIA_CFBR(256,1)
IMPLEMENT_ARIA_CFBR(128,8)
IMPLEMENT_ARIA_CFBR(192,8)
IMPLEMENT_ARIA_CFBR(256,8)
# define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aria_##keylen##_##mode = { \
nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
flags|EVP_CIPH_##MODE##_MODE, \
aria_init_key, \
aria_##mode##_cipher, \
NULL, \
sizeof(EVP_ARIA_KEY), \
NULL,NULL,NULL,NULL }; \
const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \
{ return &aria_##keylen##_##mode; }
static int aria_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
unsigned int num = EVP_CIPHER_CTX_num(ctx);
EVP_ARIA_KEY *dat = EVP_C_DATA(EVP_ARIA_KEY,ctx);
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks,
EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
(block128_f) aria_encrypt);
EVP_CIPHER_CTX_set_num(ctx, num);
return 1;
}
BLOCK_CIPHER_generic(NID_aria, 128, 1, 16, ctr, ctr, CTR, 0)
BLOCK_CIPHER_generic(NID_aria, 192, 1, 16, ctr, ctr, CTR, 0)
BLOCK_CIPHER_generic(NID_aria, 256, 1, 16, ctr, ctr, CTR, 0)
/* Authenticated cipher modes (GCM/CCM) */
/* increment counter (64-bit int) by 1 */
static void ctr64_inc(unsigned char *counter)
{
int n = 8;
unsigned char c;
do {
--n;
c = counter[n];
++c;
counter[n] = c;
if (c)
return;
} while (n);
}
static int aria_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret;
EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&gctx->ks.ks);
CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks,
(block128_f) aria_encrypt);
if (ret < 0) {
EVPerr(EVP_F_ARIA_GCM_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);
return 0;
}
/*
* If we have an iv can set it directly, otherwise use saved IV.
*/
if (iv == NULL && gctx->iv_set)
iv = gctx->iv;
if (iv) {
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
gctx->iv_set = 1;
}
gctx->key_set = 1;
} else {
/* If key set use IV, otherwise copy */
if (gctx->key_set)
CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen);
else
memcpy(gctx->iv, iv, gctx->ivlen);
gctx->iv_set = 1;
gctx->iv_gen = 0;
}
return 1;
}
static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,c);
switch (type) {
case EVP_CTRL_INIT:
gctx->key_set = 0;
gctx->iv_set = 0;
gctx->ivlen = EVP_CIPHER_CTX_iv_length(c);
gctx->iv = EVP_CIPHER_CTX_iv_noconst(c);
gctx->taglen = -1;
gctx->iv_gen = 0;
gctx->tls_aad_len = -1;
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
if (arg <= 0)
return 0;
/* Allocate memory for IV if needed */
if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) {
if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c))
OPENSSL_free(gctx->iv);
if ((gctx->iv = OPENSSL_malloc(arg)) == NULL) {
EVPerr(EVP_F_ARIA_GCM_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
}
gctx->ivlen = arg;
return 1;
case EVP_CTRL_AEAD_SET_TAG:
if (arg <= 0 || arg > 16 || EVP_CIPHER_CTX_encrypting(c))
return 0;
memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
gctx->taglen = arg;
return 1;
case EVP_CTRL_AEAD_GET_TAG:
if (arg <= 0 || arg > 16 || !EVP_CIPHER_CTX_encrypting(c)
|| gctx->taglen < 0)
return 0;
memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(c), arg);
return 1;
case EVP_CTRL_GCM_SET_IV_FIXED:
/* Special case: -1 length restores whole IV */
if (arg == -1) {
memcpy(gctx->iv, ptr, gctx->ivlen);
gctx->iv_gen = 1;
return 1;
}
/*
* Fixed field must be at least 4 bytes and invocation field at least
* 8.
*/
if ((arg < 4) || (gctx->ivlen - arg) < 8)
return 0;
if (arg)
memcpy(gctx->iv, ptr, arg);
if (EVP_CIPHER_CTX_encrypting(c)
&& RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
return 0;
gctx->iv_gen = 1;
return 1;
case EVP_CTRL_GCM_IV_GEN:
if (gctx->iv_gen == 0 || gctx->key_set == 0)
return 0;
CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
if (arg <= 0 || arg > gctx->ivlen)
arg = gctx->ivlen;
memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
/*
* Invocation field will be at least 8 bytes in size and so no need
* to check wrap around or increment more than last 8 bytes.
*/
ctr64_inc(gctx->iv + gctx->ivlen - 8);
gctx->iv_set = 1;
return 1;
case EVP_CTRL_GCM_SET_IV_INV:
if (gctx->iv_gen == 0 || gctx->key_set == 0
|| EVP_CIPHER_CTX_encrypting(c))
return 0;
memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
gctx->iv_set = 1;
return 1;
case EVP_CTRL_AEAD_TLS1_AAD:
/* Save the AAD for later use */
if (arg != EVP_AEAD_TLS1_AAD_LEN)
return 0;
memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
gctx->tls_aad_len = arg;
{
unsigned int len =
EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8
| EVP_CIPHER_CTX_buf_noconst(c)[arg - 1];
/* Correct length for explicit IV */
if (len < EVP_GCM_TLS_EXPLICIT_IV_LEN)
return 0;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too */
if (!EVP_CIPHER_CTX_encrypting(c)) {
if (len < EVP_GCM_TLS_TAG_LEN)
return 0;
len -= EVP_GCM_TLS_TAG_LEN;
}
EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8;
EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff;
}
/* Extra padding: tag appended to record */
return EVP_GCM_TLS_TAG_LEN;
case EVP_CTRL_COPY:
{
EVP_CIPHER_CTX *out = ptr;
EVP_ARIA_GCM_CTX *gctx_out = EVP_C_DATA(EVP_ARIA_GCM_CTX,out);
if (gctx->gcm.key) {
if (gctx->gcm.key != &gctx->ks)
return 0;
gctx_out->gcm.key = &gctx_out->ks;
}
if (gctx->iv == EVP_CIPHER_CTX_iv_noconst(c))
gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out);
else {
if ((gctx_out->iv = OPENSSL_malloc(gctx->ivlen)) == NULL) {
EVPerr(EVP_F_ARIA_GCM_CTRL, ERR_R_MALLOC_FAILURE);
return 0;
}
memcpy(gctx_out->iv, gctx->iv, gctx->ivlen);
}
return 1;
}
default:
return -1;
}
}
static int aria_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx);
int rv = -1;
/* Encrypt/decrypt must be performed in place */
if (out != in
|| len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN))
return -1;
/*
* Set IV from start of buffer or generate IV and write to start of
* buffer.
*/
if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CIPHER_CTX_encrypting(ctx) ?
EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
goto err;
/* Use saved AAD */
if (CRYPTO_gcm128_aad(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx),
gctx->tls_aad_len))
goto err;
/* Fix buffer and length to point to payload */
in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
if (EVP_CIPHER_CTX_encrypting(ctx)) {
/* Encrypt payload */
if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
goto err;
out += len;
/* Finally write tag */
CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
} else {
/* Decrypt */
if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
goto err;
/* Retrieve tag */
CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx),
EVP_GCM_TLS_TAG_LEN);
/* If tag mismatch wipe buffer */
if (CRYPTO_memcmp(EVP_CIPHER_CTX_buf_noconst(ctx), in + len,
EVP_GCM_TLS_TAG_LEN)) {
OPENSSL_cleanse(out, len);
goto err;
}
rv = len;
}
err:
gctx->iv_set = 0;
gctx->tls_aad_len = -1;
return rv;
}
static int aria_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX,ctx);
/* If not set up, return error */
if (!gctx->key_set)
return -1;
if (gctx->tls_aad_len >= 0)
return aria_gcm_tls_cipher(ctx, out, in, len);
if (!gctx->iv_set)
return -1;
if (in) {
if (out == NULL) {
if (CRYPTO_gcm128_aad(&gctx->gcm, in, len))
return -1;
} else if (EVP_CIPHER_CTX_encrypting(ctx)) {
if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
return -1;
} else {
if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
return -1;
}
return len;
}
if (!EVP_CIPHER_CTX_encrypting(ctx)) {
if (gctx->taglen < 0)
return -1;
if (CRYPTO_gcm128_finish(&gctx->gcm,
EVP_CIPHER_CTX_buf_noconst(ctx),
gctx->taglen) != 0)
return -1;
gctx->iv_set = 0;
return 0;
}
CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), 16);
gctx->taglen = 16;
/* Don't reuse the IV */
gctx->iv_set = 0;
return 0;
}
+static int aria_gcm_cleanup(EVP_CIPHER_CTX *ctx)
+{
+ EVP_ARIA_GCM_CTX *gctx = EVP_C_DATA(EVP_ARIA_GCM_CTX, ctx);
+
+ if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(ctx))
+ OPENSSL_free(gctx->iv);
+
+ return 1;
+}
+
static int aria_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
int ret;
EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx);
if (!iv && !key)
return 1;
if (key) {
ret = aria_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8,
&cctx->ks.ks);
CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L,
&cctx->ks, (block128_f) aria_encrypt);
if (ret < 0) {
EVPerr(EVP_F_ARIA_CCM_INIT_KEY,EVP_R_ARIA_KEY_SETUP_FAILED);
return 0;
}
cctx->str = NULL;
cctx->key_set = 1;
}
if (iv) {
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L);
cctx->iv_set = 1;
}
return 1;
}
static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
{
EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,c);
switch (type) {
case EVP_CTRL_INIT:
cctx->key_set = 0;
cctx->iv_set = 0;
cctx->L = 8;
cctx->M = 12;
cctx->tag_set = 0;
cctx->len_set = 0;
cctx->tls_aad_len = -1;
return 1;
case EVP_CTRL_AEAD_TLS1_AAD:
/* Save the AAD for later use */
if (arg != EVP_AEAD_TLS1_AAD_LEN)
return 0;
memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
cctx->tls_aad_len = arg;
{
uint16_t len =
EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8
| EVP_CIPHER_CTX_buf_noconst(c)[arg - 1];
/* Correct length for explicit IV */
if (len < EVP_CCM_TLS_EXPLICIT_IV_LEN)
return 0;
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN;
/* If decrypting correct for tag too */
if (!EVP_CIPHER_CTX_encrypting(c)) {
if (len < cctx->M)
return 0;
len -= cctx->M;
}
EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8;
EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff;
}
/* Extra padding: tag appended to record */
return cctx->M;
case EVP_CTRL_CCM_SET_IV_FIXED:
/* Sanity check length */
if (arg != EVP_CCM_TLS_FIXED_IV_LEN)
return 0;
/* Just copy to first part of IV */
memcpy(EVP_CIPHER_CTX_iv_noconst(c), ptr, arg);
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
arg = 15 - arg;
/* fall thru */
case EVP_CTRL_CCM_SET_L:
if (arg < 2 || arg > 8)
return 0;
cctx->L = arg;
return 1;
case EVP_CTRL_AEAD_SET_TAG:
if ((arg & 1) || arg < 4 || arg > 16)
return 0;
if (EVP_CIPHER_CTX_encrypting(c) && ptr)
return 0;
if (ptr) {
cctx->tag_set = 1;
memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg);
}
cctx->M = arg;
return 1;
case EVP_CTRL_AEAD_GET_TAG:
if (!EVP_CIPHER_CTX_encrypting(c) || !cctx->tag_set)
return 0;
if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg))
return 0;
cctx->tag_set = 0;
cctx->iv_set = 0;
cctx->len_set = 0;
return 1;
case EVP_CTRL_COPY:
{
EVP_CIPHER_CTX *out = ptr;
EVP_ARIA_CCM_CTX *cctx_out = EVP_C_DATA(EVP_ARIA_CCM_CTX,out);
if (cctx->ccm.key) {
if (cctx->ccm.key != &cctx->ks)
return 0;
cctx_out->ccm.key = &cctx_out->ks;
}
return 1;
}
default:
return -1;
}
}
static int aria_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx);
CCM128_CONTEXT *ccm = &cctx->ccm;
/* Encrypt/decrypt must be performed in place */
if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M))
return -1;
/* If encrypting set explicit IV from sequence number (start of AAD) */
if (EVP_CIPHER_CTX_encrypting(ctx))
memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx),
EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Get rest of IV from explicit IV */
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx) + EVP_CCM_TLS_FIXED_IV_LEN, in,
EVP_CCM_TLS_EXPLICIT_IV_LEN);
/* Correct length value */
len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), 15 - cctx->L,
len))
return -1;
/* Use saved AAD */
CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx), cctx->tls_aad_len);
/* Fix buffer to point to payload */
in += EVP_CCM_TLS_EXPLICIT_IV_LEN;
out += EVP_CCM_TLS_EXPLICIT_IV_LEN;
if (EVP_CIPHER_CTX_encrypting(ctx)) {
if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, cctx->str)
: CRYPTO_ccm128_encrypt(ccm, in, out, len))
return -1;
if (!CRYPTO_ccm128_tag(ccm, out + len, cctx->M))
return -1;
return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M;
} else {
if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, cctx->str)
: !CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
unsigned char tag[16];
if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
if (!CRYPTO_memcmp(tag, in + len, cctx->M))
return len;
}
}
OPENSSL_cleanse(out, len);
return -1;
}
}
static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_ARIA_CCM_CTX *cctx = EVP_C_DATA(EVP_ARIA_CCM_CTX,ctx);
CCM128_CONTEXT *ccm = &cctx->ccm;
/* If not set up, return error */
if (!cctx->key_set)
return -1;
if (cctx->tls_aad_len >= 0)
return aria_ccm_tls_cipher(ctx, out, in, len);
/* EVP_*Final() doesn't return any data */
if (in == NULL && out != NULL)
return 0;
if (!cctx->iv_set)
return -1;
if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set)
return -1;
if (!out) {
if (!in) {
if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
15 - cctx->L, len))
return -1;
cctx->len_set = 1;
return len;
}
/* If have AAD need message length */
if (!cctx->len_set && len)
return -1;
CRYPTO_ccm128_aad(ccm, in, len);
return len;
}
/* If not set length yet do it */
if (!cctx->len_set) {
if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx),
15 - cctx->L, len))
return -1;
cctx->len_set = 1;
}
if (EVP_CIPHER_CTX_encrypting(ctx)) {
if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, cctx->str)
: CRYPTO_ccm128_encrypt(ccm, in, out, len))
return -1;
cctx->tag_set = 1;
return len;
} else {
int rv = -1;
if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len,
cctx->str) :
!CRYPTO_ccm128_decrypt(ccm, in, out, len)) {
unsigned char tag[16];
if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) {
if (!CRYPTO_memcmp(tag, EVP_CIPHER_CTX_buf_noconst(ctx),
cctx->M))
rv = len;
}
}
if (rv == -1)
OPENSSL_cleanse(out, len);
cctx->iv_set = 0;
cctx->tag_set = 0;
cctx->len_set = 0;
return rv;
}
}
+#define aria_ccm_cleanup NULL
+
#define ARIA_AUTH_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \
| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \
| EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_AEAD_CIPHER)
#define BLOCK_CIPHER_aead(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aria_##keylen##_##mode = { \
nid##_##keylen##_##nmode, \
blocksize, keylen/8, ivlen, \
ARIA_AUTH_FLAGS|EVP_CIPH_##MODE##_MODE, \
aria_##mode##_init_key, \
aria_##mode##_cipher, \
- NULL, \
+ aria_##mode##_cleanup, \
sizeof(EVP_ARIA_##MODE##_CTX), \
NULL,NULL,aria_##mode##_ctrl,NULL }; \
const EVP_CIPHER *EVP_aria_##keylen##_##mode(void) \
{ return (EVP_CIPHER*)&aria_##keylen##_##mode; }
BLOCK_CIPHER_aead(NID_aria, 128, 1, 12, gcm, gcm, GCM, 0)
BLOCK_CIPHER_aead(NID_aria, 192, 1, 12, gcm, gcm, GCM, 0)
BLOCK_CIPHER_aead(NID_aria, 256, 1, 12, gcm, gcm, GCM, 0)
BLOCK_CIPHER_aead(NID_aria, 128, 1, 12, ccm, ccm, CCM, 0)
BLOCK_CIPHER_aead(NID_aria, 192, 1, 12, ccm, ccm, CCM, 0)
BLOCK_CIPHER_aead(NID_aria, 256, 1, 12, ccm, ccm, CCM, 0)
#endif
diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c
index c1917bb86a6b..600365d2f077 100644
--- a/crypto/evp/e_chacha20_poly1305.c
+++ b/crypto/evp/e_chacha20_poly1305.c
@@ -1,630 +1,632 @@
/*
- * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#ifndef OPENSSL_NO_CHACHA
# include <openssl/evp.h>
# include <openssl/objects.h>
# include "evp_locl.h"
# include "internal/evp_int.h"
# include "internal/chacha.h"
typedef struct {
union {
double align; /* this ensures even sizeof(EVP_CHACHA_KEY)%8==0 */
unsigned int d[CHACHA_KEY_SIZE / 4];
} key;
unsigned int counter[CHACHA_CTR_SIZE / 4];
unsigned char buf[CHACHA_BLK_SIZE];
unsigned int partial_len;
} EVP_CHACHA_KEY;
#define data(ctx) ((EVP_CHACHA_KEY *)(ctx)->cipher_data)
+#define CHACHA20_POLY1305_MAX_IVLEN 12
+
static int chacha_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char user_key[CHACHA_KEY_SIZE],
const unsigned char iv[CHACHA_CTR_SIZE], int enc)
{
EVP_CHACHA_KEY *key = data(ctx);
unsigned int i;
if (user_key)
for (i = 0; i < CHACHA_KEY_SIZE; i+=4) {
key->key.d[i/4] = CHACHA_U8TOU32(user_key+i);
}
if (iv)
for (i = 0; i < CHACHA_CTR_SIZE; i+=4) {
key->counter[i/4] = CHACHA_U8TOU32(iv+i);
}
key->partial_len = 0;
return 1;
}
static int chacha_cipher(EVP_CIPHER_CTX * ctx, unsigned char *out,
const unsigned char *inp, size_t len)
{
EVP_CHACHA_KEY *key = data(ctx);
unsigned int n, rem, ctr32;
if ((n = key->partial_len)) {
while (len && n < CHACHA_BLK_SIZE) {
*out++ = *inp++ ^ key->buf[n++];
len--;
}
key->partial_len = n;
if (len == 0)
return 1;
if (n == CHACHA_BLK_SIZE) {
key->partial_len = 0;
key->counter[0]++;
if (key->counter[0] == 0)
key->counter[1]++;
}
}
rem = (unsigned int)(len % CHACHA_BLK_SIZE);
len -= rem;
ctr32 = key->counter[0];
while (len >= CHACHA_BLK_SIZE) {
size_t blocks = len / CHACHA_BLK_SIZE;
/*
* 1<<28 is just a not-so-small yet not-so-large number...
* Below condition is practically never met, but it has to
* be checked for code correctness.
*/
if (sizeof(size_t)>sizeof(unsigned int) && blocks>(1U<<28))
blocks = (1U<<28);
/*
* As ChaCha20_ctr32 operates on 32-bit counter, caller
* has to handle overflow. 'if' below detects the
* overflow, which is then handled by limiting the
* amount of blocks to the exact overflow point...
*/
ctr32 += (unsigned int)blocks;
if (ctr32 < blocks) {
blocks -= ctr32;
ctr32 = 0;
}
blocks *= CHACHA_BLK_SIZE;
ChaCha20_ctr32(out, inp, blocks, key->key.d, key->counter);
len -= blocks;
inp += blocks;
out += blocks;
key->counter[0] = ctr32;
if (ctr32 == 0) key->counter[1]++;
}
if (rem) {
memset(key->buf, 0, sizeof(key->buf));
ChaCha20_ctr32(key->buf, key->buf, CHACHA_BLK_SIZE,
key->key.d, key->counter);
for (n = 0; n < rem; n++)
out[n] = inp[n] ^ key->buf[n];
key->partial_len = rem;
}
return 1;
}
static const EVP_CIPHER chacha20 = {
NID_chacha20,
1, /* block_size */
CHACHA_KEY_SIZE, /* key_len */
CHACHA_CTR_SIZE, /* iv_len, 128-bit counter in the context */
EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT,
chacha_init_key,
chacha_cipher,
NULL,
sizeof(EVP_CHACHA_KEY),
NULL,
NULL,
NULL,
NULL
};
const EVP_CIPHER *EVP_chacha20(void)
{
return &chacha20;
}
# ifndef OPENSSL_NO_POLY1305
# include "internal/poly1305.h"
typedef struct {
EVP_CHACHA_KEY key;
unsigned int nonce[12/4];
unsigned char tag[POLY1305_BLOCK_SIZE];
unsigned char tls_aad[POLY1305_BLOCK_SIZE];
struct { uint64_t aad, text; } len;
int aad, mac_inited, tag_len, nonce_len;
size_t tls_payload_length;
} EVP_CHACHA_AEAD_CTX;
# define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
# define aead_data(ctx) ((EVP_CHACHA_AEAD_CTX *)(ctx)->cipher_data)
# define POLY1305_ctx(actx) ((POLY1305 *)(actx + 1))
static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
const unsigned char *inkey,
const unsigned char *iv, int enc)
{
EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
if (!inkey && !iv)
return 1;
actx->len.aad = 0;
actx->len.text = 0;
actx->aad = 0;
actx->mac_inited = 0;
actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
if (iv != NULL) {
unsigned char temp[CHACHA_CTR_SIZE] = { 0 };
/* pad on the left */
if (actx->nonce_len <= CHACHA_CTR_SIZE)
memcpy(temp + CHACHA_CTR_SIZE - actx->nonce_len, iv,
actx->nonce_len);
chacha_init_key(ctx, inkey, temp, enc);
actx->nonce[0] = actx->key.counter[1];
actx->nonce[1] = actx->key.counter[2];
actx->nonce[2] = actx->key.counter[3];
} else {
chacha_init_key(ctx, inkey, NULL, enc);
}
return 1;
}
# if !defined(OPENSSL_SMALL_FOOTPRINT)
# if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
defined(_M_AMD64) || defined(_M_X64))
# define XOR128_HELPERS
void *xor128_encrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
void *xor128_decrypt_n_pad(void *out, const void *inp, void *otp, size_t len);
static const unsigned char zero[4 * CHACHA_BLK_SIZE] = { 0 };
# else
static const unsigned char zero[2 * CHACHA_BLK_SIZE] = { 0 };
# endif
static int chacha20_poly1305_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
size_t tail, tohash_len, buf_len, plen = actx->tls_payload_length;
unsigned char *buf, *tohash, *ctr, storage[sizeof(zero) + 32];
if (len != plen + POLY1305_BLOCK_SIZE)
return -1;
buf = storage + ((0 - (size_t)storage) & 15); /* align */
ctr = buf + CHACHA_BLK_SIZE;
tohash = buf + CHACHA_BLK_SIZE - POLY1305_BLOCK_SIZE;
# ifdef XOR128_HELPERS
if (plen <= 3 * CHACHA_BLK_SIZE) {
actx->key.counter[0] = 0;
buf_len = (plen + 2 * CHACHA_BLK_SIZE - 1) & (0 - CHACHA_BLK_SIZE);
ChaCha20_ctr32(buf, zero, buf_len, actx->key.key.d,
actx->key.counter);
Poly1305_Init(POLY1305_ctx(actx), buf);
actx->key.partial_len = 0;
memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE);
tohash_len = POLY1305_BLOCK_SIZE;
actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
actx->len.text = plen;
if (plen) {
if (ctx->encrypt)
ctr = xor128_encrypt_n_pad(out, in, ctr, plen);
else
ctr = xor128_decrypt_n_pad(out, in, ctr, plen);
in += plen;
out += plen;
tohash_len = (size_t)(ctr - tohash);
}
}
# else
if (plen <= CHACHA_BLK_SIZE) {
size_t i;
actx->key.counter[0] = 0;
ChaCha20_ctr32(buf, zero, (buf_len = 2 * CHACHA_BLK_SIZE),
actx->key.key.d, actx->key.counter);
Poly1305_Init(POLY1305_ctx(actx), buf);
actx->key.partial_len = 0;
memcpy(tohash, actx->tls_aad, POLY1305_BLOCK_SIZE);
tohash_len = POLY1305_BLOCK_SIZE;
actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
actx->len.text = plen;
if (ctx->encrypt) {
for (i = 0; i < plen; i++) {
out[i] = ctr[i] ^= in[i];
}
} else {
for (i = 0; i < plen; i++) {
unsigned char c = in[i];
out[i] = ctr[i] ^ c;
ctr[i] = c;
}
}
in += i;
out += i;
tail = (0 - i) & (POLY1305_BLOCK_SIZE - 1);
memset(ctr + i, 0, tail);
ctr += i + tail;
tohash_len += i + tail;
}
# endif
else {
actx->key.counter[0] = 0;
ChaCha20_ctr32(buf, zero, (buf_len = CHACHA_BLK_SIZE),
actx->key.key.d, actx->key.counter);
Poly1305_Init(POLY1305_ctx(actx), buf);
actx->key.counter[0] = 1;
actx->key.partial_len = 0;
Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad, POLY1305_BLOCK_SIZE);
tohash = ctr;
tohash_len = 0;
actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
actx->len.text = plen;
if (ctx->encrypt) {
ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter);
Poly1305_Update(POLY1305_ctx(actx), out, plen);
} else {
Poly1305_Update(POLY1305_ctx(actx), in, plen);
ChaCha20_ctr32(out, in, plen, actx->key.key.d, actx->key.counter);
}
in += plen;
out += plen;
tail = (0 - plen) & (POLY1305_BLOCK_SIZE - 1);
Poly1305_Update(POLY1305_ctx(actx), zero, tail);
}
{
const union {
long one;
char little;
} is_endian = { 1 };
if (is_endian.little) {
memcpy(ctr, (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
} else {
ctr[0] = (unsigned char)(actx->len.aad);
ctr[1] = (unsigned char)(actx->len.aad>>8);
ctr[2] = (unsigned char)(actx->len.aad>>16);
ctr[3] = (unsigned char)(actx->len.aad>>24);
ctr[4] = (unsigned char)(actx->len.aad>>32);
ctr[5] = (unsigned char)(actx->len.aad>>40);
ctr[6] = (unsigned char)(actx->len.aad>>48);
ctr[7] = (unsigned char)(actx->len.aad>>56);
ctr[8] = (unsigned char)(actx->len.text);
ctr[9] = (unsigned char)(actx->len.text>>8);
ctr[10] = (unsigned char)(actx->len.text>>16);
ctr[11] = (unsigned char)(actx->len.text>>24);
ctr[12] = (unsigned char)(actx->len.text>>32);
ctr[13] = (unsigned char)(actx->len.text>>40);
ctr[14] = (unsigned char)(actx->len.text>>48);
ctr[15] = (unsigned char)(actx->len.text>>56);
}
tohash_len += POLY1305_BLOCK_SIZE;
}
Poly1305_Update(POLY1305_ctx(actx), tohash, tohash_len);
OPENSSL_cleanse(buf, buf_len);
Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
: tohash);
actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
if (ctx->encrypt) {
memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
} else {
if (CRYPTO_memcmp(tohash, in, POLY1305_BLOCK_SIZE)) {
memset(out - (len - POLY1305_BLOCK_SIZE), 0,
len - POLY1305_BLOCK_SIZE);
return -1;
}
}
return len;
}
# else
static const unsigned char zero[CHACHA_BLK_SIZE] = { 0 };
# endif
static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in, size_t len)
{
EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
size_t rem, plen = actx->tls_payload_length;
if (!actx->mac_inited) {
# if !defined(OPENSSL_SMALL_FOOTPRINT)
if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL)
return chacha20_poly1305_tls_cipher(ctx, out, in, len);
# endif
actx->key.counter[0] = 0;
ChaCha20_ctr32(actx->key.buf, zero, CHACHA_BLK_SIZE,
actx->key.key.d, actx->key.counter);
Poly1305_Init(POLY1305_ctx(actx), actx->key.buf);
actx->key.counter[0] = 1;
actx->key.partial_len = 0;
actx->len.aad = actx->len.text = 0;
actx->mac_inited = 1;
if (plen != NO_TLS_PAYLOAD_LENGTH) {
Poly1305_Update(POLY1305_ctx(actx), actx->tls_aad,
EVP_AEAD_TLS1_AAD_LEN);
actx->len.aad = EVP_AEAD_TLS1_AAD_LEN;
actx->aad = 1;
}
}
if (in) { /* aad or text */
if (out == NULL) { /* aad */
Poly1305_Update(POLY1305_ctx(actx), in, len);
actx->len.aad += len;
actx->aad = 1;
return len;
} else { /* plain- or ciphertext */
if (actx->aad) { /* wrap up aad */
if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
Poly1305_Update(POLY1305_ctx(actx), zero,
POLY1305_BLOCK_SIZE - rem);
actx->aad = 0;
}
actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
if (plen == NO_TLS_PAYLOAD_LENGTH)
plen = len;
else if (len != plen + POLY1305_BLOCK_SIZE)
return -1;
if (ctx->encrypt) { /* plaintext */
chacha_cipher(ctx, out, in, plen);
Poly1305_Update(POLY1305_ctx(actx), out, plen);
in += plen;
out += plen;
actx->len.text += plen;
} else { /* ciphertext */
Poly1305_Update(POLY1305_ctx(actx), in, plen);
chacha_cipher(ctx, out, in, plen);
in += plen;
out += plen;
actx->len.text += plen;
}
}
}
if (in == NULL /* explicit final */
|| plen != len) { /* or tls mode */
const union {
long one;
char little;
} is_endian = { 1 };
unsigned char temp[POLY1305_BLOCK_SIZE];
if (actx->aad) { /* wrap up aad */
if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
Poly1305_Update(POLY1305_ctx(actx), zero,
POLY1305_BLOCK_SIZE - rem);
actx->aad = 0;
}
if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE))
Poly1305_Update(POLY1305_ctx(actx), zero,
POLY1305_BLOCK_SIZE - rem);
if (is_endian.little) {
Poly1305_Update(POLY1305_ctx(actx),
(unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
} else {
temp[0] = (unsigned char)(actx->len.aad);
temp[1] = (unsigned char)(actx->len.aad>>8);
temp[2] = (unsigned char)(actx->len.aad>>16);
temp[3] = (unsigned char)(actx->len.aad>>24);
temp[4] = (unsigned char)(actx->len.aad>>32);
temp[5] = (unsigned char)(actx->len.aad>>40);
temp[6] = (unsigned char)(actx->len.aad>>48);
temp[7] = (unsigned char)(actx->len.aad>>56);
temp[8] = (unsigned char)(actx->len.text);
temp[9] = (unsigned char)(actx->len.text>>8);
temp[10] = (unsigned char)(actx->len.text>>16);
temp[11] = (unsigned char)(actx->len.text>>24);
temp[12] = (unsigned char)(actx->len.text>>32);
temp[13] = (unsigned char)(actx->len.text>>40);
temp[14] = (unsigned char)(actx->len.text>>48);
temp[15] = (unsigned char)(actx->len.text>>56);
Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE);
}
Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
: temp);
actx->mac_inited = 0;
if (in != NULL && len != plen) { /* tls mode */
if (ctx->encrypt) {
memcpy(out, actx->tag, POLY1305_BLOCK_SIZE);
} else {
if (CRYPTO_memcmp(temp, in, POLY1305_BLOCK_SIZE)) {
memset(out - plen, 0, plen);
return -1;
}
}
}
else if (!ctx->encrypt) {
if (CRYPTO_memcmp(temp, actx->tag, actx->tag_len))
return -1;
}
}
return len;
}
static int chacha20_poly1305_cleanup(EVP_CIPHER_CTX *ctx)
{
EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
if (actx)
OPENSSL_cleanse(ctx->cipher_data, sizeof(*actx) + Poly1305_ctx_size());
return 1;
}
static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
void *ptr)
{
EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
switch(type) {
case EVP_CTRL_INIT:
if (actx == NULL)
actx = ctx->cipher_data
= OPENSSL_zalloc(sizeof(*actx) + Poly1305_ctx_size());
if (actx == NULL) {
EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_INITIALIZATION_ERROR);
return 0;
}
actx->len.aad = 0;
actx->len.text = 0;
actx->aad = 0;
actx->mac_inited = 0;
actx->tag_len = 0;
actx->nonce_len = 12;
actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
memset(actx->tls_aad, 0, POLY1305_BLOCK_SIZE);
return 1;
case EVP_CTRL_COPY:
if (actx) {
EVP_CIPHER_CTX *dst = (EVP_CIPHER_CTX *)ptr;
dst->cipher_data =
OPENSSL_memdup(actx, sizeof(*actx) + Poly1305_ctx_size());
if (dst->cipher_data == NULL) {
EVPerr(EVP_F_CHACHA20_POLY1305_CTRL, EVP_R_COPY_ERROR);
return 0;
}
}
return 1;
case EVP_CTRL_AEAD_SET_IVLEN:
- if (arg <= 0 || arg > CHACHA_CTR_SIZE)
+ if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN)
return 0;
actx->nonce_len = arg;
return 1;
case EVP_CTRL_AEAD_SET_IV_FIXED:
if (arg != 12)
return 0;
actx->nonce[0] = actx->key.counter[1]
= CHACHA_U8TOU32((unsigned char *)ptr);
actx->nonce[1] = actx->key.counter[2]
= CHACHA_U8TOU32((unsigned char *)ptr+4);
actx->nonce[2] = actx->key.counter[3]
= CHACHA_U8TOU32((unsigned char *)ptr+8);
return 1;
case EVP_CTRL_AEAD_SET_TAG:
if (arg <= 0 || arg > POLY1305_BLOCK_SIZE)
return 0;
if (ptr != NULL) {
memcpy(actx->tag, ptr, arg);
actx->tag_len = arg;
}
return 1;
case EVP_CTRL_AEAD_GET_TAG:
if (arg <= 0 || arg > POLY1305_BLOCK_SIZE || !ctx->encrypt)
return 0;
memcpy(ptr, actx->tag, arg);
return 1;
case EVP_CTRL_AEAD_TLS1_AAD:
if (arg != EVP_AEAD_TLS1_AAD_LEN)
return 0;
{
unsigned int len;
unsigned char *aad = ptr;
memcpy(actx->tls_aad, ptr, EVP_AEAD_TLS1_AAD_LEN);
len = aad[EVP_AEAD_TLS1_AAD_LEN - 2] << 8 |
aad[EVP_AEAD_TLS1_AAD_LEN - 1];
aad = actx->tls_aad;
if (!ctx->encrypt) {
if (len < POLY1305_BLOCK_SIZE)
return 0;
len -= POLY1305_BLOCK_SIZE; /* discount attached tag */
aad[EVP_AEAD_TLS1_AAD_LEN - 2] = (unsigned char)(len >> 8);
aad[EVP_AEAD_TLS1_AAD_LEN - 1] = (unsigned char)len;
}
actx->tls_payload_length = len;
/*
* merge record sequence number as per RFC7905
*/
actx->key.counter[1] = actx->nonce[0];
actx->key.counter[2] = actx->nonce[1] ^ CHACHA_U8TOU32(aad);
actx->key.counter[3] = actx->nonce[2] ^ CHACHA_U8TOU32(aad+4);
actx->mac_inited = 0;
return POLY1305_BLOCK_SIZE; /* tag length */
}
case EVP_CTRL_AEAD_SET_MAC_KEY:
/* no-op */
return 1;
default:
return -1;
}
}
static EVP_CIPHER chacha20_poly1305 = {
NID_chacha20_poly1305,
1, /* block_size */
CHACHA_KEY_SIZE, /* key_len */
12, /* iv_len, 96-bit nonce in the context */
EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV |
EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER,
chacha20_poly1305_init_key,
chacha20_poly1305_cipher,
chacha20_poly1305_cleanup,
0, /* 0 moves context-specific structure allocation to ctrl */
NULL, /* set_asn1_parameters */
NULL, /* get_asn1_parameters */
chacha20_poly1305_ctrl,
NULL /* app_data */
};
const EVP_CIPHER *EVP_chacha20_poly1305(void)
{
return(&chacha20_poly1305);
}
# endif
#endif
diff --git a/crypto/evp/p_lib.c b/crypto/evp/p_lib.c
index 148df90f84b1..3cd7ca8d54ca 100644
--- a/crypto/evp/p_lib.c
+++ b/crypto/evp/p_lib.c
@@ -1,686 +1,691 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
#include <openssl/dh.h>
#include <openssl/cmac.h>
#include <openssl/engine.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
static void EVP_PKEY_free_it(EVP_PKEY *x);
int EVP_PKEY_bits(const EVP_PKEY *pkey)
{
if (pkey && pkey->ameth && pkey->ameth->pkey_bits)
return pkey->ameth->pkey_bits(pkey);
return 0;
}
int EVP_PKEY_security_bits(const EVP_PKEY *pkey)
{
if (pkey == NULL)
return 0;
if (!pkey->ameth || !pkey->ameth->pkey_security_bits)
return -2;
return pkey->ameth->pkey_security_bits(pkey);
}
int EVP_PKEY_size(const EVP_PKEY *pkey)
{
if (pkey && pkey->ameth && pkey->ameth->pkey_size)
return pkey->ameth->pkey_size(pkey);
return 0;
}
int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode)
{
#ifndef OPENSSL_NO_DSA
if (pkey->type == EVP_PKEY_DSA) {
int ret = pkey->save_parameters;
if (mode >= 0)
pkey->save_parameters = mode;
return ret;
}
#endif
#ifndef OPENSSL_NO_EC
if (pkey->type == EVP_PKEY_EC) {
int ret = pkey->save_parameters;
if (mode >= 0)
pkey->save_parameters = mode;
return ret;
}
#endif
return 0;
}
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
{
if (to->type == EVP_PKEY_NONE) {
if (EVP_PKEY_set_type(to, from->type) == 0)
return 0;
} else if (to->type != from->type) {
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_KEY_TYPES);
goto err;
}
if (EVP_PKEY_missing_parameters(from)) {
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_MISSING_PARAMETERS);
goto err;
}
if (!EVP_PKEY_missing_parameters(to)) {
if (EVP_PKEY_cmp_parameters(to, from) == 1)
return 1;
EVPerr(EVP_F_EVP_PKEY_COPY_PARAMETERS, EVP_R_DIFFERENT_PARAMETERS);
return 0;
}
if (from->ameth && from->ameth->param_copy)
return from->ameth->param_copy(to, from);
err:
return 0;
}
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey)
{
if (pkey->ameth && pkey->ameth->param_missing)
return pkey->ameth->param_missing(pkey);
return 0;
}
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
{
if (a->type != b->type)
return -1;
if (a->ameth && a->ameth->param_cmp)
return a->ameth->param_cmp(a, b);
return -2;
}
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
if (a->type != b->type)
return -1;
if (a->ameth) {
int ret;
/* Compare parameters if the algorithm has them */
if (a->ameth->param_cmp) {
ret = a->ameth->param_cmp(a, b);
if (ret <= 0)
return ret;
}
if (a->ameth->pub_cmp)
return a->ameth->pub_cmp(a, b);
}
return -2;
}
EVP_PKEY *EVP_PKEY_new(void)
{
EVP_PKEY *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->type = EVP_PKEY_NONE;
ret->save_type = EVP_PKEY_NONE;
ret->references = 1;
ret->save_parameters = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
EVPerr(EVP_F_EVP_PKEY_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
return ret;
}
int EVP_PKEY_up_ref(EVP_PKEY *pkey)
{
int i;
if (CRYPTO_UP_REF(&pkey->references, &i, pkey->lock) <= 0)
return 0;
REF_PRINT_COUNT("EVP_PKEY", pkey);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
/*
* Setup a public key ASN1 method and ENGINE from a NID or a string. If pkey
* is NULL just return 1 or 0 if the algorithm exists.
*/
static int pkey_set_type(EVP_PKEY *pkey, ENGINE *e, int type, const char *str,
int len)
{
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE **eptr = (e == NULL) ? &e : NULL;
if (pkey) {
if (pkey->pkey.ptr)
EVP_PKEY_free_it(pkey);
/*
* If key type matches and a method exists then this lookup has
* succeeded once so just indicate success.
*/
if ((type == pkey->save_type) && pkey->ameth)
return 1;
#ifndef OPENSSL_NO_ENGINE
/* If we have ENGINEs release them */
ENGINE_finish(pkey->engine);
pkey->engine = NULL;
ENGINE_finish(pkey->pmeth_engine);
pkey->pmeth_engine = NULL;
#endif
}
if (str)
ameth = EVP_PKEY_asn1_find_str(eptr, str, len);
else
ameth = EVP_PKEY_asn1_find(eptr, type);
#ifndef OPENSSL_NO_ENGINE
if (pkey == NULL && eptr != NULL)
ENGINE_finish(e);
#endif
if (ameth == NULL) {
EVPerr(EVP_F_PKEY_SET_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
if (pkey) {
pkey->ameth = ameth;
pkey->engine = e;
pkey->type = pkey->ameth->pkey_id;
pkey->save_type = type;
}
return 1;
}
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
const unsigned char *priv,
size_t len)
{
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL
|| !pkey_set_type(ret, e, type, NULL, -1)) {
/* EVPerr already called */
goto err;
}
if (ret->ameth->set_priv_key == NULL) {
EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
goto err;
}
if (!ret->ameth->set_priv_key(ret, priv, len)) {
EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PRIVATE_KEY, EVP_R_KEY_SETUP_FAILED);
goto err;
}
return ret;
err:
EVP_PKEY_free(ret);
return NULL;
}
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
const unsigned char *pub,
size_t len)
{
EVP_PKEY *ret = EVP_PKEY_new();
if (ret == NULL
|| !pkey_set_type(ret, e, type, NULL, -1)) {
/* EVPerr already called */
goto err;
}
if (ret->ameth->set_pub_key == NULL) {
EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
goto err;
}
if (!ret->ameth->set_pub_key(ret, pub, len)) {
EVPerr(EVP_F_EVP_PKEY_NEW_RAW_PUBLIC_KEY, EVP_R_KEY_SETUP_FAILED);
goto err;
}
return ret;
err:
EVP_PKEY_free(ret);
return NULL;
}
int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
size_t *len)
{
if (pkey->ameth->get_priv_key == NULL) {
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (!pkey->ameth->get_priv_key(pkey, priv, len)) {
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PRIVATE_KEY, EVP_R_GET_RAW_KEY_FAILED);
return 0;
}
return 1;
}
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
size_t *len)
{
if (pkey->ameth->get_pub_key == NULL) {
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return 0;
}
if (!pkey->ameth->get_pub_key(pkey, pub, len)) {
EVPerr(EVP_F_EVP_PKEY_GET_RAW_PUBLIC_KEY, EVP_R_GET_RAW_KEY_FAILED);
return 0;
}
return 1;
}
EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
size_t len, const EVP_CIPHER *cipher)
{
#ifndef OPENSSL_NO_CMAC
EVP_PKEY *ret = EVP_PKEY_new();
CMAC_CTX *cmctx = CMAC_CTX_new();
if (ret == NULL
|| cmctx == NULL
|| !pkey_set_type(ret, e, EVP_PKEY_CMAC, NULL, -1)) {
/* EVPerr already called */
goto err;
}
if (!CMAC_Init(cmctx, priv, len, cipher, e)) {
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY, EVP_R_KEY_SETUP_FAILED);
goto err;
}
ret->pkey.ptr = cmctx;
return ret;
err:
EVP_PKEY_free(ret);
CMAC_CTX_free(cmctx);
return NULL;
#else
EVPerr(EVP_F_EVP_PKEY_NEW_CMAC_KEY,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return NULL;
#endif
}
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type)
{
return pkey_set_type(pkey, NULL, type, NULL, -1);
}
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len)
{
return pkey_set_type(pkey, NULL, EVP_PKEY_NONE, str, len);
}
int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type)
{
if (pkey->type == type) {
return 1; /* it already is that type */
}
/*
* The application is requesting to alias this to a different pkey type,
* but not one that resolves to the base type.
*/
if (EVP_PKEY_type(type) != EVP_PKEY_base_id(pkey)) {
EVPerr(EVP_F_EVP_PKEY_SET_ALIAS_TYPE, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
pkey->type = type;
return 1;
}
#ifndef OPENSSL_NO_ENGINE
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e)
{
if (e != NULL) {
if (!ENGINE_init(e)) {
EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, ERR_R_ENGINE_LIB);
return 0;
}
if (ENGINE_get_pkey_meth(e, pkey->type) == NULL) {
ENGINE_finish(e);
EVPerr(EVP_F_EVP_PKEY_SET1_ENGINE, EVP_R_UNSUPPORTED_ALGORITHM);
return 0;
}
}
ENGINE_finish(pkey->pmeth_engine);
pkey->pmeth_engine = e;
return 1;
}
+
+ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey)
+{
+ return pkey->engine;
+}
#endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key)
{
if (pkey == NULL || !EVP_PKEY_set_type(pkey, type))
return 0;
pkey->pkey.ptr = key;
return (key != NULL);
}
void *EVP_PKEY_get0(const EVP_PKEY *pkey)
{
return pkey->pkey.ptr;
}
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len)
{
ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_HMAC) {
EVPerr(EVP_F_EVP_PKEY_GET0_HMAC, EVP_R_EXPECTING_AN_HMAC_KEY);
return NULL;
}
os = EVP_PKEY_get0(pkey);
*len = os->length;
return os->data;
}
#ifndef OPENSSL_NO_POLY1305
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len)
{
ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_POLY1305) {
EVPerr(EVP_F_EVP_PKEY_GET0_POLY1305, EVP_R_EXPECTING_A_POLY1305_KEY);
return NULL;
}
os = EVP_PKEY_get0(pkey);
*len = os->length;
return os->data;
}
#endif
#ifndef OPENSSL_NO_SIPHASH
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len)
{
ASN1_OCTET_STRING *os = NULL;
if (pkey->type != EVP_PKEY_SIPHASH) {
EVPerr(EVP_F_EVP_PKEY_GET0_SIPHASH, EVP_R_EXPECTING_A_SIPHASH_KEY);
return NULL;
}
os = EVP_PKEY_get0(pkey);
*len = os->length;
return os->data;
}
#endif
#ifndef OPENSSL_NO_RSA
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key)
{
int ret = EVP_PKEY_assign_RSA(pkey, key);
if (ret)
RSA_up_ref(key);
return ret;
}
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_RSA) {
EVPerr(EVP_F_EVP_PKEY_GET0_RSA, EVP_R_EXPECTING_AN_RSA_KEY);
return NULL;
}
return pkey->pkey.rsa;
}
RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey)
{
RSA *ret = EVP_PKEY_get0_RSA(pkey);
if (ret != NULL)
RSA_up_ref(ret);
return ret;
}
#endif
#ifndef OPENSSL_NO_DSA
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key)
{
int ret = EVP_PKEY_assign_DSA(pkey, key);
if (ret)
DSA_up_ref(key);
return ret;
}
DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_DSA) {
EVPerr(EVP_F_EVP_PKEY_GET0_DSA, EVP_R_EXPECTING_A_DSA_KEY);
return NULL;
}
return pkey->pkey.dsa;
}
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey)
{
DSA *ret = EVP_PKEY_get0_DSA(pkey);
if (ret != NULL)
DSA_up_ref(ret);
return ret;
}
#endif
#ifndef OPENSSL_NO_EC
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key)
{
int ret = EVP_PKEY_assign_EC_KEY(pkey, key);
if (ret)
EC_KEY_up_ref(key);
return ret;
}
EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_EC) {
EVPerr(EVP_F_EVP_PKEY_GET0_EC_KEY, EVP_R_EXPECTING_A_EC_KEY);
return NULL;
}
return pkey->pkey.ec;
}
EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey)
{
EC_KEY *ret = EVP_PKEY_get0_EC_KEY(pkey);
if (ret != NULL)
EC_KEY_up_ref(ret);
return ret;
}
#endif
#ifndef OPENSSL_NO_DH
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key)
{
int ret = EVP_PKEY_assign_DH(pkey, key);
if (ret)
DH_up_ref(key);
return ret;
}
DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey)
{
if (pkey->type != EVP_PKEY_DH && pkey->type != EVP_PKEY_DHX) {
EVPerr(EVP_F_EVP_PKEY_GET0_DH, EVP_R_EXPECTING_A_DH_KEY);
return NULL;
}
return pkey->pkey.dh;
}
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey)
{
DH *ret = EVP_PKEY_get0_DH(pkey);
if (ret != NULL)
DH_up_ref(ret);
return ret;
}
#endif
int EVP_PKEY_type(int type)
{
int ret;
const EVP_PKEY_ASN1_METHOD *ameth;
ENGINE *e;
ameth = EVP_PKEY_asn1_find(&e, type);
if (ameth)
ret = ameth->pkey_id;
else
ret = NID_undef;
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(e);
#endif
return ret;
}
int EVP_PKEY_id(const EVP_PKEY *pkey)
{
return pkey->type;
}
int EVP_PKEY_base_id(const EVP_PKEY *pkey)
{
return EVP_PKEY_type(pkey->type);
}
void EVP_PKEY_free(EVP_PKEY *x)
{
int i;
if (x == NULL)
return;
CRYPTO_DOWN_REF(&x->references, &i, x->lock);
REF_PRINT_COUNT("EVP_PKEY", x);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
EVP_PKEY_free_it(x);
CRYPTO_THREAD_lock_free(x->lock);
sk_X509_ATTRIBUTE_pop_free(x->attributes, X509_ATTRIBUTE_free);
OPENSSL_free(x);
}
static void EVP_PKEY_free_it(EVP_PKEY *x)
{
/* internal function; x is never NULL */
if (x->ameth && x->ameth->pkey_free) {
x->ameth->pkey_free(x);
x->pkey.ptr = NULL;
}
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(x->engine);
x->engine = NULL;
ENGINE_finish(x->pmeth_engine);
x->pmeth_engine = NULL;
#endif
}
static int unsup_alg(BIO *out, const EVP_PKEY *pkey, int indent,
const char *kstr)
{
BIO_indent(out, indent, 128);
BIO_printf(out, "%s algorithm \"%s\" unsupported\n",
kstr, OBJ_nid2ln(pkey->type));
return 1;
}
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
if (pkey->ameth && pkey->ameth->pub_print)
return pkey->ameth->pub_print(out, pkey, indent, pctx);
return unsup_alg(out, pkey, indent, "Public Key");
}
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
if (pkey->ameth && pkey->ameth->priv_print)
return pkey->ameth->priv_print(out, pkey, indent, pctx);
return unsup_alg(out, pkey, indent, "Private Key");
}
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx)
{
if (pkey->ameth && pkey->ameth->param_print)
return pkey->ameth->param_print(out, pkey, indent, pctx);
return unsup_alg(out, pkey, indent, "Parameters");
}
static int evp_pkey_asn1_ctrl(EVP_PKEY *pkey, int op, int arg1, void *arg2)
{
if (pkey->ameth == NULL || pkey->ameth->pkey_ctrl == NULL)
return -2;
return pkey->ameth->pkey_ctrl(pkey, op, arg1, arg2);
}
int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid)
{
return evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_DEFAULT_MD_NID, 0, pnid);
}
int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey,
const unsigned char *pt, size_t ptlen)
{
if (ptlen > INT_MAX)
return 0;
if (evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_SET1_TLS_ENCPT, ptlen,
(void *)pt) <= 0)
return 0;
return 1;
}
size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt)
{
int rv;
rv = evp_pkey_asn1_ctrl(pkey, ASN1_PKEY_CTRL_GET1_TLS_ENCPT, 0, ppt);
if (rv <= 0)
return 0;
return rv;
}
diff --git a/crypto/evp/p_open.c b/crypto/evp/p_open.c
index f2976f8a994a..1ce87454bdec 100644
--- a/crypto/evp/p_open.c
+++ b/crypto/evp/p_open.c
@@ -1,73 +1,73 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
#ifdef OPENSSL_NO_RSA
NON_EMPTY_TRANSLATION_UNIT
#else
# include <stdio.h>
# include <openssl/evp.h>
# include <openssl/objects.h>
# include <openssl/x509.h>
# include <openssl/rsa.h>
int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *ek, int ekl, const unsigned char *iv,
EVP_PKEY *priv)
{
unsigned char *key = NULL;
int i, size = 0, ret = 0;
if (type) {
EVP_CIPHER_CTX_reset(ctx);
if (!EVP_DecryptInit_ex(ctx, type, NULL, NULL, NULL))
return 0;
}
if (!priv)
return 1;
if (EVP_PKEY_id(priv) != EVP_PKEY_RSA) {
EVPerr(EVP_F_EVP_OPENINIT, EVP_R_PUBLIC_KEY_NOT_RSA);
goto err;
}
size = EVP_PKEY_size(priv);
- key = OPENSSL_malloc(size + 2);
+ key = OPENSSL_malloc(size);
if (key == NULL) {
/* ERROR */
EVPerr(EVP_F_EVP_OPENINIT, ERR_R_MALLOC_FAILURE);
goto err;
}
i = EVP_PKEY_decrypt_old(key, ek, ekl, priv);
if ((i <= 0) || !EVP_CIPHER_CTX_set_key_length(ctx, i)) {
/* ERROR */
goto err;
}
if (!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv))
goto err;
ret = 1;
err:
OPENSSL_clear_free(key, size);
return ret;
}
int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl)
{
int i;
i = EVP_DecryptFinal_ex(ctx, out, outl);
if (i)
i = EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, NULL);
return i;
}
#endif
diff --git a/crypto/hmac/hmac.c b/crypto/hmac/hmac.c
index e4031b44a576..0c0a7133fb5a 100644
--- a/crypto/hmac/hmac.c
+++ b/crypto/hmac/hmac.c
@@ -1,247 +1,254 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "internal/cryptlib.h"
#include <openssl/hmac.h>
#include <openssl/opensslconf.h>
#include "hmac_lcl.h"
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int len,
const EVP_MD *md, ENGINE *impl)
{
int rv = 0;
int i, j, reset = 0;
unsigned char pad[HMAC_MAX_MD_CBLOCK_SIZE];
/* If we are changing MD then we must have a key */
if (md != NULL && md != ctx->md && (key == NULL || len < 0))
return 0;
if (md != NULL) {
reset = 1;
ctx->md = md;
} else if (ctx->md) {
md = ctx->md;
} else {
return 0;
}
+ /*
+ * The HMAC construction is not allowed to be used with the
+ * extendable-output functions (XOF) shake128 and shake256.
+ */
+ if ((EVP_MD_meth_get_flags(md) & EVP_MD_FLAG_XOF) != 0)
+ return 0;
+
if (key != NULL) {
reset = 1;
j = EVP_MD_block_size(md);
if (!ossl_assert(j <= (int)sizeof(ctx->key)))
return 0;
if (j < len) {
if (!EVP_DigestInit_ex(ctx->md_ctx, md, impl)
|| !EVP_DigestUpdate(ctx->md_ctx, key, len)
|| !EVP_DigestFinal_ex(ctx->md_ctx, ctx->key,
&ctx->key_length))
return 0;
} else {
if (len < 0 || len > (int)sizeof(ctx->key))
return 0;
memcpy(ctx->key, key, len);
ctx->key_length = len;
}
if (ctx->key_length != HMAC_MAX_MD_CBLOCK_SIZE)
memset(&ctx->key[ctx->key_length], 0,
HMAC_MAX_MD_CBLOCK_SIZE - ctx->key_length);
}
if (reset) {
for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
pad[i] = 0x36 ^ ctx->key[i];
if (!EVP_DigestInit_ex(ctx->i_ctx, md, impl)
|| !EVP_DigestUpdate(ctx->i_ctx, pad, EVP_MD_block_size(md)))
goto err;
for (i = 0; i < HMAC_MAX_MD_CBLOCK_SIZE; i++)
pad[i] = 0x5c ^ ctx->key[i];
if (!EVP_DigestInit_ex(ctx->o_ctx, md, impl)
|| !EVP_DigestUpdate(ctx->o_ctx, pad, EVP_MD_block_size(md)))
goto err;
}
if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->i_ctx))
goto err;
rv = 1;
err:
if (reset)
OPENSSL_cleanse(pad, sizeof(pad));
return rv;
}
#if OPENSSL_API_COMPAT < 0x10100000L
int HMAC_Init(HMAC_CTX *ctx, const void *key, int len, const EVP_MD *md)
{
if (key && md)
HMAC_CTX_reset(ctx);
return HMAC_Init_ex(ctx, key, len, md, NULL);
}
#endif
int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, size_t len)
{
if (!ctx->md)
return 0;
return EVP_DigestUpdate(ctx->md_ctx, data, len);
}
int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len)
{
unsigned int i;
unsigned char buf[EVP_MAX_MD_SIZE];
if (!ctx->md)
goto err;
if (!EVP_DigestFinal_ex(ctx->md_ctx, buf, &i))
goto err;
if (!EVP_MD_CTX_copy_ex(ctx->md_ctx, ctx->o_ctx))
goto err;
if (!EVP_DigestUpdate(ctx->md_ctx, buf, i))
goto err;
if (!EVP_DigestFinal_ex(ctx->md_ctx, md, len))
goto err;
return 1;
err:
return 0;
}
size_t HMAC_size(const HMAC_CTX *ctx)
{
int size = EVP_MD_size((ctx)->md);
return (size < 0) ? 0 : size;
}
HMAC_CTX *HMAC_CTX_new(void)
{
HMAC_CTX *ctx = OPENSSL_zalloc(sizeof(HMAC_CTX));
if (ctx != NULL) {
if (!HMAC_CTX_reset(ctx)) {
HMAC_CTX_free(ctx);
return NULL;
}
}
return ctx;
}
static void hmac_ctx_cleanup(HMAC_CTX *ctx)
{
EVP_MD_CTX_reset(ctx->i_ctx);
EVP_MD_CTX_reset(ctx->o_ctx);
EVP_MD_CTX_reset(ctx->md_ctx);
ctx->md = NULL;
ctx->key_length = 0;
OPENSSL_cleanse(ctx->key, sizeof(ctx->key));
}
void HMAC_CTX_free(HMAC_CTX *ctx)
{
if (ctx != NULL) {
hmac_ctx_cleanup(ctx);
EVP_MD_CTX_free(ctx->i_ctx);
EVP_MD_CTX_free(ctx->o_ctx);
EVP_MD_CTX_free(ctx->md_ctx);
OPENSSL_free(ctx);
}
}
static int hmac_ctx_alloc_mds(HMAC_CTX *ctx)
{
if (ctx->i_ctx == NULL)
ctx->i_ctx = EVP_MD_CTX_new();
if (ctx->i_ctx == NULL)
return 0;
if (ctx->o_ctx == NULL)
ctx->o_ctx = EVP_MD_CTX_new();
if (ctx->o_ctx == NULL)
return 0;
if (ctx->md_ctx == NULL)
ctx->md_ctx = EVP_MD_CTX_new();
if (ctx->md_ctx == NULL)
return 0;
return 1;
}
int HMAC_CTX_reset(HMAC_CTX *ctx)
{
hmac_ctx_cleanup(ctx);
if (!hmac_ctx_alloc_mds(ctx)) {
hmac_ctx_cleanup(ctx);
return 0;
}
return 1;
}
int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx)
{
if (!hmac_ctx_alloc_mds(dctx))
goto err;
if (!EVP_MD_CTX_copy_ex(dctx->i_ctx, sctx->i_ctx))
goto err;
if (!EVP_MD_CTX_copy_ex(dctx->o_ctx, sctx->o_ctx))
goto err;
if (!EVP_MD_CTX_copy_ex(dctx->md_ctx, sctx->md_ctx))
goto err;
memcpy(dctx->key, sctx->key, HMAC_MAX_MD_CBLOCK_SIZE);
dctx->key_length = sctx->key_length;
dctx->md = sctx->md;
return 1;
err:
hmac_ctx_cleanup(dctx);
return 0;
}
unsigned char *HMAC(const EVP_MD *evp_md, const void *key, int key_len,
const unsigned char *d, size_t n, unsigned char *md,
unsigned int *md_len)
{
HMAC_CTX *c = NULL;
static unsigned char m[EVP_MAX_MD_SIZE];
static const unsigned char dummy_key[1] = {'\0'};
if (md == NULL)
md = m;
if ((c = HMAC_CTX_new()) == NULL)
goto err;
/* For HMAC_Init_ex, NULL key signals reuse. */
if (key == NULL && key_len == 0) {
key = dummy_key;
}
if (!HMAC_Init_ex(c, key, key_len, evp_md, NULL))
goto err;
if (!HMAC_Update(c, d, n))
goto err;
if (!HMAC_Final(c, md, md_len))
goto err;
HMAC_CTX_free(c);
return md;
err:
HMAC_CTX_free(c);
return NULL;
}
void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags)
{
EVP_MD_CTX_set_flags(ctx->i_ctx, flags);
EVP_MD_CTX_set_flags(ctx->o_ctx, flags);
EVP_MD_CTX_set_flags(ctx->md_ctx, flags);
}
const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx)
{
return ctx->md;
}
diff --git a/crypto/include/internal/dso_conf.h.in b/crypto/include/internal/dso_conf.h.in
index d6e9d1b1baae..2a76818b50d9 100644
--- a/crypto/include/internal/dso_conf.h.in
+++ b/crypto/include/internal/dso_conf.h.in
@@ -1,30 +1,31 @@
{- join("\n",map { "/* $_ */" } @autowarntext) -}
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_DSO_CONF_H
# define HEADER_DSO_CONF_H
-{- output_off() if $disabled{dso} -}
{- # The DSO code currently always implements all functions so that no
# applications will have to worry about that from a compilation point
# of view. However, the "method"s may return zero unless that platform
# has support compiled in for them. Currently each method is enabled
# by a define "DSO_<name>" ... we translate the "dso_scheme" config
# string entry into using the following logic;
my $scheme = uc $target{dso_scheme};
+ if (!$scheme) {
+ $scheme = "NONE";
+ }
my @macros = ( "DSO_$scheme" );
if ($scheme eq 'DLFCN') {
@macros = ( "DSO_DLFCN", "HAVE_DLFCN_H" );
} elsif ($scheme eq "DLFCN_NO_H") {
@macros = ( "DSO_DLFCN" );
}
join("\n", map { "# define $_" } @macros); -}
# define DSO_EXTENSION "{- $target{dso_extension} -}"
-{- output_on() if $disabled{dso} -}
#endif
diff --git a/crypto/init.c b/crypto/init.c
index b9a7334a7ed7..62626a707ea8 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -1,854 +1,852 @@
/*
* Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h"
#include "internal/cryptlib_int.h"
#include <openssl/err.h>
#include "internal/rand_int.h"
#include "internal/bio.h"
#include <openssl/evp.h>
#include "internal/evp_int.h"
#include "internal/conf.h"
#include "internal/async.h"
#include "internal/engine.h"
#include "internal/comp.h"
#include "internal/err.h"
#include "internal/err_int.h"
#include "internal/objects.h"
#include <stdlib.h>
#include <assert.h>
#include "internal/thread_once.h"
#include "internal/dso_conf.h"
#include "internal/dso.h"
#include "internal/store.h"
static int stopped = 0;
/*
* Since per-thread-specific-data destructors are not universally
* available, i.e. not on Windows, only below CRYPTO_THREAD_LOCAL key
* is assumed to have destructor associated. And then an effort is made
* to call this single destructor on non-pthread platform[s].
*
* Initial value is "impossible". It is used as guard value to shortcut
* destructor for threads terminating before libcrypto is initialized or
* after it's de-initialized. Access to the key doesn't have to be
* serialized for the said threads, because they didn't use libcrypto
* and it doesn't matter if they pick "impossible" or derefernce real
* key value and pull NULL past initialization in the first thread that
* intends to use libcrypto.
*/
static union {
long sane;
CRYPTO_THREAD_LOCAL value;
} destructor_key = { -1 };
static void ossl_init_thread_stop(struct thread_local_inits_st *locals);
static void ossl_init_thread_destructor(void *local)
{
ossl_init_thread_stop((struct thread_local_inits_st *)local);
}
static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc)
{
struct thread_local_inits_st *local =
CRYPTO_THREAD_get_local(&destructor_key.value);
if (alloc) {
if (local == NULL
&& (local = OPENSSL_zalloc(sizeof(*local))) != NULL
&& !CRYPTO_THREAD_set_local(&destructor_key.value, local)) {
OPENSSL_free(local);
return NULL;
}
} else {
CRYPTO_THREAD_set_local(&destructor_key.value, NULL);
}
return local;
}
typedef struct ossl_init_stop_st OPENSSL_INIT_STOP;
struct ossl_init_stop_st {
void (*handler)(void);
OPENSSL_INIT_STOP *next;
};
static OPENSSL_INIT_STOP *stop_handlers = NULL;
static CRYPTO_RWLOCK *init_lock = NULL;
static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT;
static int base_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_base)
{
CRYPTO_THREAD_LOCAL key;
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_base: Setting up stop handlers\n");
#endif
#ifndef OPENSSL_NO_CRYPTO_MDEBUG
ossl_malloc_setup_failures();
#endif
if (!CRYPTO_THREAD_init_local(&key, ossl_init_thread_destructor))
return 0;
if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL)
goto err;
OPENSSL_cpuid_setup();
destructor_key.value = key;
base_inited = 1;
return 1;
err:
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_base not ok!\n");
#endif
CRYPTO_THREAD_lock_free(init_lock);
init_lock = NULL;
CRYPTO_THREAD_cleanup_local(&key);
return 0;
}
static CRYPTO_ONCE register_atexit = CRYPTO_ONCE_STATIC_INIT;
#if !defined(OPENSSL_SYS_UEFI) && defined(_WIN32)
static int win32atexit(void)
{
OPENSSL_cleanup();
return 0;
}
#endif
DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit)
{
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_register_atexit()\n");
#endif
#ifndef OPENSSL_SYS_UEFI
# ifdef _WIN32
/* We use _onexit() in preference because it gets called on DLL unload */
if (_onexit(win32atexit) == NULL)
return 0;
# else
if (atexit(OPENSSL_cleanup) != 0)
return 0;
# endif
#endif
return 1;
}
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_register_atexit,
ossl_init_register_atexit)
{
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_no_register_atexit ok!\n");
#endif
/* Do nothing in this case */
return 1;
}
static CRYPTO_ONCE load_crypto_nodelete = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_nodelete)
{
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_nodelete()\n");
#endif
-#if !defined(OPENSSL_NO_DSO) \
- && !defined(OPENSSL_USE_NODELETE) \
+#if !defined(OPENSSL_USE_NODELETE) \
&& !defined(OPENSSL_NO_PINSHARED)
-# ifdef DSO_WIN32
+# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
{
HMODULE handle = NULL;
BOOL ret;
/* We don't use the DSO route for WIN32 because there is a better way */
ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
| GET_MODULE_HANDLE_EX_FLAG_PIN,
(void *)&base_inited, &handle);
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n",
(ret == TRUE ? "No!" : "Yes."));
# endif
return (ret == TRUE) ? 1 : 0;
}
-# else
+# elif !defined(DSO_NONE)
/*
* Deliberately leak a reference to ourselves. This will force the library
* to remain loaded until the atexit() handler is run at process exit.
*/
{
DSO *dso;
void *err;
if (!err_shelve_state(&err))
return 0;
dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE);
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: obtained DSO reference? %s\n",
(dso == NULL ? "No!" : "Yes."));
/*
* In case of No!, it is uncertain our exit()-handlers can still be
* called. After dlclose() the whole library might have been unloaded
* already.
*/
# endif
DSO_free(dso);
err_unshelve_state(err);
}
# endif
#endif
return 1;
}
static CRYPTO_ONCE load_crypto_strings = CRYPTO_ONCE_STATIC_INIT;
static int load_crypto_strings_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings)
{
int ret = 1;
/*
* OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time
* pulling in all the error strings during static linking
*/
#if !defined(OPENSSL_NO_ERR) && !defined(OPENSSL_NO_AUTOERRINIT)
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_strings: "
"err_load_crypto_strings_int()\n");
# endif
ret = err_load_crypto_strings_int();
load_crypto_strings_inited = 1;
#endif
return ret;
}
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_load_crypto_strings,
ossl_init_load_crypto_strings)
{
/* Do nothing in this case */
return 1;
}
static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers)
{
/*
* OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
* pulling in all the ciphers during static linking
*/
#ifndef OPENSSL_NO_AUTOALGINIT
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_ciphers: "
"openssl_add_all_ciphers_int()\n");
# endif
openssl_add_all_ciphers_int();
#endif
return 1;
}
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_ciphers,
ossl_init_add_all_ciphers)
{
/* Do nothing */
return 1;
}
static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests)
{
/*
* OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time
* pulling in all the ciphers during static linking
*/
#ifndef OPENSSL_NO_AUTOALGINIT
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_add_all_digests: "
"openssl_add_all_digests()\n");
# endif
openssl_add_all_digests_int();
#endif
return 1;
}
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_add_all_digests,
ossl_init_add_all_digests)
{
/* Do nothing */
return 1;
}
static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT;
static int config_inited = 0;
static const OPENSSL_INIT_SETTINGS *conf_settings = NULL;
DEFINE_RUN_ONCE_STATIC(ossl_init_config)
{
int ret = openssl_config_int(conf_settings);
config_inited = 1;
return ret;
}
DEFINE_RUN_ONCE_STATIC_ALT(ossl_init_no_config, ossl_init_config)
{
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr,
"OPENSSL_INIT: ossl_init_config: openssl_no_config_int()\n");
#endif
openssl_no_config_int();
config_inited = 1;
return 1;
}
static CRYPTO_ONCE async = CRYPTO_ONCE_STATIC_INIT;
static int async_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_async)
{
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_async: async_init()\n");
#endif
if (!async_init())
return 0;
async_inited = 1;
return 1;
}
#ifndef OPENSSL_NO_ENGINE
static CRYPTO_ONCE engine_openssl = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_openssl: "
"engine_load_openssl_int()\n");
# endif
engine_load_openssl_int();
return 1;
}
# ifndef OPENSSL_NO_DEVCRYPTOENG
static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: "
"engine_load_devcrypto_int()\n");
# endif
engine_load_devcrypto_int();
return 1;
}
# endif
# ifndef OPENSSL_NO_RDRAND
static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_rdrand: "
"engine_load_rdrand_int()\n");
# endif
engine_load_rdrand_int();
return 1;
}
# endif
static CRYPTO_ONCE engine_dynamic = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dynamic: "
"engine_load_dynamic_int()\n");
# endif
engine_load_dynamic_int();
return 1;
}
# ifndef OPENSSL_NO_STATIC_ENGINE
# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_padlock: "
"engine_load_padlock_int()\n");
# endif
engine_load_padlock_int();
return 1;
}
# endif
# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
static CRYPTO_ONCE engine_capi = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_capi: "
"engine_load_capi_int()\n");
# endif
engine_load_capi_int();
return 1;
}
# endif
# if !defined(OPENSSL_NO_AFALGENG)
static CRYPTO_ONCE engine_afalg = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg)
{
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_afalg: "
"engine_load_afalg_int()\n");
# endif
engine_load_afalg_int();
return 1;
}
# endif
# endif
#endif
#ifndef OPENSSL_NO_COMP
static CRYPTO_ONCE zlib = CRYPTO_ONCE_STATIC_INIT;
static int zlib_inited = 0;
DEFINE_RUN_ONCE_STATIC(ossl_init_zlib)
{
/* Do nothing - we need to know about this for the later cleanup */
zlib_inited = 1;
return 1;
}
#endif
static void ossl_init_thread_stop(struct thread_local_inits_st *locals)
{
/* Can't do much about this */
if (locals == NULL)
return;
if (locals->async) {
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
"async_delete_thread_state()\n");
#endif
async_delete_thread_state();
}
if (locals->err_state) {
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
"err_delete_thread_state()\n");
#endif
err_delete_thread_state();
}
if (locals->rand) {
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_stop: "
"drbg_delete_thread_state()\n");
#endif
drbg_delete_thread_state();
}
OPENSSL_free(locals);
}
void OPENSSL_thread_stop(void)
{
if (destructor_key.sane != -1)
ossl_init_thread_stop(ossl_init_get_thread_local(0));
}
int ossl_init_thread_start(uint64_t opts)
{
struct thread_local_inits_st *locals;
if (!OPENSSL_init_crypto(0, NULL))
return 0;
locals = ossl_init_get_thread_local(1);
if (locals == NULL)
return 0;
if (opts & OPENSSL_INIT_THREAD_ASYNC) {
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
"marking thread for async\n");
#endif
locals->async = 1;
}
if (opts & OPENSSL_INIT_THREAD_ERR_STATE) {
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
"marking thread for err_state\n");
#endif
locals->err_state = 1;
}
if (opts & OPENSSL_INIT_THREAD_RAND) {
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: ossl_init_thread_start: "
"marking thread for rand\n");
#endif
locals->rand = 1;
}
return 1;
}
void OPENSSL_cleanup(void)
{
OPENSSL_INIT_STOP *currhandler, *lasthandler;
CRYPTO_THREAD_LOCAL key;
/* If we've not been inited then no need to deinit */
if (!base_inited)
return;
/* Might be explicitly called and also by atexit */
if (stopped)
return;
stopped = 1;
/*
* Thread stop may not get automatically called by the thread library for
* the very last thread in some situations, so call it directly.
*/
ossl_init_thread_stop(ossl_init_get_thread_local(0));
currhandler = stop_handlers;
while (currhandler != NULL) {
currhandler->handler();
lasthandler = currhandler;
currhandler = currhandler->next;
OPENSSL_free(lasthandler);
}
stop_handlers = NULL;
CRYPTO_THREAD_lock_free(init_lock);
init_lock = NULL;
/*
* We assume we are single-threaded for this function, i.e. no race
* conditions for the various "*_inited" vars below.
*/
#ifndef OPENSSL_NO_COMP
if (zlib_inited) {
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"comp_zlib_cleanup_int()\n");
#endif
comp_zlib_cleanup_int();
}
#endif
if (async_inited) {
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"async_deinit()\n");
# endif
async_deinit();
}
if (load_crypto_strings_inited) {
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"err_free_strings_int()\n");
#endif
err_free_strings_int();
}
key = destructor_key.value;
destructor_key.sane = -1;
CRYPTO_THREAD_cleanup_local(&key);
#ifdef OPENSSL_INIT_DEBUG
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"rand_cleanup_int()\n");
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"conf_modules_free_int()\n");
#ifndef OPENSSL_NO_ENGINE
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"engine_cleanup_int()\n");
#endif
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"crypto_cleanup_all_ex_data_int()\n");
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"bio_sock_cleanup_int()\n");
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"bio_cleanup()\n");
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"evp_cleanup_int()\n");
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"obj_cleanup_int()\n");
fprintf(stderr, "OPENSSL_INIT: OPENSSL_cleanup: "
"err_cleanup()\n");
#endif
/*
* Note that cleanup order is important:
* - rand_cleanup_int could call an ENGINE's RAND cleanup function so
* must be called before engine_cleanup_int()
* - ENGINEs use CRYPTO_EX_DATA and therefore, must be cleaned up
* before the ex data handlers are wiped in CRYPTO_cleanup_all_ex_data().
* - conf_modules_free_int() can end up in ENGINE code so must be called
* before engine_cleanup_int()
* - ENGINEs and additional EVP algorithms might use added OIDs names so
* obj_cleanup_int() must be called last
*/
rand_cleanup_int();
rand_drbg_cleanup_int();
conf_modules_free_int();
#ifndef OPENSSL_NO_ENGINE
engine_cleanup_int();
#endif
ossl_store_cleanup_int();
crypto_cleanup_all_ex_data_int();
bio_cleanup();
evp_cleanup_int();
obj_cleanup_int();
err_cleanup();
CRYPTO_secure_malloc_done();
base_inited = 0;
}
/*
* If this function is called with a non NULL settings value then it must be
* called prior to any threads making calls to any OpenSSL functions,
* i.e. passing a non-null settings value is assumed to be single-threaded.
*/
int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings)
{
if (stopped) {
if (!(opts & OPENSSL_INIT_BASE_ONLY))
CRYPTOerr(CRYPTO_F_OPENSSL_INIT_CRYPTO, ERR_R_INIT_FAIL);
return 0;
}
/*
* When the caller specifies OPENSSL_INIT_BASE_ONLY, that should be the
* *only* option specified. With that option we return immediately after
* doing the requested limited initialization. Note that
* err_shelve_state() called by us via ossl_init_load_crypto_nodelete()
* re-enters OPENSSL_init_crypto() with OPENSSL_INIT_BASE_ONLY, but with
* base already initialized this is a harmless NOOP.
*
* If we remain the only caller of err_shelve_state() the recursion should
* perhaps be removed, but if in doubt, it can be left in place.
*/
if (!RUN_ONCE(&base, ossl_init_base))
return 0;
if (opts & OPENSSL_INIT_BASE_ONLY)
return 1;
/*
* Now we don't always set up exit handlers, the INIT_BASE_ONLY calls
* should not have the side-effect of setting up exit handlers, and
* therefore, this code block is below the INIT_BASE_ONLY-conditioned early
* return above.
*/
if ((opts & OPENSSL_INIT_NO_ATEXIT) != 0) {
if (!RUN_ONCE_ALT(&register_atexit, ossl_init_no_register_atexit,
ossl_init_register_atexit))
return 0;
} else if (!RUN_ONCE(&register_atexit, ossl_init_register_atexit)) {
return 0;
}
if (!RUN_ONCE(&load_crypto_nodelete, ossl_init_load_crypto_nodelete))
return 0;
if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS)
&& !RUN_ONCE_ALT(&load_crypto_strings,
ossl_init_no_load_crypto_strings,
ossl_init_load_crypto_strings))
return 0;
if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
&& !RUN_ONCE(&load_crypto_strings, ossl_init_load_crypto_strings))
return 0;
if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS)
&& !RUN_ONCE_ALT(&add_all_ciphers, ossl_init_no_add_all_ciphers,
ossl_init_add_all_ciphers))
return 0;
if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS)
&& !RUN_ONCE(&add_all_ciphers, ossl_init_add_all_ciphers))
return 0;
if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS)
&& !RUN_ONCE_ALT(&add_all_digests, ossl_init_no_add_all_digests,
ossl_init_add_all_digests))
return 0;
if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS)
&& !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests))
return 0;
if ((opts & OPENSSL_INIT_ATFORK)
&& !openssl_init_fork_handlers())
return 0;
if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG)
&& !RUN_ONCE_ALT(&config, ossl_init_no_config, ossl_init_config))
return 0;
if (opts & OPENSSL_INIT_LOAD_CONFIG) {
int ret;
CRYPTO_THREAD_write_lock(init_lock);
conf_settings = settings;
ret = RUN_ONCE(&config, ossl_init_config);
conf_settings = NULL;
CRYPTO_THREAD_unlock(init_lock);
- if (!ret)
+ if (ret <= 0)
return 0;
}
if ((opts & OPENSSL_INIT_ASYNC)
&& !RUN_ONCE(&async, ossl_init_async))
return 0;
#ifndef OPENSSL_NO_ENGINE
if ((opts & OPENSSL_INIT_ENGINE_OPENSSL)
&& !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl))
return 0;
# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG)
if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV)
&& !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto))
return 0;
# endif
# ifndef OPENSSL_NO_RDRAND
if ((opts & OPENSSL_INIT_ENGINE_RDRAND)
&& !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand))
return 0;
# endif
if ((opts & OPENSSL_INIT_ENGINE_DYNAMIC)
&& !RUN_ONCE(&engine_dynamic, ossl_init_engine_dynamic))
return 0;
# ifndef OPENSSL_NO_STATIC_ENGINE
# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK)
if ((opts & OPENSSL_INIT_ENGINE_PADLOCK)
&& !RUN_ONCE(&engine_padlock, ossl_init_engine_padlock))
return 0;
# endif
# if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG)
if ((opts & OPENSSL_INIT_ENGINE_CAPI)
&& !RUN_ONCE(&engine_capi, ossl_init_engine_capi))
return 0;
# endif
# if !defined(OPENSSL_NO_AFALGENG)
if ((opts & OPENSSL_INIT_ENGINE_AFALG)
&& !RUN_ONCE(&engine_afalg, ossl_init_engine_afalg))
return 0;
# endif
# endif
if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN
| OPENSSL_INIT_ENGINE_OPENSSL
| OPENSSL_INIT_ENGINE_AFALG)) {
ENGINE_register_all_complete();
}
#endif
#ifndef OPENSSL_NO_COMP
if ((opts & OPENSSL_INIT_ZLIB)
&& !RUN_ONCE(&zlib, ossl_init_zlib))
return 0;
#endif
return 1;
}
int OPENSSL_atexit(void (*handler)(void))
{
OPENSSL_INIT_STOP *newhand;
-#if !defined(OPENSSL_NO_DSO) \
- && !defined(OPENSSL_USE_NODELETE)\
+#if !defined(OPENSSL_USE_NODELETE)\
&& !defined(OPENSSL_NO_PINSHARED)
{
union {
void *sym;
void (*func)(void);
} handlersym;
handlersym.func = handler;
-# ifdef DSO_WIN32
+# if defined(DSO_WIN32) && !defined(_WIN32_WCE)
{
HMODULE handle = NULL;
BOOL ret;
/*
* We don't use the DSO route for WIN32 because there is a better
* way
*/
ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
| GET_MODULE_HANDLE_EX_FLAG_PIN,
handlersym.sym, &handle);
if (!ret)
return 0;
}
-# else
+# elif !defined(DSO_NONE)
/*
* Deliberately leak a reference to the handler. This will force the
* library/code containing the handler to remain loaded until we run the
* atexit handler. If -znodelete has been used then this is
* unnecessary.
*/
{
DSO *dso = NULL;
ERR_set_mark();
dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE);
# ifdef OPENSSL_INIT_DEBUG
fprintf(stderr,
"OPENSSL_INIT: OPENSSL_atexit: obtained DSO reference? %s\n",
(dso == NULL ? "No!" : "Yes."));
/* See same code above in ossl_init_base() for an explanation. */
# endif
DSO_free(dso);
ERR_pop_to_mark();
}
# endif
}
#endif
if ((newhand = OPENSSL_malloc(sizeof(*newhand))) == NULL) {
CRYPTOerr(CRYPTO_F_OPENSSL_ATEXIT, ERR_R_MALLOC_FAILURE);
return 0;
}
newhand->handler = handler;
newhand->next = stop_handlers;
stop_handlers = newhand;
return 1;
}
#ifdef OPENSSL_SYS_UNIX
/*
* The following three functions are for OpenSSL developers. This is
* where we set/reset state across fork (called via pthread_atfork when
* it exists, or manually by the application when it doesn't).
*
* WARNING! If you put code in either OPENSSL_fork_parent or
* OPENSSL_fork_child, you MUST MAKE SURE that they are async-signal-
* safe. See this link, for example:
* http://man7.org/linux/man-pages/man7/signal-safety.7.html
*/
void OPENSSL_fork_prepare(void)
{
}
void OPENSSL_fork_parent(void)
{
}
void OPENSSL_fork_child(void)
{
rand_fork();
}
#endif
diff --git a/crypto/mips_arch.h b/crypto/mips_arch.h
index 75043e79d337..e18ac07210c5 100644
--- a/crypto/mips_arch.h
+++ b/crypto/mips_arch.h
@@ -1,40 +1,40 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef __MIPS_ARCH_H__
# define __MIPS_ARCH_H__
# if (defined(__mips_smartmips) || defined(_MIPS_ARCH_MIPS32R3) || \
- defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6))
+ defined(_MIPS_ARCH_MIPS32R5) || defined(_MIPS_ARCH_MIPS32R6)) \
&& !defined(_MIPS_ARCH_MIPS32R2)
# define _MIPS_ARCH_MIPS32R2
# endif
# if (defined(_MIPS_ARCH_MIPS64R3) || defined(_MIPS_ARCH_MIPS64R5) || \
defined(_MIPS_ARCH_MIPS64R6)) \
&& !defined(_MIPS_ARCH_MIPS64R2)
# define _MIPS_ARCH_MIPS64R2
# endif
# if defined(_MIPS_ARCH_MIPS64R6)
# define dmultu(rs,rt)
# define mflo(rd,rs,rt) dmulu rd,rs,rt
# define mfhi(rd,rs,rt) dmuhu rd,rs,rt
# elif defined(_MIPS_ARCH_MIPS32R6)
# define multu(rs,rt)
# define mflo(rd,rs,rt) mulu rd,rs,rt
# define mfhi(rd,rs,rt) muhu rd,rs,rt
# else
# define dmultu(rs,rt) dmultu rs,rt
# define multu(rs,rt) multu rs,rt
# define mflo(rd,rs,rt) mflo rd
# define mfhi(rd,rs,rt) mfhi rd
# endif
#endif
diff --git a/crypto/modes/asm/ghash-x86_64.pl b/crypto/modes/asm/ghash-x86_64.pl
index 30158aa076da..6b2a51ecd77e 100755
--- a/crypto/modes/asm/ghash-x86_64.pl
+++ b/crypto/modes/asm/ghash-x86_64.pl
@@ -1,1816 +1,1818 @@
#! /usr/bin/env perl
# Copyright 2010-2019 The OpenSSL Project Authors. All Rights Reserved.
#
# Licensed under the OpenSSL license (the "License"). You may not use
# this file except in compliance with the License. You can obtain a copy
# in the file LICENSE in the source distribution or at
# https://www.openssl.org/source/license.html
#
# ====================================================================
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
# project. The module is, however, dual licensed under OpenSSL and
# CRYPTOGAMS licenses depending on where you obtain it. For further
# details see http://www.openssl.org/~appro/cryptogams/.
# ====================================================================
#
# March, June 2010
#
# The module implements "4-bit" GCM GHASH function and underlying
# single multiplication operation in GF(2^128). "4-bit" means that
# it uses 256 bytes per-key table [+128 bytes shared table]. GHASH
# function features so called "528B" variant utilizing additional
# 256+16 bytes of per-key storage [+512 bytes shared table].
# Performance results are for this streamed GHASH subroutine and are
# expressed in cycles per processed byte, less is better:
#
# gcc 3.4.x(*) assembler
#
# P4 28.6 14.0 +100%
# Opteron 19.3 7.7 +150%
# Core2 17.8 8.1(**) +120%
# Atom 31.6 16.8 +88%
# VIA Nano 21.8 10.1 +115%
#
# (*) comparison is not completely fair, because C results are
# for vanilla "256B" implementation, while assembler results
# are for "528B";-)
# (**) it's mystery [to me] why Core2 result is not same as for
# Opteron;
# May 2010
#
# Add PCLMULQDQ version performing at 2.02 cycles per processed byte.
# See ghash-x86.pl for background information and details about coding
# techniques.
#
# Special thanks to David Woodhouse for providing access to a
# Westmere-based system on behalf of Intel Open Source Technology Centre.
# December 2012
#
# Overhaul: aggregate Karatsuba post-processing, improve ILP in
# reduction_alg9, increase reduction aggregate factor to 4x. As for
# the latter. ghash-x86.pl discusses that it makes lesser sense to
# increase aggregate factor. Then why increase here? Critical path
# consists of 3 independent pclmulqdq instructions, Karatsuba post-
# processing and reduction. "On top" of this we lay down aggregated
# multiplication operations, triplets of independent pclmulqdq's. As
# issue rate for pclmulqdq is limited, it makes lesser sense to
# aggregate more multiplications than it takes to perform remaining
# non-multiplication operations. 2x is near-optimal coefficient for
# contemporary Intel CPUs (therefore modest improvement coefficient),
# but not for Bulldozer. Latter is because logical SIMD operations
# are twice as slow in comparison to Intel, so that critical path is
# longer. A CPU with higher pclmulqdq issue rate would also benefit
# from higher aggregate factor...
#
# Westmere 1.78(+13%)
# Sandy Bridge 1.80(+8%)
# Ivy Bridge 1.80(+7%)
# Haswell 0.55(+93%) (if system doesn't support AVX)
# Broadwell 0.45(+110%)(if system doesn't support AVX)
# Skylake 0.44(+110%)(if system doesn't support AVX)
# Bulldozer 1.49(+27%)
# Silvermont 2.88(+13%)
# Knights L 2.12(-) (if system doesn't support AVX)
# Goldmont 1.08(+24%)
# March 2013
#
# ... 8x aggregate factor AVX code path is using reduction algorithm
# suggested by Shay Gueron[1]. Even though contemporary AVX-capable
# CPUs such as Sandy and Ivy Bridge can execute it, the code performs
# sub-optimally in comparison to above mentioned version. But thanks
# to Ilya Albrekht and Max Locktyukhin of Intel Corp. we knew that
# it performs in 0.41 cycles per byte on Haswell processor, in
# 0.29 on Broadwell, and in 0.36 on Skylake.
#
# Knights Landing achieves 1.09 cpb.
#
# [1] http://rt.openssl.org/Ticket/Display.html?id=2900&user=guest&pass=guest
$flavour = shift;
$output = shift;
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; }
$win64=0; $win64=1 if ($flavour =~ /[nm]asm|mingw64/ || $output =~ /\.asm$/);
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
( $xlate="${dir}x86_64-xlate.pl" and -f $xlate ) or
( $xlate="${dir}../../perlasm/x86_64-xlate.pl" and -f $xlate) or
die "can't locate x86_64-xlate.pl";
if (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
=~ /GNU assembler version ([2-9]\.[0-9]+)/) {
$avx = ($1>=2.20) + ($1>=2.22);
}
if (!$avx && $win64 && ($flavour =~ /nasm/ || $ENV{ASM} =~ /nasm/) &&
`nasm -v 2>&1` =~ /NASM version ([2-9]\.[0-9]+)/) {
$avx = ($1>=2.09) + ($1>=2.10);
}
if (!$avx && $win64 && ($flavour =~ /masm/ || $ENV{ASM} =~ /ml64/) &&
`ml64 2>&1` =~ /Version ([0-9]+)\./) {
$avx = ($1>=10) + ($1>=11);
}
if (!$avx && `$ENV{CC} -v 2>&1` =~ /((?:^clang|LLVM) version|.*based on LLVM) ([3-9]\.[0-9]+)/) {
$avx = ($2>=3.0) + ($2>3.0);
}
open OUT,"| \"$^X\" \"$xlate\" $flavour \"$output\"";
*STDOUT=*OUT;
$do4xaggr=1;
# common register layout
$nlo="%rax";
$nhi="%rbx";
$Zlo="%r8";
$Zhi="%r9";
$tmp="%r10";
$rem_4bit = "%r11";
$Xi="%rdi";
$Htbl="%rsi";
# per-function register layout
$cnt="%rcx";
$rem="%rdx";
sub LB() { my $r=shift; $r =~ s/%[er]([a-d])x/%\1l/ or
$r =~ s/%[er]([sd]i)/%\1l/ or
$r =~ s/%[er](bp)/%\1l/ or
$r =~ s/%(r[0-9]+)[d]?/%\1b/; $r; }
sub AUTOLOAD() # thunk [simplified] 32-bit style perlasm
{ my $opcode = $AUTOLOAD; $opcode =~ s/.*:://;
my $arg = pop;
$arg = "\$$arg" if ($arg*1 eq $arg);
$code .= "\t$opcode\t".join(',',$arg,reverse @_)."\n";
}
{ my $N;
sub loop() {
my $inp = shift;
$N++;
$code.=<<___;
xor $nlo,$nlo
xor $nhi,$nhi
mov `&LB("$Zlo")`,`&LB("$nlo")`
mov `&LB("$Zlo")`,`&LB("$nhi")`
shl \$4,`&LB("$nlo")`
mov \$14,$cnt
mov 8($Htbl,$nlo),$Zlo
mov ($Htbl,$nlo),$Zhi
and \$0xf0,`&LB("$nhi")`
mov $Zlo,$rem
jmp .Loop$N
.align 16
.Loop$N:
shr \$4,$Zlo
and \$0xf,$rem
mov $Zhi,$tmp
mov ($inp,$cnt),`&LB("$nlo")`
shr \$4,$Zhi
xor 8($Htbl,$nhi),$Zlo
shl \$60,$tmp
xor ($Htbl,$nhi),$Zhi
mov `&LB("$nlo")`,`&LB("$nhi")`
xor ($rem_4bit,$rem,8),$Zhi
mov $Zlo,$rem
shl \$4,`&LB("$nlo")`
xor $tmp,$Zlo
dec $cnt
js .Lbreak$N
shr \$4,$Zlo
and \$0xf,$rem
mov $Zhi,$tmp
shr \$4,$Zhi
xor 8($Htbl,$nlo),$Zlo
shl \$60,$tmp
xor ($Htbl,$nlo),$Zhi
and \$0xf0,`&LB("$nhi")`
xor ($rem_4bit,$rem,8),$Zhi
mov $Zlo,$rem
xor $tmp,$Zlo
jmp .Loop$N
.align 16
.Lbreak$N:
shr \$4,$Zlo
and \$0xf,$rem
mov $Zhi,$tmp
shr \$4,$Zhi
xor 8($Htbl,$nlo),$Zlo
shl \$60,$tmp
xor ($Htbl,$nlo),$Zhi
and \$0xf0,`&LB("$nhi")`
xor ($rem_4bit,$rem,8),$Zhi
mov $Zlo,$rem
xor $tmp,$Zlo
shr \$4,$Zlo
and \$0xf,$rem
mov $Zhi,$tmp
shr \$4,$Zhi
xor 8($Htbl,$nhi),$Zlo
shl \$60,$tmp
xor ($Htbl,$nhi),$Zhi
xor $tmp,$Zlo
xor ($rem_4bit,$rem,8),$Zhi
bswap $Zlo
bswap $Zhi
___
}}
$code=<<___;
.text
.extern OPENSSL_ia32cap_P
.globl gcm_gmult_4bit
.type gcm_gmult_4bit,\@function,2
.align 16
gcm_gmult_4bit:
.cfi_startproc
push %rbx
.cfi_push %rbx
push %rbp # %rbp and others are pushed exclusively in
.cfi_push %rbp
push %r12 # order to reuse Win64 exception handler...
.cfi_push %r12
push %r13
.cfi_push %r13
push %r14
.cfi_push %r14
push %r15
.cfi_push %r15
sub \$280,%rsp
.cfi_adjust_cfa_offset 280
.Lgmult_prologue:
movzb 15($Xi),$Zlo
lea .Lrem_4bit(%rip),$rem_4bit
___
&loop ($Xi);
$code.=<<___;
mov $Zlo,8($Xi)
mov $Zhi,($Xi)
lea 280+48(%rsp),%rsi
.cfi_def_cfa %rsi,8
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea (%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lgmult_epilogue:
ret
.cfi_endproc
.size gcm_gmult_4bit,.-gcm_gmult_4bit
___
# per-function register layout
$inp="%rdx";
$len="%rcx";
$rem_8bit=$rem_4bit;
$code.=<<___;
.globl gcm_ghash_4bit
.type gcm_ghash_4bit,\@function,4
.align 16
gcm_ghash_4bit:
.cfi_startproc
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
sub \$280,%rsp
.cfi_adjust_cfa_offset 280
.Lghash_prologue:
mov $inp,%r14 # reassign couple of args
mov $len,%r15
___
{ my $inp="%r14";
my $dat="%edx";
my $len="%r15";
my @nhi=("%ebx","%ecx");
my @rem=("%r12","%r13");
my $Hshr4="%rbp";
&sub ($Htbl,-128); # size optimization
&lea ($Hshr4,"16+128(%rsp)");
{ my @lo =($nlo,$nhi);
my @hi =($Zlo,$Zhi);
&xor ($dat,$dat);
for ($i=0,$j=-2;$i<18;$i++,$j++) {
&mov ("$j(%rsp)",&LB($dat)) if ($i>1);
&or ($lo[0],$tmp) if ($i>1);
&mov (&LB($dat),&LB($lo[1])) if ($i>0 && $i<17);
&shr ($lo[1],4) if ($i>0 && $i<17);
&mov ($tmp,$hi[1]) if ($i>0 && $i<17);
&shr ($hi[1],4) if ($i>0 && $i<17);
&mov ("8*$j($Hshr4)",$hi[0]) if ($i>1);
&mov ($hi[0],"16*$i+0-128($Htbl)") if ($i<16);
&shl (&LB($dat),4) if ($i>0 && $i<17);
&mov ("8*$j-128($Hshr4)",$lo[0]) if ($i>1);
&mov ($lo[0],"16*$i+8-128($Htbl)") if ($i<16);
&shl ($tmp,60) if ($i>0 && $i<17);
push (@lo,shift(@lo));
push (@hi,shift(@hi));
}
}
&add ($Htbl,-128);
&mov ($Zlo,"8($Xi)");
&mov ($Zhi,"0($Xi)");
&add ($len,$inp); # pointer to the end of data
&lea ($rem_8bit,".Lrem_8bit(%rip)");
&jmp (".Louter_loop");
$code.=".align 16\n.Louter_loop:\n";
&xor ($Zhi,"($inp)");
&mov ("%rdx","8($inp)");
&lea ($inp,"16($inp)");
&xor ("%rdx",$Zlo);
&mov ("($Xi)",$Zhi);
&mov ("8($Xi)","%rdx");
&shr ("%rdx",32);
&xor ($nlo,$nlo);
&rol ($dat,8);
&mov (&LB($nlo),&LB($dat));
&movz ($nhi[0],&LB($dat));
&shl (&LB($nlo),4);
&shr ($nhi[0],4);
for ($j=11,$i=0;$i<15;$i++) {
&rol ($dat,8);
&xor ($Zlo,"8($Htbl,$nlo)") if ($i>0);
&xor ($Zhi,"($Htbl,$nlo)") if ($i>0);
&mov ($Zlo,"8($Htbl,$nlo)") if ($i==0);
&mov ($Zhi,"($Htbl,$nlo)") if ($i==0);
&mov (&LB($nlo),&LB($dat));
&xor ($Zlo,$tmp) if ($i>0);
&movzw ($rem[1],"($rem_8bit,$rem[1],2)") if ($i>0);
&movz ($nhi[1],&LB($dat));
&shl (&LB($nlo),4);
&movzb ($rem[0],"(%rsp,$nhi[0])");
&shr ($nhi[1],4) if ($i<14);
&and ($nhi[1],0xf0) if ($i==14);
&shl ($rem[1],48) if ($i>0);
&xor ($rem[0],$Zlo);
&mov ($tmp,$Zhi);
&xor ($Zhi,$rem[1]) if ($i>0);
&shr ($Zlo,8);
&movz ($rem[0],&LB($rem[0]));
&mov ($dat,"$j($Xi)") if (--$j%4==0);
&shr ($Zhi,8);
&xor ($Zlo,"-128($Hshr4,$nhi[0],8)");
&shl ($tmp,56);
&xor ($Zhi,"($Hshr4,$nhi[0],8)");
unshift (@nhi,pop(@nhi)); # "rotate" registers
unshift (@rem,pop(@rem));
}
&movzw ($rem[1],"($rem_8bit,$rem[1],2)");
&xor ($Zlo,"8($Htbl,$nlo)");
&xor ($Zhi,"($Htbl,$nlo)");
&shl ($rem[1],48);
&xor ($Zlo,$tmp);
&xor ($Zhi,$rem[1]);
&movz ($rem[0],&LB($Zlo));
&shr ($Zlo,4);
&mov ($tmp,$Zhi);
&shl (&LB($rem[0]),4);
&shr ($Zhi,4);
&xor ($Zlo,"8($Htbl,$nhi[0])");
&movzw ($rem[0],"($rem_8bit,$rem[0],2)");
&shl ($tmp,60);
&xor ($Zhi,"($Htbl,$nhi[0])");
&xor ($Zlo,$tmp);
&shl ($rem[0],48);
&bswap ($Zlo);
&xor ($Zhi,$rem[0]);
&bswap ($Zhi);
&cmp ($inp,$len);
&jb (".Louter_loop");
}
$code.=<<___;
mov $Zlo,8($Xi)
mov $Zhi,($Xi)
lea 280+48(%rsp),%rsi
.cfi_def_cfa %rsi,8
mov -48(%rsi),%r15
.cfi_restore %r15
mov -40(%rsi),%r14
.cfi_restore %r14
mov -32(%rsi),%r13
.cfi_restore %r13
mov -24(%rsi),%r12
.cfi_restore %r12
mov -16(%rsi),%rbp
.cfi_restore %rbp
mov -8(%rsi),%rbx
.cfi_restore %rbx
lea 0(%rsi),%rsp
.cfi_def_cfa_register %rsp
.Lghash_epilogue:
ret
.cfi_endproc
.size gcm_ghash_4bit,.-gcm_ghash_4bit
___
######################################################################
# PCLMULQDQ version.
@_4args=$win64? ("%rcx","%rdx","%r8", "%r9") : # Win64 order
("%rdi","%rsi","%rdx","%rcx"); # Unix order
($Xi,$Xhi)=("%xmm0","%xmm1"); $Hkey="%xmm2";
($T1,$T2,$T3)=("%xmm3","%xmm4","%xmm5");
sub clmul64x64_T2 { # minimal register pressure
my ($Xhi,$Xi,$Hkey,$HK)=@_;
if (!defined($HK)) { $HK = $T2;
$code.=<<___;
movdqa $Xi,$Xhi #
pshufd \$0b01001110,$Xi,$T1
pshufd \$0b01001110,$Hkey,$T2
pxor $Xi,$T1 #
pxor $Hkey,$T2
___
} else {
$code.=<<___;
movdqa $Xi,$Xhi #
pshufd \$0b01001110,$Xi,$T1
pxor $Xi,$T1 #
___
}
$code.=<<___;
pclmulqdq \$0x00,$Hkey,$Xi #######
pclmulqdq \$0x11,$Hkey,$Xhi #######
pclmulqdq \$0x00,$HK,$T1 #######
pxor $Xi,$T1 #
pxor $Xhi,$T1 #
movdqa $T1,$T2 #
psrldq \$8,$T1
pslldq \$8,$T2 #
pxor $T1,$Xhi
pxor $T2,$Xi #
___
}
sub reduction_alg9 { # 17/11 times faster than Intel version
my ($Xhi,$Xi) = @_;
$code.=<<___;
# 1st phase
movdqa $Xi,$T2 #
movdqa $Xi,$T1
psllq \$5,$Xi
pxor $Xi,$T1 #
psllq \$1,$Xi
pxor $T1,$Xi #
psllq \$57,$Xi #
movdqa $Xi,$T1 #
pslldq \$8,$Xi
psrldq \$8,$T1 #
pxor $T2,$Xi
pxor $T1,$Xhi #
# 2nd phase
movdqa $Xi,$T2
psrlq \$1,$Xi
pxor $T2,$Xhi #
pxor $Xi,$T2
psrlq \$5,$Xi
pxor $T2,$Xi #
psrlq \$1,$Xi #
pxor $Xhi,$Xi #
___
}
{ my ($Htbl,$Xip)=@_4args;
my $HK="%xmm6";
$code.=<<___;
.globl gcm_init_clmul
.type gcm_init_clmul,\@abi-omnipotent
.align 16
gcm_init_clmul:
.cfi_startproc
.L_init_clmul:
___
$code.=<<___ if ($win64);
.LSEH_begin_gcm_init_clmul:
# I can't trust assembler to use specific encoding:-(
.byte 0x48,0x83,0xec,0x18 #sub $0x18,%rsp
.byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp)
___
$code.=<<___;
movdqu ($Xip),$Hkey
pshufd \$0b01001110,$Hkey,$Hkey # dword swap
# <<1 twist
pshufd \$0b11111111,$Hkey,$T2 # broadcast uppermost dword
movdqa $Hkey,$T1
psllq \$1,$Hkey
pxor $T3,$T3 #
psrlq \$63,$T1
pcmpgtd $T2,$T3 # broadcast carry bit
pslldq \$8,$T1
por $T1,$Hkey # H<<=1
# magic reduction
pand .L0x1c2_polynomial(%rip),$T3
pxor $T3,$Hkey # if(carry) H^=0x1c2_polynomial
# calculate H^2
pshufd \$0b01001110,$Hkey,$HK
movdqa $Hkey,$Xi
pxor $Hkey,$HK
___
&clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK);
&reduction_alg9 ($Xhi,$Xi);
$code.=<<___;
pshufd \$0b01001110,$Hkey,$T1
pshufd \$0b01001110,$Xi,$T2
pxor $Hkey,$T1 # Karatsuba pre-processing
movdqu $Hkey,0x00($Htbl) # save H
pxor $Xi,$T2 # Karatsuba pre-processing
movdqu $Xi,0x10($Htbl) # save H^2
palignr \$8,$T1,$T2 # low part is H.lo^H.hi...
movdqu $T2,0x20($Htbl) # save Karatsuba "salt"
___
if ($do4xaggr) {
&clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H^3
&reduction_alg9 ($Xhi,$Xi);
$code.=<<___;
movdqa $Xi,$T3
___
&clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H^4
&reduction_alg9 ($Xhi,$Xi);
$code.=<<___;
pshufd \$0b01001110,$T3,$T1
pshufd \$0b01001110,$Xi,$T2
pxor $T3,$T1 # Karatsuba pre-processing
movdqu $T3,0x30($Htbl) # save H^3
pxor $Xi,$T2 # Karatsuba pre-processing
movdqu $Xi,0x40($Htbl) # save H^4
palignr \$8,$T1,$T2 # low part is H^3.lo^H^3.hi...
movdqu $T2,0x50($Htbl) # save Karatsuba "salt"
___
}
$code.=<<___ if ($win64);
movaps (%rsp),%xmm6
lea 0x18(%rsp),%rsp
.LSEH_end_gcm_init_clmul:
___
$code.=<<___;
ret
.cfi_endproc
.size gcm_init_clmul,.-gcm_init_clmul
___
}
{ my ($Xip,$Htbl)=@_4args;
$code.=<<___;
.globl gcm_gmult_clmul
.type gcm_gmult_clmul,\@abi-omnipotent
.align 16
gcm_gmult_clmul:
.cfi_startproc
.L_gmult_clmul:
movdqu ($Xip),$Xi
movdqa .Lbswap_mask(%rip),$T3
movdqu ($Htbl),$Hkey
movdqu 0x20($Htbl),$T2
pshufb $T3,$Xi
___
&clmul64x64_T2 ($Xhi,$Xi,$Hkey,$T2);
$code.=<<___ if (0 || (&reduction_alg9($Xhi,$Xi)&&0));
# experimental alternative. special thing about is that there
# no dependency between the two multiplications...
mov \$`0xE1<<1`,%eax
mov \$0xA040608020C0E000,%r10 # ((7..0)·0xE0)&0xff
mov \$0x07,%r11d
movq %rax,$T1
movq %r10,$T2
movq %r11,$T3 # borrow $T3
pand $Xi,$T3
pshufb $T3,$T2 # ($Xi&7)·0xE0
movq %rax,$T3
pclmulqdq \$0x00,$Xi,$T1 # ·(0xE1<<1)
pxor $Xi,$T2
pslldq \$15,$T2
paddd $T2,$T2 # <<(64+56+1)
pxor $T2,$Xi
pclmulqdq \$0x01,$T3,$Xi
movdqa .Lbswap_mask(%rip),$T3 # reload $T3
psrldq \$1,$T1
pxor $T1,$Xhi
pslldq \$7,$Xi
pxor $Xhi,$Xi
___
$code.=<<___;
pshufb $T3,$Xi
movdqu $Xi,($Xip)
ret
.cfi_endproc
.size gcm_gmult_clmul,.-gcm_gmult_clmul
___
}
{ my ($Xip,$Htbl,$inp,$len)=@_4args;
my ($Xln,$Xmn,$Xhn,$Hkey2,$HK) = map("%xmm$_",(3..7));
my ($T1,$T2,$T3)=map("%xmm$_",(8..10));
$code.=<<___;
.globl gcm_ghash_clmul
.type gcm_ghash_clmul,\@abi-omnipotent
.align 32
gcm_ghash_clmul:
.cfi_startproc
.L_ghash_clmul:
___
$code.=<<___ if ($win64);
lea -0x88(%rsp),%rax
.LSEH_begin_gcm_ghash_clmul:
# I can't trust assembler to use specific encoding:-(
.byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp
.byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6,-0x20(%rax)
.byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7,-0x10(%rax)
.byte 0x44,0x0f,0x29,0x00 #movaps %xmm8,0(%rax)
.byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9,0x10(%rax)
.byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10,0x20(%rax)
.byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11,0x30(%rax)
.byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12,0x40(%rax)
.byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13,0x50(%rax)
.byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14,0x60(%rax)
.byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15,0x70(%rax)
___
$code.=<<___;
movdqa .Lbswap_mask(%rip),$T3
movdqu ($Xip),$Xi
movdqu ($Htbl),$Hkey
movdqu 0x20($Htbl),$HK
pshufb $T3,$Xi
sub \$0x10,$len
jz .Lodd_tail
movdqu 0x10($Htbl),$Hkey2
___
if ($do4xaggr) {
my ($Xl,$Xm,$Xh,$Hkey3,$Hkey4)=map("%xmm$_",(11..15));
$code.=<<___;
mov OPENSSL_ia32cap_P+4(%rip),%eax
cmp \$0x30,$len
jb .Lskip4x
and \$`1<<26|1<<22`,%eax # isolate MOVBE+XSAVE
cmp \$`1<<22`,%eax # check for MOVBE without XSAVE
je .Lskip4x
sub \$0x30,$len
mov \$0xA040608020C0E000,%rax # ((7..0)·0xE0)&0xff
movdqu 0x30($Htbl),$Hkey3
movdqu 0x40($Htbl),$Hkey4
#######
# Xi+4 =[(H*Ii+3) + (H^2*Ii+2) + (H^3*Ii+1) + H^4*(Ii+Xi)] mod P
#
movdqu 0x30($inp),$Xln
movdqu 0x20($inp),$Xl
pshufb $T3,$Xln
pshufb $T3,$Xl
movdqa $Xln,$Xhn
pshufd \$0b01001110,$Xln,$Xmn
pxor $Xln,$Xmn
pclmulqdq \$0x00,$Hkey,$Xln
pclmulqdq \$0x11,$Hkey,$Xhn
pclmulqdq \$0x00,$HK,$Xmn
movdqa $Xl,$Xh
pshufd \$0b01001110,$Xl,$Xm
pxor $Xl,$Xm
pclmulqdq \$0x00,$Hkey2,$Xl
pclmulqdq \$0x11,$Hkey2,$Xh
pclmulqdq \$0x10,$HK,$Xm
xorps $Xl,$Xln
xorps $Xh,$Xhn
movups 0x50($Htbl),$HK
xorps $Xm,$Xmn
movdqu 0x10($inp),$Xl
movdqu 0($inp),$T1
pshufb $T3,$Xl
pshufb $T3,$T1
movdqa $Xl,$Xh
pshufd \$0b01001110,$Xl,$Xm
pxor $T1,$Xi
pxor $Xl,$Xm
pclmulqdq \$0x00,$Hkey3,$Xl
movdqa $Xi,$Xhi
pshufd \$0b01001110,$Xi,$T1
pxor $Xi,$T1
pclmulqdq \$0x11,$Hkey3,$Xh
pclmulqdq \$0x00,$HK,$Xm
xorps $Xl,$Xln
xorps $Xh,$Xhn
lea 0x40($inp),$inp
sub \$0x40,$len
jc .Ltail4x
jmp .Lmod4_loop
.align 32
.Lmod4_loop:
pclmulqdq \$0x00,$Hkey4,$Xi
xorps $Xm,$Xmn
movdqu 0x30($inp),$Xl
pshufb $T3,$Xl
pclmulqdq \$0x11,$Hkey4,$Xhi
xorps $Xln,$Xi
movdqu 0x20($inp),$Xln
movdqa $Xl,$Xh
pclmulqdq \$0x10,$HK,$T1
pshufd \$0b01001110,$Xl,$Xm
xorps $Xhn,$Xhi
pxor $Xl,$Xm
pshufb $T3,$Xln
movups 0x20($Htbl),$HK
xorps $Xmn,$T1
pclmulqdq \$0x00,$Hkey,$Xl
pshufd \$0b01001110,$Xln,$Xmn
pxor $Xi,$T1 # aggregated Karatsuba post-processing
movdqa $Xln,$Xhn
pxor $Xhi,$T1 #
pxor $Xln,$Xmn
movdqa $T1,$T2 #
pclmulqdq \$0x11,$Hkey,$Xh
pslldq \$8,$T1
psrldq \$8,$T2 #
pxor $T1,$Xi
movdqa .L7_mask(%rip),$T1
pxor $T2,$Xhi #
movq %rax,$T2
pand $Xi,$T1 # 1st phase
pshufb $T1,$T2 #
pxor $Xi,$T2 #
pclmulqdq \$0x00,$HK,$Xm
psllq \$57,$T2 #
movdqa $T2,$T1 #
pslldq \$8,$T2
pclmulqdq \$0x00,$Hkey2,$Xln
psrldq \$8,$T1 #
pxor $T2,$Xi
pxor $T1,$Xhi #
movdqu 0($inp),$T1
movdqa $Xi,$T2 # 2nd phase
psrlq \$1,$Xi
pclmulqdq \$0x11,$Hkey2,$Xhn
xorps $Xl,$Xln
movdqu 0x10($inp),$Xl
pshufb $T3,$Xl
pclmulqdq \$0x10,$HK,$Xmn
xorps $Xh,$Xhn
movups 0x50($Htbl),$HK
pshufb $T3,$T1
pxor $T2,$Xhi #
pxor $Xi,$T2
psrlq \$5,$Xi
movdqa $Xl,$Xh
pxor $Xm,$Xmn
pshufd \$0b01001110,$Xl,$Xm
pxor $T2,$Xi #
pxor $T1,$Xhi
pxor $Xl,$Xm
pclmulqdq \$0x00,$Hkey3,$Xl
psrlq \$1,$Xi #
pxor $Xhi,$Xi #
movdqa $Xi,$Xhi
pclmulqdq \$0x11,$Hkey3,$Xh
xorps $Xl,$Xln
pshufd \$0b01001110,$Xi,$T1
pxor $Xi,$T1
pclmulqdq \$0x00,$HK,$Xm
xorps $Xh,$Xhn
lea 0x40($inp),$inp
sub \$0x40,$len
jnc .Lmod4_loop
.Ltail4x:
pclmulqdq \$0x00,$Hkey4,$Xi
pclmulqdq \$0x11,$Hkey4,$Xhi
pclmulqdq \$0x10,$HK,$T1
xorps $Xm,$Xmn
xorps $Xln,$Xi
xorps $Xhn,$Xhi
pxor $Xi,$Xhi # aggregated Karatsuba post-processing
pxor $Xmn,$T1
pxor $Xhi,$T1 #
pxor $Xi,$Xhi
movdqa $T1,$T2 #
psrldq \$8,$T1
pslldq \$8,$T2 #
pxor $T1,$Xhi
pxor $T2,$Xi #
___
&reduction_alg9($Xhi,$Xi);
$code.=<<___;
add \$0x40,$len
jz .Ldone
movdqu 0x20($Htbl),$HK
sub \$0x10,$len
jz .Lodd_tail
.Lskip4x:
___
}
$code.=<<___;
#######
# Xi+2 =[H*(Ii+1 + Xi+1)] mod P =
# [(H*Ii+1) + (H*Xi+1)] mod P =
# [(H*Ii+1) + H^2*(Ii+Xi)] mod P
#
movdqu ($inp),$T1 # Ii
movdqu 16($inp),$Xln # Ii+1
pshufb $T3,$T1
pshufb $T3,$Xln
pxor $T1,$Xi # Ii+Xi
movdqa $Xln,$Xhn
pshufd \$0b01001110,$Xln,$Xmn
pxor $Xln,$Xmn
pclmulqdq \$0x00,$Hkey,$Xln
pclmulqdq \$0x11,$Hkey,$Xhn
pclmulqdq \$0x00,$HK,$Xmn
lea 32($inp),$inp # i+=2
nop
sub \$0x20,$len
jbe .Leven_tail
nop
jmp .Lmod_loop
.align 32
.Lmod_loop:
movdqa $Xi,$Xhi
movdqa $Xmn,$T1
pshufd \$0b01001110,$Xi,$Xmn #
pxor $Xi,$Xmn #
pclmulqdq \$0x00,$Hkey2,$Xi
pclmulqdq \$0x11,$Hkey2,$Xhi
pclmulqdq \$0x10,$HK,$Xmn
pxor $Xln,$Xi # (H*Ii+1) + H^2*(Ii+Xi)
pxor $Xhn,$Xhi
movdqu ($inp),$T2 # Ii
pxor $Xi,$T1 # aggregated Karatsuba post-processing
pshufb $T3,$T2
movdqu 16($inp),$Xln # Ii+1
pxor $Xhi,$T1
pxor $T2,$Xhi # "Ii+Xi", consume early
pxor $T1,$Xmn
pshufb $T3,$Xln
movdqa $Xmn,$T1 #
psrldq \$8,$T1
pslldq \$8,$Xmn #
pxor $T1,$Xhi
pxor $Xmn,$Xi #
movdqa $Xln,$Xhn #
movdqa $Xi,$T2 # 1st phase
movdqa $Xi,$T1
psllq \$5,$Xi
pxor $Xi,$T1 #
pclmulqdq \$0x00,$Hkey,$Xln #######
psllq \$1,$Xi
pxor $T1,$Xi #
psllq \$57,$Xi #
movdqa $Xi,$T1 #
pslldq \$8,$Xi
psrldq \$8,$T1 #
pxor $T2,$Xi
pshufd \$0b01001110,$Xhn,$Xmn
pxor $T1,$Xhi #
pxor $Xhn,$Xmn #
movdqa $Xi,$T2 # 2nd phase
psrlq \$1,$Xi
pclmulqdq \$0x11,$Hkey,$Xhn #######
pxor $T2,$Xhi #
pxor $Xi,$T2
psrlq \$5,$Xi
pxor $T2,$Xi #
lea 32($inp),$inp
psrlq \$1,$Xi #
pclmulqdq \$0x00,$HK,$Xmn #######
pxor $Xhi,$Xi #
sub \$0x20,$len
ja .Lmod_loop
.Leven_tail:
movdqa $Xi,$Xhi
movdqa $Xmn,$T1
pshufd \$0b01001110,$Xi,$Xmn #
pxor $Xi,$Xmn #
pclmulqdq \$0x00,$Hkey2,$Xi
pclmulqdq \$0x11,$Hkey2,$Xhi
pclmulqdq \$0x10,$HK,$Xmn
pxor $Xln,$Xi # (H*Ii+1) + H^2*(Ii+Xi)
pxor $Xhn,$Xhi
pxor $Xi,$T1
pxor $Xhi,$T1
pxor $T1,$Xmn
movdqa $Xmn,$T1 #
psrldq \$8,$T1
pslldq \$8,$Xmn #
pxor $T1,$Xhi
pxor $Xmn,$Xi #
___
&reduction_alg9 ($Xhi,$Xi);
$code.=<<___;
test $len,$len
jnz .Ldone
.Lodd_tail:
movdqu ($inp),$T1 # Ii
pshufb $T3,$T1
pxor $T1,$Xi # Ii+Xi
___
&clmul64x64_T2 ($Xhi,$Xi,$Hkey,$HK); # H*(Ii+Xi)
&reduction_alg9 ($Xhi,$Xi);
$code.=<<___;
.Ldone:
pshufb $T3,$Xi
movdqu $Xi,($Xip)
___
$code.=<<___ if ($win64);
movaps (%rsp),%xmm6
movaps 0x10(%rsp),%xmm7
movaps 0x20(%rsp),%xmm8
movaps 0x30(%rsp),%xmm9
movaps 0x40(%rsp),%xmm10
movaps 0x50(%rsp),%xmm11
movaps 0x60(%rsp),%xmm12
movaps 0x70(%rsp),%xmm13
movaps 0x80(%rsp),%xmm14
movaps 0x90(%rsp),%xmm15
lea 0xa8(%rsp),%rsp
.LSEH_end_gcm_ghash_clmul:
___
$code.=<<___;
ret
.cfi_endproc
.size gcm_ghash_clmul,.-gcm_ghash_clmul
___
}
$code.=<<___;
.globl gcm_init_avx
.type gcm_init_avx,\@abi-omnipotent
.align 32
gcm_init_avx:
.cfi_startproc
___
if ($avx) {
my ($Htbl,$Xip)=@_4args;
my $HK="%xmm6";
$code.=<<___ if ($win64);
.LSEH_begin_gcm_init_avx:
# I can't trust assembler to use specific encoding:-(
.byte 0x48,0x83,0xec,0x18 #sub $0x18,%rsp
.byte 0x0f,0x29,0x34,0x24 #movaps %xmm6,(%rsp)
___
$code.=<<___;
vzeroupper
vmovdqu ($Xip),$Hkey
vpshufd \$0b01001110,$Hkey,$Hkey # dword swap
# <<1 twist
vpshufd \$0b11111111,$Hkey,$T2 # broadcast uppermost dword
vpsrlq \$63,$Hkey,$T1
vpsllq \$1,$Hkey,$Hkey
vpxor $T3,$T3,$T3 #
vpcmpgtd $T2,$T3,$T3 # broadcast carry bit
vpslldq \$8,$T1,$T1
vpor $T1,$Hkey,$Hkey # H<<=1
# magic reduction
vpand .L0x1c2_polynomial(%rip),$T3,$T3
vpxor $T3,$Hkey,$Hkey # if(carry) H^=0x1c2_polynomial
vpunpckhqdq $Hkey,$Hkey,$HK
vmovdqa $Hkey,$Xi
vpxor $Hkey,$HK,$HK
mov \$4,%r10 # up to H^8
jmp .Linit_start_avx
___
sub clmul64x64_avx {
my ($Xhi,$Xi,$Hkey,$HK)=@_;
if (!defined($HK)) { $HK = $T2;
$code.=<<___;
vpunpckhqdq $Xi,$Xi,$T1
vpunpckhqdq $Hkey,$Hkey,$T2
vpxor $Xi,$T1,$T1 #
vpxor $Hkey,$T2,$T2
___
} else {
$code.=<<___;
vpunpckhqdq $Xi,$Xi,$T1
vpxor $Xi,$T1,$T1 #
___
}
$code.=<<___;
vpclmulqdq \$0x11,$Hkey,$Xi,$Xhi #######
vpclmulqdq \$0x00,$Hkey,$Xi,$Xi #######
vpclmulqdq \$0x00,$HK,$T1,$T1 #######
vpxor $Xi,$Xhi,$T2 #
vpxor $T2,$T1,$T1 #
vpslldq \$8,$T1,$T2 #
vpsrldq \$8,$T1,$T1
vpxor $T2,$Xi,$Xi #
vpxor $T1,$Xhi,$Xhi
___
}
sub reduction_avx {
my ($Xhi,$Xi) = @_;
$code.=<<___;
vpsllq \$57,$Xi,$T1 # 1st phase
vpsllq \$62,$Xi,$T2
vpxor $T1,$T2,$T2 #
vpsllq \$63,$Xi,$T1
vpxor $T1,$T2,$T2 #
vpslldq \$8,$T2,$T1 #
vpsrldq \$8,$T2,$T2
vpxor $T1,$Xi,$Xi #
vpxor $T2,$Xhi,$Xhi
vpsrlq \$1,$Xi,$T2 # 2nd phase
vpxor $Xi,$Xhi,$Xhi
vpxor $T2,$Xi,$Xi #
vpsrlq \$5,$T2,$T2
vpxor $T2,$Xi,$Xi #
vpsrlq \$1,$Xi,$Xi #
vpxor $Xhi,$Xi,$Xi #
___
}
$code.=<<___;
.align 32
.Linit_loop_avx:
vpalignr \$8,$T1,$T2,$T3 # low part is H.lo^H.hi...
vmovdqu $T3,-0x10($Htbl) # save Karatsuba "salt"
___
&clmul64x64_avx ($Xhi,$Xi,$Hkey,$HK); # calculate H^3,5,7
&reduction_avx ($Xhi,$Xi);
$code.=<<___;
.Linit_start_avx:
vmovdqa $Xi,$T3
___
&clmul64x64_avx ($Xhi,$Xi,$Hkey,$HK); # calculate H^2,4,6,8
&reduction_avx ($Xhi,$Xi);
$code.=<<___;
vpshufd \$0b01001110,$T3,$T1
vpshufd \$0b01001110,$Xi,$T2
vpxor $T3,$T1,$T1 # Karatsuba pre-processing
vmovdqu $T3,0x00($Htbl) # save H^1,3,5,7
vpxor $Xi,$T2,$T2 # Karatsuba pre-processing
vmovdqu $Xi,0x10($Htbl) # save H^2,4,6,8
lea 0x30($Htbl),$Htbl
sub \$1,%r10
jnz .Linit_loop_avx
vpalignr \$8,$T2,$T1,$T3 # last "salt" is flipped
vmovdqu $T3,-0x10($Htbl)
vzeroupper
___
$code.=<<___ if ($win64);
movaps (%rsp),%xmm6
lea 0x18(%rsp),%rsp
.LSEH_end_gcm_init_avx:
___
$code.=<<___;
ret
.cfi_endproc
.size gcm_init_avx,.-gcm_init_avx
___
} else {
$code.=<<___;
jmp .L_init_clmul
+.cfi_endproc
.size gcm_init_avx,.-gcm_init_avx
___
}
$code.=<<___;
.globl gcm_gmult_avx
.type gcm_gmult_avx,\@abi-omnipotent
.align 32
gcm_gmult_avx:
.cfi_startproc
jmp .L_gmult_clmul
.cfi_endproc
.size gcm_gmult_avx,.-gcm_gmult_avx
___
$code.=<<___;
.globl gcm_ghash_avx
.type gcm_ghash_avx,\@abi-omnipotent
.align 32
gcm_ghash_avx:
.cfi_startproc
___
if ($avx) {
my ($Xip,$Htbl,$inp,$len)=@_4args;
my ($Xlo,$Xhi,$Xmi,
$Zlo,$Zhi,$Zmi,
$Hkey,$HK,$T1,$T2,
$Xi,$Xo,$Tred,$bswap,$Ii,$Ij) = map("%xmm$_",(0..15));
$code.=<<___ if ($win64);
lea -0x88(%rsp),%rax
.LSEH_begin_gcm_ghash_avx:
# I can't trust assembler to use specific encoding:-(
.byte 0x48,0x8d,0x60,0xe0 #lea -0x20(%rax),%rsp
.byte 0x0f,0x29,0x70,0xe0 #movaps %xmm6,-0x20(%rax)
.byte 0x0f,0x29,0x78,0xf0 #movaps %xmm7,-0x10(%rax)
.byte 0x44,0x0f,0x29,0x00 #movaps %xmm8,0(%rax)
.byte 0x44,0x0f,0x29,0x48,0x10 #movaps %xmm9,0x10(%rax)
.byte 0x44,0x0f,0x29,0x50,0x20 #movaps %xmm10,0x20(%rax)
.byte 0x44,0x0f,0x29,0x58,0x30 #movaps %xmm11,0x30(%rax)
.byte 0x44,0x0f,0x29,0x60,0x40 #movaps %xmm12,0x40(%rax)
.byte 0x44,0x0f,0x29,0x68,0x50 #movaps %xmm13,0x50(%rax)
.byte 0x44,0x0f,0x29,0x70,0x60 #movaps %xmm14,0x60(%rax)
.byte 0x44,0x0f,0x29,0x78,0x70 #movaps %xmm15,0x70(%rax)
___
$code.=<<___;
vzeroupper
vmovdqu ($Xip),$Xi # load $Xi
lea .L0x1c2_polynomial(%rip),%r10
lea 0x40($Htbl),$Htbl # size optimization
vmovdqu .Lbswap_mask(%rip),$bswap
vpshufb $bswap,$Xi,$Xi
cmp \$0x80,$len
jb .Lshort_avx
sub \$0x80,$len
vmovdqu 0x70($inp),$Ii # I[7]
vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1
vpshufb $bswap,$Ii,$Ii
vmovdqu 0x20-0x40($Htbl),$HK
vpunpckhqdq $Ii,$Ii,$T2
vmovdqu 0x60($inp),$Ij # I[6]
vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
vpxor $Ii,$T2,$T2
vpshufb $bswap,$Ij,$Ij
vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2
vpunpckhqdq $Ij,$Ij,$T1
vmovdqu 0x50($inp),$Ii # I[5]
vpclmulqdq \$0x00,$HK,$T2,$Xmi
vpxor $Ij,$T1,$T1
vpshufb $bswap,$Ii,$Ii
vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
vpunpckhqdq $Ii,$Ii,$T2
vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3
vpxor $Ii,$T2,$T2
vmovdqu 0x40($inp),$Ij # I[4]
vpclmulqdq \$0x10,$HK,$T1,$Zmi
vmovdqu 0x50-0x40($Htbl),$HK
vpshufb $bswap,$Ij,$Ij
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
vpxor $Xhi,$Zhi,$Zhi
vpunpckhqdq $Ij,$Ij,$T1
vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T2,$Xmi
vpxor $Ij,$T1,$T1
vmovdqu 0x30($inp),$Ii # I[3]
vpxor $Zlo,$Xlo,$Xlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
vpxor $Zhi,$Xhi,$Xhi
vpshufb $bswap,$Ii,$Ii
vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5
vpxor $Zmi,$Xmi,$Xmi
vpunpckhqdq $Ii,$Ii,$T2
vpclmulqdq \$0x10,$HK,$T1,$Zmi
vmovdqu 0x80-0x40($Htbl),$HK
vpxor $Ii,$T2,$T2
vmovdqu 0x20($inp),$Ij # I[2]
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
vpxor $Xhi,$Zhi,$Zhi
vpshufb $bswap,$Ij,$Ij
vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6
vpxor $Xmi,$Zmi,$Zmi
vpunpckhqdq $Ij,$Ij,$T1
vpclmulqdq \$0x00,$HK,$T2,$Xmi
vpxor $Ij,$T1,$T1
vmovdqu 0x10($inp),$Ii # I[1]
vpxor $Zlo,$Xlo,$Xlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
vpxor $Zhi,$Xhi,$Xhi
vpshufb $bswap,$Ii,$Ii
vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7
vpxor $Zmi,$Xmi,$Xmi
vpunpckhqdq $Ii,$Ii,$T2
vpclmulqdq \$0x10,$HK,$T1,$Zmi
vmovdqu 0xb0-0x40($Htbl),$HK
vpxor $Ii,$T2,$T2
vmovdqu ($inp),$Ij # I[0]
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
vpxor $Xhi,$Zhi,$Zhi
vpshufb $bswap,$Ij,$Ij
vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
vmovdqu 0xa0-0x40($Htbl),$Hkey # $Hkey^8
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x10,$HK,$T2,$Xmi
lea 0x80($inp),$inp
cmp \$0x80,$len
jb .Ltail_avx
vpxor $Xi,$Ij,$Ij # accumulate $Xi
sub \$0x80,$len
jmp .Loop8x_avx
.align 32
.Loop8x_avx:
vpunpckhqdq $Ij,$Ij,$T1
vmovdqu 0x70($inp),$Ii # I[7]
vpxor $Xlo,$Zlo,$Zlo
vpxor $Ij,$T1,$T1
vpclmulqdq \$0x00,$Hkey,$Ij,$Xi
vpshufb $bswap,$Ii,$Ii
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x11,$Hkey,$Ij,$Xo
vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1
vpunpckhqdq $Ii,$Ii,$T2
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T1,$Tred
vmovdqu 0x20-0x40($Htbl),$HK
vpxor $Ii,$T2,$T2
vmovdqu 0x60($inp),$Ij # I[6]
vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
vpxor $Zlo,$Xi,$Xi # collect result
vpshufb $bswap,$Ij,$Ij
vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
vxorps $Zhi,$Xo,$Xo
vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2
vpunpckhqdq $Ij,$Ij,$T1
vpclmulqdq \$0x00,$HK, $T2,$Xmi
vpxor $Zmi,$Tred,$Tred
vxorps $Ij,$T1,$T1
vmovdqu 0x50($inp),$Ii # I[5]
vpxor $Xi,$Tred,$Tred # aggregated Karatsuba post-processing
vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
vpxor $Xo,$Tred,$Tred
vpslldq \$8,$Tred,$T2
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
vpsrldq \$8,$Tred,$Tred
vpxor $T2, $Xi, $Xi
vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3
vpshufb $bswap,$Ii,$Ii
vxorps $Tred,$Xo, $Xo
vpxor $Xhi,$Zhi,$Zhi
vpunpckhqdq $Ii,$Ii,$T2
vpclmulqdq \$0x10,$HK, $T1,$Zmi
vmovdqu 0x50-0x40($Htbl),$HK
vpxor $Ii,$T2,$T2
vpxor $Xmi,$Zmi,$Zmi
vmovdqu 0x40($inp),$Ij # I[4]
vpalignr \$8,$Xi,$Xi,$Tred # 1st phase
vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
vpshufb $bswap,$Ij,$Ij
vpxor $Zlo,$Xlo,$Xlo
vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Zhi,$Xhi,$Xhi
vpclmulqdq \$0x00,$HK, $T2,$Xmi
vxorps $Ij,$T1,$T1
vpxor $Zmi,$Xmi,$Xmi
vmovdqu 0x30($inp),$Ii # I[3]
vpclmulqdq \$0x10,(%r10),$Xi,$Xi
vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
vpshufb $bswap,$Ii,$Ii
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5
vpunpckhqdq $Ii,$Ii,$T2
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x10,$HK, $T1,$Zmi
vmovdqu 0x80-0x40($Htbl),$HK
vpxor $Ii,$T2,$T2
vpxor $Xmi,$Zmi,$Zmi
vmovdqu 0x20($inp),$Ij # I[2]
vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
vpshufb $bswap,$Ij,$Ij
vpxor $Zlo,$Xlo,$Xlo
vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Zhi,$Xhi,$Xhi
vpclmulqdq \$0x00,$HK, $T2,$Xmi
vpxor $Ij,$T1,$T1
vpxor $Zmi,$Xmi,$Xmi
vxorps $Tred,$Xi,$Xi
vmovdqu 0x10($inp),$Ii # I[1]
vpalignr \$8,$Xi,$Xi,$Tred # 2nd phase
vpclmulqdq \$0x00,$Hkey,$Ij,$Zlo
vpshufb $bswap,$Ii,$Ii
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x11,$Hkey,$Ij,$Zhi
vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7
vpclmulqdq \$0x10,(%r10),$Xi,$Xi
vxorps $Xo,$Tred,$Tred
vpunpckhqdq $Ii,$Ii,$T2
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x10,$HK, $T1,$Zmi
vmovdqu 0xb0-0x40($Htbl),$HK
vpxor $Ii,$T2,$T2
vpxor $Xmi,$Zmi,$Zmi
vmovdqu ($inp),$Ij # I[0]
vpclmulqdq \$0x00,$Hkey,$Ii,$Xlo
vpshufb $bswap,$Ij,$Ij
vpclmulqdq \$0x11,$Hkey,$Ii,$Xhi
vmovdqu 0xa0-0x40($Htbl),$Hkey # $Hkey^8
vpxor $Tred,$Ij,$Ij
vpclmulqdq \$0x10,$HK, $T2,$Xmi
vpxor $Xi,$Ij,$Ij # accumulate $Xi
lea 0x80($inp),$inp
sub \$0x80,$len
jnc .Loop8x_avx
add \$0x80,$len
jmp .Ltail_no_xor_avx
.align 32
.Lshort_avx:
vmovdqu -0x10($inp,$len),$Ii # very last word
lea ($inp,$len),$inp
vmovdqu 0x00-0x40($Htbl),$Hkey # $Hkey^1
vmovdqu 0x20-0x40($Htbl),$HK
vpshufb $bswap,$Ii,$Ij
vmovdqa $Xlo,$Zlo # subtle way to zero $Zlo,
vmovdqa $Xhi,$Zhi # $Zhi and
vmovdqa $Xmi,$Zmi # $Zmi
sub \$0x10,$len
jz .Ltail_avx
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
vpxor $Ij,$T1,$T1
vmovdqu -0x20($inp),$Ii
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
vmovdqu 0x10-0x40($Htbl),$Hkey # $Hkey^2
vpshufb $bswap,$Ii,$Ij
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T1,$Xmi
vpsrldq \$8,$HK,$HK
sub \$0x10,$len
jz .Ltail_avx
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
vpxor $Ij,$T1,$T1
vmovdqu -0x30($inp),$Ii
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
vmovdqu 0x30-0x40($Htbl),$Hkey # $Hkey^3
vpshufb $bswap,$Ii,$Ij
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T1,$Xmi
vmovdqu 0x50-0x40($Htbl),$HK
sub \$0x10,$len
jz .Ltail_avx
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
vpxor $Ij,$T1,$T1
vmovdqu -0x40($inp),$Ii
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
vmovdqu 0x40-0x40($Htbl),$Hkey # $Hkey^4
vpshufb $bswap,$Ii,$Ij
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T1,$Xmi
vpsrldq \$8,$HK,$HK
sub \$0x10,$len
jz .Ltail_avx
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
vpxor $Ij,$T1,$T1
vmovdqu -0x50($inp),$Ii
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
vmovdqu 0x60-0x40($Htbl),$Hkey # $Hkey^5
vpshufb $bswap,$Ii,$Ij
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T1,$Xmi
vmovdqu 0x80-0x40($Htbl),$HK
sub \$0x10,$len
jz .Ltail_avx
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
vpxor $Ij,$T1,$T1
vmovdqu -0x60($inp),$Ii
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
vmovdqu 0x70-0x40($Htbl),$Hkey # $Hkey^6
vpshufb $bswap,$Ii,$Ij
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T1,$Xmi
vpsrldq \$8,$HK,$HK
sub \$0x10,$len
jz .Ltail_avx
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
vpxor $Ij,$T1,$T1
vmovdqu -0x70($inp),$Ii
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
vmovdqu 0x90-0x40($Htbl),$Hkey # $Hkey^7
vpshufb $bswap,$Ii,$Ij
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T1,$Xmi
vmovq 0xb8-0x40($Htbl),$HK
sub \$0x10,$len
jmp .Ltail_avx
.align 32
.Ltail_avx:
vpxor $Xi,$Ij,$Ij # accumulate $Xi
.Ltail_no_xor_avx:
vpunpckhqdq $Ij,$Ij,$T1
vpxor $Xlo,$Zlo,$Zlo
vpclmulqdq \$0x00,$Hkey,$Ij,$Xlo
vpxor $Ij,$T1,$T1
vpxor $Xhi,$Zhi,$Zhi
vpclmulqdq \$0x11,$Hkey,$Ij,$Xhi
vpxor $Xmi,$Zmi,$Zmi
vpclmulqdq \$0x00,$HK,$T1,$Xmi
vmovdqu (%r10),$Tred
vpxor $Xlo,$Zlo,$Xi
vpxor $Xhi,$Zhi,$Xo
vpxor $Xmi,$Zmi,$Zmi
vpxor $Xi, $Zmi,$Zmi # aggregated Karatsuba post-processing
vpxor $Xo, $Zmi,$Zmi
vpslldq \$8, $Zmi,$T2
vpsrldq \$8, $Zmi,$Zmi
vpxor $T2, $Xi, $Xi
vpxor $Zmi,$Xo, $Xo
vpclmulqdq \$0x10,$Tred,$Xi,$T2 # 1st phase
vpalignr \$8,$Xi,$Xi,$Xi
vpxor $T2,$Xi,$Xi
vpclmulqdq \$0x10,$Tred,$Xi,$T2 # 2nd phase
vpalignr \$8,$Xi,$Xi,$Xi
vpxor $Xo,$Xi,$Xi
vpxor $T2,$Xi,$Xi
cmp \$0,$len
jne .Lshort_avx
vpshufb $bswap,$Xi,$Xi
vmovdqu $Xi,($Xip)
vzeroupper
___
$code.=<<___ if ($win64);
movaps (%rsp),%xmm6
movaps 0x10(%rsp),%xmm7
movaps 0x20(%rsp),%xmm8
movaps 0x30(%rsp),%xmm9
movaps 0x40(%rsp),%xmm10
movaps 0x50(%rsp),%xmm11
movaps 0x60(%rsp),%xmm12
movaps 0x70(%rsp),%xmm13
movaps 0x80(%rsp),%xmm14
movaps 0x90(%rsp),%xmm15
lea 0xa8(%rsp),%rsp
.LSEH_end_gcm_ghash_avx:
___
$code.=<<___;
ret
.cfi_endproc
.size gcm_ghash_avx,.-gcm_ghash_avx
___
} else {
$code.=<<___;
jmp .L_ghash_clmul
+.cfi_endproc
.size gcm_ghash_avx,.-gcm_ghash_avx
___
}
$code.=<<___;
.align 64
.Lbswap_mask:
.byte 15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0
.L0x1c2_polynomial:
.byte 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xc2
.L7_mask:
.long 7,0,7,0
.L7_mask_poly:
.long 7,0,`0xE1<<1`,0
.align 64
.type .Lrem_4bit,\@object
.Lrem_4bit:
.long 0,`0x0000<<16`,0,`0x1C20<<16`,0,`0x3840<<16`,0,`0x2460<<16`
.long 0,`0x7080<<16`,0,`0x6CA0<<16`,0,`0x48C0<<16`,0,`0x54E0<<16`
.long 0,`0xE100<<16`,0,`0xFD20<<16`,0,`0xD940<<16`,0,`0xC560<<16`
.long 0,`0x9180<<16`,0,`0x8DA0<<16`,0,`0xA9C0<<16`,0,`0xB5E0<<16`
.type .Lrem_8bit,\@object
.Lrem_8bit:
.value 0x0000,0x01C2,0x0384,0x0246,0x0708,0x06CA,0x048C,0x054E
.value 0x0E10,0x0FD2,0x0D94,0x0C56,0x0918,0x08DA,0x0A9C,0x0B5E
.value 0x1C20,0x1DE2,0x1FA4,0x1E66,0x1B28,0x1AEA,0x18AC,0x196E
.value 0x1230,0x13F2,0x11B4,0x1076,0x1538,0x14FA,0x16BC,0x177E
.value 0x3840,0x3982,0x3BC4,0x3A06,0x3F48,0x3E8A,0x3CCC,0x3D0E
.value 0x3650,0x3792,0x35D4,0x3416,0x3158,0x309A,0x32DC,0x331E
.value 0x2460,0x25A2,0x27E4,0x2626,0x2368,0x22AA,0x20EC,0x212E
.value 0x2A70,0x2BB2,0x29F4,0x2836,0x2D78,0x2CBA,0x2EFC,0x2F3E
.value 0x7080,0x7142,0x7304,0x72C6,0x7788,0x764A,0x740C,0x75CE
.value 0x7E90,0x7F52,0x7D14,0x7CD6,0x7998,0x785A,0x7A1C,0x7BDE
.value 0x6CA0,0x6D62,0x6F24,0x6EE6,0x6BA8,0x6A6A,0x682C,0x69EE
.value 0x62B0,0x6372,0x6134,0x60F6,0x65B8,0x647A,0x663C,0x67FE
.value 0x48C0,0x4902,0x4B44,0x4A86,0x4FC8,0x4E0A,0x4C4C,0x4D8E
.value 0x46D0,0x4712,0x4554,0x4496,0x41D8,0x401A,0x425C,0x439E
.value 0x54E0,0x5522,0x5764,0x56A6,0x53E8,0x522A,0x506C,0x51AE
.value 0x5AF0,0x5B32,0x5974,0x58B6,0x5DF8,0x5C3A,0x5E7C,0x5FBE
.value 0xE100,0xE0C2,0xE284,0xE346,0xE608,0xE7CA,0xE58C,0xE44E
.value 0xEF10,0xEED2,0xEC94,0xED56,0xE818,0xE9DA,0xEB9C,0xEA5E
.value 0xFD20,0xFCE2,0xFEA4,0xFF66,0xFA28,0xFBEA,0xF9AC,0xF86E
.value 0xF330,0xF2F2,0xF0B4,0xF176,0xF438,0xF5FA,0xF7BC,0xF67E
.value 0xD940,0xD882,0xDAC4,0xDB06,0xDE48,0xDF8A,0xDDCC,0xDC0E
.value 0xD750,0xD692,0xD4D4,0xD516,0xD058,0xD19A,0xD3DC,0xD21E
.value 0xC560,0xC4A2,0xC6E4,0xC726,0xC268,0xC3AA,0xC1EC,0xC02E
.value 0xCB70,0xCAB2,0xC8F4,0xC936,0xCC78,0xCDBA,0xCFFC,0xCE3E
.value 0x9180,0x9042,0x9204,0x93C6,0x9688,0x974A,0x950C,0x94CE
.value 0x9F90,0x9E52,0x9C14,0x9DD6,0x9898,0x995A,0x9B1C,0x9ADE
.value 0x8DA0,0x8C62,0x8E24,0x8FE6,0x8AA8,0x8B6A,0x892C,0x88EE
.value 0x83B0,0x8272,0x8034,0x81F6,0x84B8,0x857A,0x873C,0x86FE
.value 0xA9C0,0xA802,0xAA44,0xAB86,0xAEC8,0xAF0A,0xAD4C,0xAC8E
.value 0xA7D0,0xA612,0xA454,0xA596,0xA0D8,0xA11A,0xA35C,0xA29E
.value 0xB5E0,0xB422,0xB664,0xB7A6,0xB2E8,0xB32A,0xB16C,0xB0AE
.value 0xBBF0,0xBA32,0xB874,0xB9B6,0xBCF8,0xBD3A,0xBF7C,0xBEBE
.asciz "GHASH for x86_64, CRYPTOGAMS by <appro\@openssl.org>"
.align 64
___
# EXCEPTION_DISPOSITION handler (EXCEPTION_RECORD *rec,ULONG64 frame,
# CONTEXT *context,DISPATCHER_CONTEXT *disp)
if ($win64) {
$rec="%rcx";
$frame="%rdx";
$context="%r8";
$disp="%r9";
$code.=<<___;
.extern __imp_RtlVirtualUnwind
.type se_handler,\@abi-omnipotent
.align 16
se_handler:
push %rsi
push %rdi
push %rbx
push %rbp
push %r12
push %r13
push %r14
push %r15
pushfq
sub \$64,%rsp
mov 120($context),%rax # pull context->Rax
mov 248($context),%rbx # pull context->Rip
mov 8($disp),%rsi # disp->ImageBase
mov 56($disp),%r11 # disp->HandlerData
mov 0(%r11),%r10d # HandlerData[0]
lea (%rsi,%r10),%r10 # prologue label
cmp %r10,%rbx # context->Rip<prologue label
jb .Lin_prologue
mov 152($context),%rax # pull context->Rsp
mov 4(%r11),%r10d # HandlerData[1]
lea (%rsi,%r10),%r10 # epilogue label
cmp %r10,%rbx # context->Rip>=epilogue label
jae .Lin_prologue
lea 48+280(%rax),%rax # adjust "rsp"
mov -8(%rax),%rbx
mov -16(%rax),%rbp
mov -24(%rax),%r12
mov -32(%rax),%r13
mov -40(%rax),%r14
mov -48(%rax),%r15
mov %rbx,144($context) # restore context->Rbx
mov %rbp,160($context) # restore context->Rbp
mov %r12,216($context) # restore context->R12
mov %r13,224($context) # restore context->R13
mov %r14,232($context) # restore context->R14
mov %r15,240($context) # restore context->R15
.Lin_prologue:
mov 8(%rax),%rdi
mov 16(%rax),%rsi
mov %rax,152($context) # restore context->Rsp
mov %rsi,168($context) # restore context->Rsi
mov %rdi,176($context) # restore context->Rdi
mov 40($disp),%rdi # disp->ContextRecord
mov $context,%rsi # context
mov \$`1232/8`,%ecx # sizeof(CONTEXT)
.long 0xa548f3fc # cld; rep movsq
mov $disp,%rsi
xor %rcx,%rcx # arg1, UNW_FLAG_NHANDLER
mov 8(%rsi),%rdx # arg2, disp->ImageBase
mov 0(%rsi),%r8 # arg3, disp->ControlPc
mov 16(%rsi),%r9 # arg4, disp->FunctionEntry
mov 40(%rsi),%r10 # disp->ContextRecord
lea 56(%rsi),%r11 # &disp->HandlerData
lea 24(%rsi),%r12 # &disp->EstablisherFrame
mov %r10,32(%rsp) # arg5
mov %r11,40(%rsp) # arg6
mov %r12,48(%rsp) # arg7
mov %rcx,56(%rsp) # arg8, (NULL)
call *__imp_RtlVirtualUnwind(%rip)
mov \$1,%eax # ExceptionContinueSearch
add \$64,%rsp
popfq
pop %r15
pop %r14
pop %r13
pop %r12
pop %rbp
pop %rbx
pop %rdi
pop %rsi
ret
.size se_handler,.-se_handler
.section .pdata
.align 4
.rva .LSEH_begin_gcm_gmult_4bit
.rva .LSEH_end_gcm_gmult_4bit
.rva .LSEH_info_gcm_gmult_4bit
.rva .LSEH_begin_gcm_ghash_4bit
.rva .LSEH_end_gcm_ghash_4bit
.rva .LSEH_info_gcm_ghash_4bit
.rva .LSEH_begin_gcm_init_clmul
.rva .LSEH_end_gcm_init_clmul
.rva .LSEH_info_gcm_init_clmul
.rva .LSEH_begin_gcm_ghash_clmul
.rva .LSEH_end_gcm_ghash_clmul
.rva .LSEH_info_gcm_ghash_clmul
___
$code.=<<___ if ($avx);
.rva .LSEH_begin_gcm_init_avx
.rva .LSEH_end_gcm_init_avx
.rva .LSEH_info_gcm_init_clmul
.rva .LSEH_begin_gcm_ghash_avx
.rva .LSEH_end_gcm_ghash_avx
.rva .LSEH_info_gcm_ghash_clmul
___
$code.=<<___;
.section .xdata
.align 8
.LSEH_info_gcm_gmult_4bit:
.byte 9,0,0,0
.rva se_handler
.rva .Lgmult_prologue,.Lgmult_epilogue # HandlerData
.LSEH_info_gcm_ghash_4bit:
.byte 9,0,0,0
.rva se_handler
.rva .Lghash_prologue,.Lghash_epilogue # HandlerData
.LSEH_info_gcm_init_clmul:
.byte 0x01,0x08,0x03,0x00
.byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6
.byte 0x04,0x22,0x00,0x00 #sub rsp,0x18
.LSEH_info_gcm_ghash_clmul:
.byte 0x01,0x33,0x16,0x00
.byte 0x33,0xf8,0x09,0x00 #movaps 0x90(rsp),xmm15
.byte 0x2e,0xe8,0x08,0x00 #movaps 0x80(rsp),xmm14
.byte 0x29,0xd8,0x07,0x00 #movaps 0x70(rsp),xmm13
.byte 0x24,0xc8,0x06,0x00 #movaps 0x60(rsp),xmm12
.byte 0x1f,0xb8,0x05,0x00 #movaps 0x50(rsp),xmm11
.byte 0x1a,0xa8,0x04,0x00 #movaps 0x40(rsp),xmm10
.byte 0x15,0x98,0x03,0x00 #movaps 0x30(rsp),xmm9
.byte 0x10,0x88,0x02,0x00 #movaps 0x20(rsp),xmm8
.byte 0x0c,0x78,0x01,0x00 #movaps 0x10(rsp),xmm7
.byte 0x08,0x68,0x00,0x00 #movaps 0x00(rsp),xmm6
.byte 0x04,0x01,0x15,0x00 #sub rsp,0xa8
___
}
$code =~ s/\`([^\`]*)\`/eval($1)/gem;
print $code;
close STDOUT;
diff --git a/crypto/modes/ccm128.c b/crypto/modes/ccm128.c
index 85ce84f10d80..05a33239f56e 100644
--- a/crypto/modes/ccm128.c
+++ b/crypto/modes/ccm128.c
@@ -1,432 +1,432 @@
/*
- * Copyright 2011-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/crypto.h>
#include "modes_lcl.h"
#include <string.h>
/*
* First you setup M and L parameters and pass the key schedule. This is
* called once per session setup...
*/
void CRYPTO_ccm128_init(CCM128_CONTEXT *ctx,
unsigned int M, unsigned int L, void *key,
block128_f block)
{
memset(ctx->nonce.c, 0, sizeof(ctx->nonce.c));
ctx->nonce.c[0] = ((u8)(L - 1) & 7) | (u8)(((M - 2) / 2) & 7) << 3;
ctx->blocks = 0;
ctx->block = block;
ctx->key = key;
}
/* !!! Following interfaces are to be called *once* per packet !!! */
/* Then you setup per-message nonce and pass the length of the message */
int CRYPTO_ccm128_setiv(CCM128_CONTEXT *ctx,
const unsigned char *nonce, size_t nlen, size_t mlen)
{
unsigned int L = ctx->nonce.c[0] & 7; /* the L parameter */
if (nlen < (14 - L))
return -1; /* nonce is too short */
if (sizeof(mlen) == 8 && L >= 3) {
ctx->nonce.c[8] = (u8)(mlen >> (56 % (sizeof(mlen) * 8)));
ctx->nonce.c[9] = (u8)(mlen >> (48 % (sizeof(mlen) * 8)));
ctx->nonce.c[10] = (u8)(mlen >> (40 % (sizeof(mlen) * 8)));
ctx->nonce.c[11] = (u8)(mlen >> (32 % (sizeof(mlen) * 8)));
} else
ctx->nonce.u[1] = 0;
ctx->nonce.c[12] = (u8)(mlen >> 24);
ctx->nonce.c[13] = (u8)(mlen >> 16);
ctx->nonce.c[14] = (u8)(mlen >> 8);
ctx->nonce.c[15] = (u8)mlen;
ctx->nonce.c[0] &= ~0x40; /* clear Adata flag */
memcpy(&ctx->nonce.c[1], nonce, 14 - L);
return 0;
}
/* Then you pass additional authentication data, this is optional */
void CRYPTO_ccm128_aad(CCM128_CONTEXT *ctx,
const unsigned char *aad, size_t alen)
{
unsigned int i;
block128_f block = ctx->block;
if (alen == 0)
return;
ctx->nonce.c[0] |= 0x40; /* set Adata flag */
(*block) (ctx->nonce.c, ctx->cmac.c, ctx->key), ctx->blocks++;
if (alen < (0x10000 - 0x100)) {
ctx->cmac.c[0] ^= (u8)(alen >> 8);
ctx->cmac.c[1] ^= (u8)alen;
i = 2;
} else if (sizeof(alen) == 8
&& alen >= (size_t)1 << (32 % (sizeof(alen) * 8))) {
ctx->cmac.c[0] ^= 0xFF;
ctx->cmac.c[1] ^= 0xFF;
ctx->cmac.c[2] ^= (u8)(alen >> (56 % (sizeof(alen) * 8)));
ctx->cmac.c[3] ^= (u8)(alen >> (48 % (sizeof(alen) * 8)));
ctx->cmac.c[4] ^= (u8)(alen >> (40 % (sizeof(alen) * 8)));
ctx->cmac.c[5] ^= (u8)(alen >> (32 % (sizeof(alen) * 8)));
ctx->cmac.c[6] ^= (u8)(alen >> 24);
ctx->cmac.c[7] ^= (u8)(alen >> 16);
ctx->cmac.c[8] ^= (u8)(alen >> 8);
ctx->cmac.c[9] ^= (u8)alen;
i = 10;
} else {
ctx->cmac.c[0] ^= 0xFF;
ctx->cmac.c[1] ^= 0xFE;
ctx->cmac.c[2] ^= (u8)(alen >> 24);
ctx->cmac.c[3] ^= (u8)(alen >> 16);
ctx->cmac.c[4] ^= (u8)(alen >> 8);
ctx->cmac.c[5] ^= (u8)alen;
i = 6;
}
do {
for (; i < 16 && alen; ++i, ++aad, --alen)
ctx->cmac.c[i] ^= *aad;
(*block) (ctx->cmac.c, ctx->cmac.c, ctx->key), ctx->blocks++;
i = 0;
} while (alen);
}
/* Finally you encrypt or decrypt the message */
/*
* counter part of nonce may not be larger than L*8 bits, L is not larger
* than 8, therefore 64-bit counter...
*/
static void ctr64_inc(unsigned char *counter)
{
unsigned int n = 8;
u8 c;
counter += 8;
do {
--n;
c = counter[n];
++c;
counter[n] = c;
if (c)
return;
} while (n);
}
int CRYPTO_ccm128_encrypt(CCM128_CONTEXT *ctx,
const unsigned char *inp, unsigned char *out,
size_t len)
{
size_t n;
unsigned int i, L;
unsigned char flags0 = ctx->nonce.c[0];
block128_f block = ctx->block;
void *key = ctx->key;
union {
u64 u[2];
u8 c[16];
} scratch;
if (!(flags0 & 0x40))
(*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
ctx->nonce.c[0] = L = flags0 & 7;
for (n = 0, i = 15 - L; i < 15; ++i) {
n |= ctx->nonce.c[i];
ctx->nonce.c[i] = 0;
n <<= 8;
}
n |= ctx->nonce.c[15]; /* reconstructed length */
ctx->nonce.c[15] = 1;
if (n != len)
return -1; /* length mismatch */
ctx->blocks += ((len + 15) >> 3) | 1;
if (ctx->blocks > (U64(1) << 61))
return -2; /* too much data */
while (len >= 16) {
#if defined(STRICT_ALIGNMENT)
union {
u64 u[2];
u8 c[16];
} temp;
memcpy(temp.c, inp, 16);
ctx->cmac.u[0] ^= temp.u[0];
ctx->cmac.u[1] ^= temp.u[1];
#else
ctx->cmac.u[0] ^= ((u64 *)inp)[0];
ctx->cmac.u[1] ^= ((u64 *)inp)[1];
#endif
(*block) (ctx->cmac.c, ctx->cmac.c, key);
(*block) (ctx->nonce.c, scratch.c, key);
ctr64_inc(ctx->nonce.c);
#if defined(STRICT_ALIGNMENT)
temp.u[0] ^= scratch.u[0];
temp.u[1] ^= scratch.u[1];
memcpy(out, temp.c, 16);
#else
((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0];
((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1];
#endif
inp += 16;
out += 16;
len -= 16;
}
if (len) {
for (i = 0; i < len; ++i)
ctx->cmac.c[i] ^= inp[i];
(*block) (ctx->cmac.c, ctx->cmac.c, key);
(*block) (ctx->nonce.c, scratch.c, key);
for (i = 0; i < len; ++i)
out[i] = scratch.c[i] ^ inp[i];
}
for (i = 15 - L; i < 16; ++i)
ctx->nonce.c[i] = 0;
(*block) (ctx->nonce.c, scratch.c, key);
ctx->cmac.u[0] ^= scratch.u[0];
ctx->cmac.u[1] ^= scratch.u[1];
ctx->nonce.c[0] = flags0;
return 0;
}
int CRYPTO_ccm128_decrypt(CCM128_CONTEXT *ctx,
const unsigned char *inp, unsigned char *out,
size_t len)
{
size_t n;
unsigned int i, L;
unsigned char flags0 = ctx->nonce.c[0];
block128_f block = ctx->block;
void *key = ctx->key;
union {
u64 u[2];
u8 c[16];
} scratch;
if (!(flags0 & 0x40))
(*block) (ctx->nonce.c, ctx->cmac.c, key);
ctx->nonce.c[0] = L = flags0 & 7;
for (n = 0, i = 15 - L; i < 15; ++i) {
n |= ctx->nonce.c[i];
ctx->nonce.c[i] = 0;
n <<= 8;
}
n |= ctx->nonce.c[15]; /* reconstructed length */
ctx->nonce.c[15] = 1;
if (n != len)
return -1;
while (len >= 16) {
#if defined(STRICT_ALIGNMENT)
union {
u64 u[2];
u8 c[16];
} temp;
#endif
(*block) (ctx->nonce.c, scratch.c, key);
ctr64_inc(ctx->nonce.c);
#if defined(STRICT_ALIGNMENT)
memcpy(temp.c, inp, 16);
ctx->cmac.u[0] ^= (scratch.u[0] ^= temp.u[0]);
ctx->cmac.u[1] ^= (scratch.u[1] ^= temp.u[1]);
memcpy(out, scratch.c, 16);
#else
ctx->cmac.u[0] ^= (((u64 *)out)[0] = scratch.u[0] ^ ((u64 *)inp)[0]);
ctx->cmac.u[1] ^= (((u64 *)out)[1] = scratch.u[1] ^ ((u64 *)inp)[1]);
#endif
(*block) (ctx->cmac.c, ctx->cmac.c, key);
inp += 16;
out += 16;
len -= 16;
}
if (len) {
(*block) (ctx->nonce.c, scratch.c, key);
for (i = 0; i < len; ++i)
ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
(*block) (ctx->cmac.c, ctx->cmac.c, key);
}
for (i = 15 - L; i < 16; ++i)
ctx->nonce.c[i] = 0;
(*block) (ctx->nonce.c, scratch.c, key);
ctx->cmac.u[0] ^= scratch.u[0];
ctx->cmac.u[1] ^= scratch.u[1];
ctx->nonce.c[0] = flags0;
return 0;
}
static void ctr64_add(unsigned char *counter, size_t inc)
{
size_t n = 8, val = 0;
counter += 8;
do {
--n;
val += counter[n] + (inc & 0xff);
counter[n] = (unsigned char)val;
val >>= 8; /* carry bit */
inc >>= 8;
} while (n && (inc || val));
}
int CRYPTO_ccm128_encrypt_ccm64(CCM128_CONTEXT *ctx,
const unsigned char *inp, unsigned char *out,
size_t len, ccm128_f stream)
{
size_t n;
unsigned int i, L;
unsigned char flags0 = ctx->nonce.c[0];
block128_f block = ctx->block;
void *key = ctx->key;
union {
u64 u[2];
u8 c[16];
} scratch;
if (!(flags0 & 0x40))
(*block) (ctx->nonce.c, ctx->cmac.c, key), ctx->blocks++;
ctx->nonce.c[0] = L = flags0 & 7;
for (n = 0, i = 15 - L; i < 15; ++i) {
n |= ctx->nonce.c[i];
ctx->nonce.c[i] = 0;
n <<= 8;
}
n |= ctx->nonce.c[15]; /* reconstructed length */
ctx->nonce.c[15] = 1;
if (n != len)
return -1; /* length mismatch */
ctx->blocks += ((len + 15) >> 3) | 1;
if (ctx->blocks > (U64(1) << 61))
return -2; /* too much data */
if ((n = len / 16)) {
(*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
n *= 16;
inp += n;
out += n;
len -= n;
if (len)
ctr64_add(ctx->nonce.c, n / 16);
}
if (len) {
for (i = 0; i < len; ++i)
ctx->cmac.c[i] ^= inp[i];
(*block) (ctx->cmac.c, ctx->cmac.c, key);
(*block) (ctx->nonce.c, scratch.c, key);
for (i = 0; i < len; ++i)
out[i] = scratch.c[i] ^ inp[i];
}
for (i = 15 - L; i < 16; ++i)
ctx->nonce.c[i] = 0;
(*block) (ctx->nonce.c, scratch.c, key);
ctx->cmac.u[0] ^= scratch.u[0];
ctx->cmac.u[1] ^= scratch.u[1];
ctx->nonce.c[0] = flags0;
return 0;
}
int CRYPTO_ccm128_decrypt_ccm64(CCM128_CONTEXT *ctx,
const unsigned char *inp, unsigned char *out,
size_t len, ccm128_f stream)
{
size_t n;
unsigned int i, L;
unsigned char flags0 = ctx->nonce.c[0];
block128_f block = ctx->block;
void *key = ctx->key;
union {
u64 u[2];
u8 c[16];
} scratch;
if (!(flags0 & 0x40))
(*block) (ctx->nonce.c, ctx->cmac.c, key);
ctx->nonce.c[0] = L = flags0 & 7;
for (n = 0, i = 15 - L; i < 15; ++i) {
n |= ctx->nonce.c[i];
ctx->nonce.c[i] = 0;
n <<= 8;
}
n |= ctx->nonce.c[15]; /* reconstructed length */
ctx->nonce.c[15] = 1;
if (n != len)
return -1;
if ((n = len / 16)) {
(*stream) (inp, out, n, key, ctx->nonce.c, ctx->cmac.c);
n *= 16;
inp += n;
out += n;
len -= n;
if (len)
ctr64_add(ctx->nonce.c, n / 16);
}
if (len) {
(*block) (ctx->nonce.c, scratch.c, key);
for (i = 0; i < len; ++i)
ctx->cmac.c[i] ^= (out[i] = scratch.c[i] ^ inp[i]);
(*block) (ctx->cmac.c, ctx->cmac.c, key);
}
for (i = 15 - L; i < 16; ++i)
ctx->nonce.c[i] = 0;
(*block) (ctx->nonce.c, scratch.c, key);
ctx->cmac.u[0] ^= scratch.u[0];
ctx->cmac.u[1] ^= scratch.u[1];
ctx->nonce.c[0] = flags0;
return 0;
}
size_t CRYPTO_ccm128_tag(CCM128_CONTEXT *ctx, unsigned char *tag, size_t len)
{
unsigned int M = (ctx->nonce.c[0] >> 3) & 7; /* the M parameter */
M *= 2;
M += 2;
- if (len < M)
+ if (len != M)
return 0;
memcpy(tag, ctx->cmac.c, M);
return M;
}
diff --git a/crypto/o_str.c b/crypto/o_str.c
index a8357691ad66..1dbd70d58c4d 100644
--- a/crypto/o_str.c
+++ b/crypto/o_str.c
@@ -1,248 +1,267 @@
/*
- * Copyright 2003-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2003-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "e_os.h"
#include <limits.h>
#include <openssl/crypto.h>
#include "internal/cryptlib.h"
#include "internal/o_str.h"
int OPENSSL_memcmp(const void *v1, const void *v2, size_t n)
{
const unsigned char *c1 = v1, *c2 = v2;
int ret = 0;
while (n && (ret = *c1 - *c2) == 0)
n--, c1++, c2++;
return ret;
}
char *CRYPTO_strdup(const char *str, const char* file, int line)
{
char *ret;
if (str == NULL)
return NULL;
ret = CRYPTO_malloc(strlen(str) + 1, file, line);
if (ret != NULL)
strcpy(ret, str);
return ret;
}
char *CRYPTO_strndup(const char *str, size_t s, const char* file, int line)
{
size_t maxlen;
char *ret;
if (str == NULL)
return NULL;
maxlen = OPENSSL_strnlen(str, s);
ret = CRYPTO_malloc(maxlen + 1, file, line);
if (ret) {
memcpy(ret, str, maxlen);
ret[maxlen] = '\0';
}
return ret;
}
void *CRYPTO_memdup(const void *data, size_t siz, const char* file, int line)
{
void *ret;
if (data == NULL || siz >= INT_MAX)
return NULL;
ret = CRYPTO_malloc(siz, file, line);
if (ret == NULL) {
CRYPTOerr(CRYPTO_F_CRYPTO_MEMDUP, ERR_R_MALLOC_FAILURE);
return NULL;
}
return memcpy(ret, data, siz);
}
size_t OPENSSL_strnlen(const char *str, size_t maxlen)
{
const char *p;
for (p = str; maxlen-- != 0 && *p != '\0'; ++p) ;
return p - str;
}
size_t OPENSSL_strlcpy(char *dst, const char *src, size_t size)
{
size_t l = 0;
for (; size > 1 && *src; size--) {
*dst++ = *src++;
l++;
}
if (size)
*dst = '\0';
return l + strlen(src);
}
size_t OPENSSL_strlcat(char *dst, const char *src, size_t size)
{
size_t l = 0;
for (; size > 0 && *dst; size--, dst++)
l++;
return l + OPENSSL_strlcpy(dst, src, size);
}
int OPENSSL_hexchar2int(unsigned char c)
{
#ifdef CHARSET_EBCDIC
c = os_toebcdic[c];
#endif
switch (c) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'a': case 'A':
return 0x0A;
case 'b': case 'B':
return 0x0B;
case 'c': case 'C':
return 0x0C;
case 'd': case 'D':
return 0x0D;
case 'e': case 'E':
return 0x0E;
case 'f': case 'F':
return 0x0F;
}
return -1;
}
/*
* Give a string of hex digits convert to a buffer
*/
unsigned char *OPENSSL_hexstr2buf(const char *str, long *len)
{
unsigned char *hexbuf, *q;
unsigned char ch, cl;
int chi, cli;
const unsigned char *p;
size_t s;
s = strlen(str);
if ((hexbuf = OPENSSL_malloc(s >> 1)) == NULL) {
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, ERR_R_MALLOC_FAILURE);
return NULL;
}
for (p = (const unsigned char *)str, q = hexbuf; *p; ) {
ch = *p++;
if (ch == ':')
continue;
cl = *p++;
if (!cl) {
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF,
CRYPTO_R_ODD_NUMBER_OF_DIGITS);
OPENSSL_free(hexbuf);
return NULL;
}
cli = OPENSSL_hexchar2int(cl);
chi = OPENSSL_hexchar2int(ch);
if (cli < 0 || chi < 0) {
OPENSSL_free(hexbuf);
CRYPTOerr(CRYPTO_F_OPENSSL_HEXSTR2BUF, CRYPTO_R_ILLEGAL_HEX_DIGIT);
return NULL;
}
*q++ = (unsigned char)((chi << 4) | cli);
}
if (len)
*len = q - hexbuf;
return hexbuf;
}
/*
* Given a buffer of length 'len' return a OPENSSL_malloc'ed string with its
* hex representation @@@ (Contents of buffer are always kept in ASCII, also
* on EBCDIC machines)
*/
char *OPENSSL_buf2hexstr(const unsigned char *buffer, long len)
{
static const char hexdig[] = "0123456789ABCDEF";
char *tmp, *q;
const unsigned char *p;
int i;
if (len == 0)
{
return OPENSSL_zalloc(1);
}
if ((tmp = OPENSSL_malloc(len * 3)) == NULL) {
CRYPTOerr(CRYPTO_F_OPENSSL_BUF2HEXSTR, ERR_R_MALLOC_FAILURE);
return NULL;
}
q = tmp;
for (i = 0, p = buffer; i < len; i++, p++) {
*q++ = hexdig[(*p >> 4) & 0xf];
*q++ = hexdig[*p & 0xf];
*q++ = ':';
}
q[-1] = 0;
#ifdef CHARSET_EBCDIC
ebcdic2ascii(tmp, tmp, q - tmp - 1);
#endif
return tmp;
}
int openssl_strerror_r(int errnum, char *buf, size_t buflen)
{
#if defined(_MSC_VER) && _MSC_VER>=1400
return !strerror_s(buf, buflen, errnum);
#elif defined(_GNU_SOURCE)
- return strerror_r(errnum, buf, buflen) != NULL;
+ char *err;
+
+ /*
+ * GNU strerror_r may not actually set buf.
+ * It can return a pointer to some (immutable) static string in which case
+ * buf is left unused.
+ */
+ err = strerror_r(errnum, buf, buflen);
+ if (err == NULL)
+ return 0;
+ /*
+ * If err is statically allocated, err != buf and we need to copy the data.
+ * If err points somewhere inside buf, OPENSSL_strlcpy can handle this,
+ * since src and dest are not annotated with __restrict and the function
+ * reads src byte for byte and writes to dest.
+ * If err == buf we do not have to copy anything.
+ */
+ if (err != buf)
+ OPENSSL_strlcpy(buf, err, buflen);
+ return 1;
#elif (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L) || \
(defined(_XOPEN_SOURCE) && _XOPEN_SOURCE >= 600)
/*
* We can use "real" strerror_r. The OpenSSL version differs in that it
* gives 1 on success and 0 on failure for consistency with other OpenSSL
* functions. Real strerror_r does it the other way around
*/
return !strerror_r(errnum, buf, buflen);
#else
char *err;
+
/* Fall back to non-thread safe strerror()...its all we can do */
if (buflen < 2)
return 0;
err = strerror(errnum);
/* Can this ever happen? */
if (err == NULL)
return 0;
- strncpy(buf, err, buflen - 1);
- buf[buflen - 1] = '\0';
+ OPENSSL_strlcpy(buf, err, buflen);
return 1;
#endif
}
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
index 9ab1a14b9e32..ea91db660b65 100644
--- a/crypto/objects/obj_dat.h
+++ b/crypto/objects/obj_dat.h
@@ -1,5733 +1,5733 @@
/*
* WARNING: do not edit!
* Generated by crypto/objects/obj_dat.pl
*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* Serialized OID's */
static const unsigned char so[7762] = {
0x2A,0x86,0x48,0x86,0xF7,0x0D, /* [ 0] OBJ_rsadsi */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01, /* [ 6] OBJ_pkcs */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x02, /* [ 13] OBJ_md2 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x05, /* [ 21] OBJ_md5 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x04, /* [ 29] OBJ_rc4 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x01, /* [ 37] OBJ_rsaEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x02, /* [ 46] OBJ_md2WithRSAEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x04, /* [ 55] OBJ_md5WithRSAEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x01, /* [ 64] OBJ_pbeWithMD2AndDES_CBC */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x03, /* [ 73] OBJ_pbeWithMD5AndDES_CBC */
0x55, /* [ 82] OBJ_X500 */
0x55,0x04, /* [ 83] OBJ_X509 */
0x55,0x04,0x03, /* [ 85] OBJ_commonName */
0x55,0x04,0x06, /* [ 88] OBJ_countryName */
0x55,0x04,0x07, /* [ 91] OBJ_localityName */
0x55,0x04,0x08, /* [ 94] OBJ_stateOrProvinceName */
0x55,0x04,0x0A, /* [ 97] OBJ_organizationName */
0x55,0x04,0x0B, /* [ 100] OBJ_organizationalUnitName */
0x55,0x08,0x01,0x01, /* [ 103] OBJ_rsa */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07, /* [ 107] OBJ_pkcs7 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x01, /* [ 115] OBJ_pkcs7_data */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x02, /* [ 124] OBJ_pkcs7_signed */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x03, /* [ 133] OBJ_pkcs7_enveloped */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x04, /* [ 142] OBJ_pkcs7_signedAndEnveloped */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x05, /* [ 151] OBJ_pkcs7_digest */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x07,0x06, /* [ 160] OBJ_pkcs7_encrypted */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03, /* [ 169] OBJ_pkcs3 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x03,0x01, /* [ 177] OBJ_dhKeyAgreement */
0x2B,0x0E,0x03,0x02,0x06, /* [ 186] OBJ_des_ecb */
0x2B,0x0E,0x03,0x02,0x09, /* [ 191] OBJ_des_cfb64 */
0x2B,0x0E,0x03,0x02,0x07, /* [ 196] OBJ_des_cbc */
0x2B,0x0E,0x03,0x02,0x11, /* [ 201] OBJ_des_ede_ecb */
0x2B,0x06,0x01,0x04,0x01,0x81,0x3C,0x07,0x01,0x01,0x02, /* [ 206] OBJ_idea_cbc */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x02, /* [ 217] OBJ_rc2_cbc */
0x2B,0x0E,0x03,0x02,0x12, /* [ 225] OBJ_sha */
0x2B,0x0E,0x03,0x02,0x0F, /* [ 230] OBJ_shaWithRSAEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x07, /* [ 235] OBJ_des_ede3_cbc */
0x2B,0x0E,0x03,0x02,0x08, /* [ 243] OBJ_des_ofb64 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09, /* [ 248] OBJ_pkcs9 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x01, /* [ 256] OBJ_pkcs9_emailAddress */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x02, /* [ 265] OBJ_pkcs9_unstructuredName */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x03, /* [ 274] OBJ_pkcs9_contentType */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x04, /* [ 283] OBJ_pkcs9_messageDigest */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x05, /* [ 292] OBJ_pkcs9_signingTime */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x06, /* [ 301] OBJ_pkcs9_countersignature */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x07, /* [ 310] OBJ_pkcs9_challengePassword */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x08, /* [ 319] OBJ_pkcs9_unstructuredAddress */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x09, /* [ 328] OBJ_pkcs9_extCertAttributes */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42, /* [ 337] OBJ_netscape */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01, /* [ 344] OBJ_netscape_cert_extension */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02, /* [ 352] OBJ_netscape_data_type */
0x2B,0x0E,0x03,0x02,0x1A, /* [ 360] OBJ_sha1 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x05, /* [ 365] OBJ_sha1WithRSAEncryption */
0x2B,0x0E,0x03,0x02,0x0D, /* [ 374] OBJ_dsaWithSHA */
0x2B,0x0E,0x03,0x02,0x0C, /* [ 379] OBJ_dsa_2 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0B, /* [ 384] OBJ_pbeWithSHA1AndRC2_CBC */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0C, /* [ 393] OBJ_id_pbkdf2 */
0x2B,0x0E,0x03,0x02,0x1B, /* [ 402] OBJ_dsaWithSHA1_2 */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x01, /* [ 407] OBJ_netscape_cert_type */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x02, /* [ 416] OBJ_netscape_base_url */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x03, /* [ 425] OBJ_netscape_revocation_url */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x04, /* [ 434] OBJ_netscape_ca_revocation_url */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x07, /* [ 443] OBJ_netscape_renewal_url */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x08, /* [ 452] OBJ_netscape_ca_policy_url */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0C, /* [ 461] OBJ_netscape_ssl_server_name */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x01,0x0D, /* [ 470] OBJ_netscape_comment */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x02,0x05, /* [ 479] OBJ_netscape_cert_sequence */
0x55,0x1D, /* [ 488] OBJ_id_ce */
0x55,0x1D,0x0E, /* [ 490] OBJ_subject_key_identifier */
0x55,0x1D,0x0F, /* [ 493] OBJ_key_usage */
0x55,0x1D,0x10, /* [ 496] OBJ_private_key_usage_period */
0x55,0x1D,0x11, /* [ 499] OBJ_subject_alt_name */
0x55,0x1D,0x12, /* [ 502] OBJ_issuer_alt_name */
0x55,0x1D,0x13, /* [ 505] OBJ_basic_constraints */
0x55,0x1D,0x14, /* [ 508] OBJ_crl_number */
0x55,0x1D,0x20, /* [ 511] OBJ_certificate_policies */
0x55,0x1D,0x23, /* [ 514] OBJ_authority_key_identifier */
0x2B,0x06,0x01,0x04,0x01,0x97,0x55,0x01,0x02, /* [ 517] OBJ_bf_cbc */
0x55,0x08,0x03,0x65, /* [ 526] OBJ_mdc2 */
0x55,0x08,0x03,0x64, /* [ 530] OBJ_mdc2WithRSA */
0x55,0x04,0x2A, /* [ 534] OBJ_givenName */
0x55,0x04,0x04, /* [ 537] OBJ_surname */
0x55,0x04,0x2B, /* [ 540] OBJ_initials */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2C, /* [ 543] OBJ_uniqueIdentifier */
0x55,0x1D,0x1F, /* [ 553] OBJ_crl_distribution_points */
0x2B,0x0E,0x03,0x02,0x03, /* [ 556] OBJ_md5WithRSA */
0x55,0x04,0x05, /* [ 561] OBJ_serialNumber */
0x55,0x04,0x0C, /* [ 564] OBJ_title */
0x55,0x04,0x0D, /* [ 567] OBJ_description */
0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0A, /* [ 570] OBJ_cast5_cbc */
0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0C, /* [ 579] OBJ_pbeWithMD5AndCast5_CBC */
0x2A,0x86,0x48,0xCE,0x38,0x04,0x03, /* [ 588] OBJ_dsaWithSHA1 */
0x2B,0x0E,0x03,0x02,0x1D, /* [ 595] OBJ_sha1WithRSA */
0x2A,0x86,0x48,0xCE,0x38,0x04,0x01, /* [ 600] OBJ_dsa */
0x2B,0x24,0x03,0x02,0x01, /* [ 607] OBJ_ripemd160 */
0x2B,0x24,0x03,0x03,0x01,0x02, /* [ 612] OBJ_ripemd160WithRSA */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x08, /* [ 618] OBJ_rc5_cbc */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x08, /* [ 626] OBJ_zlib_compression */
0x55,0x1D,0x25, /* [ 637] OBJ_ext_key_usage */
0x2B,0x06,0x01,0x05,0x05,0x07, /* [ 640] OBJ_id_pkix */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03, /* [ 646] OBJ_id_kp */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x01, /* [ 653] OBJ_server_auth */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x02, /* [ 661] OBJ_client_auth */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x03, /* [ 669] OBJ_code_sign */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x04, /* [ 677] OBJ_email_protect */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x08, /* [ 685] OBJ_time_stamp */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x15, /* [ 693] OBJ_ms_code_ind */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x16, /* [ 703] OBJ_ms_code_com */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x01, /* [ 713] OBJ_ms_ctl_sign */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x03, /* [ 723] OBJ_ms_sgc */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x0A,0x03,0x04, /* [ 733] OBJ_ms_efs */
0x60,0x86,0x48,0x01,0x86,0xF8,0x42,0x04,0x01, /* [ 743] OBJ_ns_sgc */
0x55,0x1D,0x1B, /* [ 752] OBJ_delta_crl */
0x55,0x1D,0x15, /* [ 755] OBJ_crl_reason */
0x55,0x1D,0x18, /* [ 758] OBJ_invalidity_date */
0x2B,0x65,0x01,0x04,0x01, /* [ 761] OBJ_sxnet */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x01, /* [ 766] OBJ_pbe_WithSHA1And128BitRC4 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x02, /* [ 776] OBJ_pbe_WithSHA1And40BitRC4 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x03, /* [ 786] OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x04, /* [ 796] OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x05, /* [ 806] OBJ_pbe_WithSHA1And128BitRC2_CBC */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x01,0x06, /* [ 816] OBJ_pbe_WithSHA1And40BitRC2_CBC */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x01, /* [ 826] OBJ_keyBag */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x02, /* [ 837] OBJ_pkcs8ShroudedKeyBag */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x03, /* [ 848] OBJ_certBag */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x04, /* [ 859] OBJ_crlBag */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x05, /* [ 870] OBJ_secretBag */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x0C,0x0A,0x01,0x06, /* [ 881] OBJ_safeContentsBag */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x14, /* [ 892] OBJ_friendlyName */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x15, /* [ 901] OBJ_localKeyID */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x16,0x01, /* [ 910] OBJ_x509Certificate */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x16,0x02, /* [ 920] OBJ_sdsiCertificate */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x17,0x01, /* [ 930] OBJ_x509Crl */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0D, /* [ 940] OBJ_pbes2 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0E, /* [ 949] OBJ_pbmac1 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x07, /* [ 958] OBJ_hmacWithSHA1 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x01, /* [ 966] OBJ_id_qt_cps */
0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x02, /* [ 974] OBJ_id_qt_unotice */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x0F, /* [ 982] OBJ_SMIMECapabilities */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x04, /* [ 991] OBJ_pbeWithMD2AndRC2_CBC */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x06, /* [ 1000] OBJ_pbeWithMD5AndRC2_CBC */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05,0x0A, /* [ 1009] OBJ_pbeWithSHA1AndDES_CBC */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x02,0x01,0x0E, /* [ 1018] OBJ_ms_ext_req */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x0E, /* [ 1028] OBJ_ext_req */
0x55,0x04,0x29, /* [ 1037] OBJ_name */
0x55,0x04,0x2E, /* [ 1040] OBJ_dnQualifier */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01, /* [ 1043] OBJ_id_pe */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30, /* [ 1050] OBJ_id_ad */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x01, /* [ 1057] OBJ_info_access */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01, /* [ 1065] OBJ_ad_OCSP */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x02, /* [ 1073] OBJ_ad_ca_issuers */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x09, /* [ 1081] OBJ_OCSP_sign */
0x2A, /* [ 1089] OBJ_member_body */
0x2A,0x86,0x48, /* [ 1090] OBJ_ISO_US */
0x2A,0x86,0x48,0xCE,0x38, /* [ 1093] OBJ_X9_57 */
0x2A,0x86,0x48,0xCE,0x38,0x04, /* [ 1098] OBJ_X9cm */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01, /* [ 1104] OBJ_pkcs1 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x05, /* [ 1112] OBJ_pkcs5 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10, /* [ 1120] OBJ_SMIME */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00, /* [ 1129] OBJ_id_smime_mod */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01, /* [ 1139] OBJ_id_smime_ct */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02, /* [ 1149] OBJ_id_smime_aa */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03, /* [ 1159] OBJ_id_smime_alg */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x04, /* [ 1169] OBJ_id_smime_cd */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05, /* [ 1179] OBJ_id_smime_spq */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06, /* [ 1189] OBJ_id_smime_cti */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x01, /* [ 1199] OBJ_id_smime_mod_cms */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x02, /* [ 1210] OBJ_id_smime_mod_ess */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x03, /* [ 1221] OBJ_id_smime_mod_oid */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x04, /* [ 1232] OBJ_id_smime_mod_msg_v3 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x05, /* [ 1243] OBJ_id_smime_mod_ets_eSignature_88 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x06, /* [ 1254] OBJ_id_smime_mod_ets_eSignature_97 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x07, /* [ 1265] OBJ_id_smime_mod_ets_eSigPolicy_88 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x00,0x08, /* [ 1276] OBJ_id_smime_mod_ets_eSigPolicy_97 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x01, /* [ 1287] OBJ_id_smime_ct_receipt */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x02, /* [ 1298] OBJ_id_smime_ct_authData */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x03, /* [ 1309] OBJ_id_smime_ct_publishCert */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x04, /* [ 1320] OBJ_id_smime_ct_TSTInfo */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x05, /* [ 1331] OBJ_id_smime_ct_TDTInfo */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x06, /* [ 1342] OBJ_id_smime_ct_contentInfo */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x07, /* [ 1353] OBJ_id_smime_ct_DVCSRequestData */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x08, /* [ 1364] OBJ_id_smime_ct_DVCSResponseData */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x01, /* [ 1375] OBJ_id_smime_aa_receiptRequest */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x02, /* [ 1386] OBJ_id_smime_aa_securityLabel */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x03, /* [ 1397] OBJ_id_smime_aa_mlExpandHistory */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x04, /* [ 1408] OBJ_id_smime_aa_contentHint */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x05, /* [ 1419] OBJ_id_smime_aa_msgSigDigest */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x06, /* [ 1430] OBJ_id_smime_aa_encapContentType */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x07, /* [ 1441] OBJ_id_smime_aa_contentIdentifier */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x08, /* [ 1452] OBJ_id_smime_aa_macValue */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x09, /* [ 1463] OBJ_id_smime_aa_equivalentLabels */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0A, /* [ 1474] OBJ_id_smime_aa_contentReference */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0B, /* [ 1485] OBJ_id_smime_aa_encrypKeyPref */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0C, /* [ 1496] OBJ_id_smime_aa_signingCertificate */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0D, /* [ 1507] OBJ_id_smime_aa_smimeEncryptCerts */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0E, /* [ 1518] OBJ_id_smime_aa_timeStampToken */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x0F, /* [ 1529] OBJ_id_smime_aa_ets_sigPolicyId */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x10, /* [ 1540] OBJ_id_smime_aa_ets_commitmentType */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x11, /* [ 1551] OBJ_id_smime_aa_ets_signerLocation */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x12, /* [ 1562] OBJ_id_smime_aa_ets_signerAttr */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x13, /* [ 1573] OBJ_id_smime_aa_ets_otherSigCert */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x14, /* [ 1584] OBJ_id_smime_aa_ets_contentTimestamp */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x15, /* [ 1595] OBJ_id_smime_aa_ets_CertificateRefs */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x16, /* [ 1606] OBJ_id_smime_aa_ets_RevocationRefs */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x17, /* [ 1617] OBJ_id_smime_aa_ets_certValues */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x18, /* [ 1628] OBJ_id_smime_aa_ets_revocationValues */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x19, /* [ 1639] OBJ_id_smime_aa_ets_escTimeStamp */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1A, /* [ 1650] OBJ_id_smime_aa_ets_certCRLTimestamp */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1B, /* [ 1661] OBJ_id_smime_aa_ets_archiveTimeStamp */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1C, /* [ 1672] OBJ_id_smime_aa_signatureType */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x1D, /* [ 1683] OBJ_id_smime_aa_dvcs_dvc */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x01, /* [ 1694] OBJ_id_smime_alg_ESDHwith3DES */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x02, /* [ 1705] OBJ_id_smime_alg_ESDHwithRC2 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x03, /* [ 1716] OBJ_id_smime_alg_3DESwrap */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x04, /* [ 1727] OBJ_id_smime_alg_RC2wrap */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x05, /* [ 1738] OBJ_id_smime_alg_ESDH */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x06, /* [ 1749] OBJ_id_smime_alg_CMS3DESwrap */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x07, /* [ 1760] OBJ_id_smime_alg_CMSRC2wrap */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x04,0x01, /* [ 1771] OBJ_id_smime_cd_ldap */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,0x01, /* [ 1782] OBJ_id_smime_spq_ets_sqt_uri */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x05,0x02, /* [ 1793] OBJ_id_smime_spq_ets_sqt_unotice */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x01, /* [ 1804] OBJ_id_smime_cti_ets_proofOfOrigin */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x02, /* [ 1815] OBJ_id_smime_cti_ets_proofOfReceipt */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x03, /* [ 1826] OBJ_id_smime_cti_ets_proofOfDelivery */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x04, /* [ 1837] OBJ_id_smime_cti_ets_proofOfSender */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x05, /* [ 1848] OBJ_id_smime_cti_ets_proofOfApproval */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x06,0x06, /* [ 1859] OBJ_id_smime_cti_ets_proofOfCreation */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x04, /* [ 1870] OBJ_md4 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00, /* [ 1878] OBJ_id_pkix_mod */
0x2B,0x06,0x01,0x05,0x05,0x07,0x02, /* [ 1885] OBJ_id_qt */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04, /* [ 1892] OBJ_id_it */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05, /* [ 1899] OBJ_id_pkip */
0x2B,0x06,0x01,0x05,0x05,0x07,0x06, /* [ 1906] OBJ_id_alg */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07, /* [ 1913] OBJ_id_cmc */
0x2B,0x06,0x01,0x05,0x05,0x07,0x08, /* [ 1920] OBJ_id_on */
0x2B,0x06,0x01,0x05,0x05,0x07,0x09, /* [ 1927] OBJ_id_pda */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0A, /* [ 1934] OBJ_id_aca */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0B, /* [ 1941] OBJ_id_qcs */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0C, /* [ 1948] OBJ_id_cct */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x01, /* [ 1955] OBJ_id_pkix1_explicit_88 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x02, /* [ 1963] OBJ_id_pkix1_implicit_88 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x03, /* [ 1971] OBJ_id_pkix1_explicit_93 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x04, /* [ 1979] OBJ_id_pkix1_implicit_93 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x05, /* [ 1987] OBJ_id_mod_crmf */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x06, /* [ 1995] OBJ_id_mod_cmc */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x07, /* [ 2003] OBJ_id_mod_kea_profile_88 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x08, /* [ 2011] OBJ_id_mod_kea_profile_93 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x09, /* [ 2019] OBJ_id_mod_cmp */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0A, /* [ 2027] OBJ_id_mod_qualified_cert_88 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0B, /* [ 2035] OBJ_id_mod_qualified_cert_93 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0C, /* [ 2043] OBJ_id_mod_attribute_cert */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0D, /* [ 2051] OBJ_id_mod_timestamp_protocol */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0E, /* [ 2059] OBJ_id_mod_ocsp */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x0F, /* [ 2067] OBJ_id_mod_dvcs */
0x2B,0x06,0x01,0x05,0x05,0x07,0x00,0x10, /* [ 2075] OBJ_id_mod_cmp2000 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x02, /* [ 2083] OBJ_biometricInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x03, /* [ 2091] OBJ_qcStatements */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x04, /* [ 2099] OBJ_ac_auditEntity */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x05, /* [ 2107] OBJ_ac_targeting */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x06, /* [ 2115] OBJ_aaControls */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x07, /* [ 2123] OBJ_sbgp_ipAddrBlock */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x08, /* [ 2131] OBJ_sbgp_autonomousSysNum */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x09, /* [ 2139] OBJ_sbgp_routerIdentifier */
0x2B,0x06,0x01,0x05,0x05,0x07,0x02,0x03, /* [ 2147] OBJ_textNotice */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x05, /* [ 2155] OBJ_ipsecEndSystem */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x06, /* [ 2163] OBJ_ipsecTunnel */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x07, /* [ 2171] OBJ_ipsecUser */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x0A, /* [ 2179] OBJ_dvcs */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x01, /* [ 2187] OBJ_id_it_caProtEncCert */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x02, /* [ 2195] OBJ_id_it_signKeyPairTypes */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x03, /* [ 2203] OBJ_id_it_encKeyPairTypes */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x04, /* [ 2211] OBJ_id_it_preferredSymmAlg */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x05, /* [ 2219] OBJ_id_it_caKeyUpdateInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x06, /* [ 2227] OBJ_id_it_currentCRL */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x07, /* [ 2235] OBJ_id_it_unsupportedOIDs */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x08, /* [ 2243] OBJ_id_it_subscriptionRequest */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x09, /* [ 2251] OBJ_id_it_subscriptionResponse */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0A, /* [ 2259] OBJ_id_it_keyPairParamReq */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0B, /* [ 2267] OBJ_id_it_keyPairParamRep */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0C, /* [ 2275] OBJ_id_it_revPassphrase */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0D, /* [ 2283] OBJ_id_it_implicitConfirm */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0E, /* [ 2291] OBJ_id_it_confirmWaitTime */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x0F, /* [ 2299] OBJ_id_it_origPKIMessage */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01, /* [ 2307] OBJ_id_regCtrl */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02, /* [ 2315] OBJ_id_regInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x01, /* [ 2323] OBJ_id_regCtrl_regToken */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x02, /* [ 2332] OBJ_id_regCtrl_authenticator */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x03, /* [ 2341] OBJ_id_regCtrl_pkiPublicationInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x04, /* [ 2350] OBJ_id_regCtrl_pkiArchiveOptions */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x05, /* [ 2359] OBJ_id_regCtrl_oldCertID */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x01,0x06, /* [ 2368] OBJ_id_regCtrl_protocolEncrKey */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,0x01, /* [ 2377] OBJ_id_regInfo_utf8Pairs */
0x2B,0x06,0x01,0x05,0x05,0x07,0x05,0x02,0x02, /* [ 2386] OBJ_id_regInfo_certReq */
0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x01, /* [ 2395] OBJ_id_alg_des40 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x02, /* [ 2403] OBJ_id_alg_noSignature */
0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x03, /* [ 2411] OBJ_id_alg_dh_sig_hmac_sha1 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x06,0x04, /* [ 2419] OBJ_id_alg_dh_pop */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x01, /* [ 2427] OBJ_id_cmc_statusInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x02, /* [ 2435] OBJ_id_cmc_identification */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x03, /* [ 2443] OBJ_id_cmc_identityProof */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x04, /* [ 2451] OBJ_id_cmc_dataReturn */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x05, /* [ 2459] OBJ_id_cmc_transactionId */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x06, /* [ 2467] OBJ_id_cmc_senderNonce */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x07, /* [ 2475] OBJ_id_cmc_recipientNonce */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x08, /* [ 2483] OBJ_id_cmc_addExtensions */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x09, /* [ 2491] OBJ_id_cmc_encryptedPOP */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0A, /* [ 2499] OBJ_id_cmc_decryptedPOP */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0B, /* [ 2507] OBJ_id_cmc_lraPOPWitness */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x0F, /* [ 2515] OBJ_id_cmc_getCert */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x10, /* [ 2523] OBJ_id_cmc_getCRL */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x11, /* [ 2531] OBJ_id_cmc_revokeRequest */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x12, /* [ 2539] OBJ_id_cmc_regInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x13, /* [ 2547] OBJ_id_cmc_responseInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x15, /* [ 2555] OBJ_id_cmc_queryPending */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x16, /* [ 2563] OBJ_id_cmc_popLinkRandom */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x17, /* [ 2571] OBJ_id_cmc_popLinkWitness */
0x2B,0x06,0x01,0x05,0x05,0x07,0x07,0x18, /* [ 2579] OBJ_id_cmc_confirmCertAcceptance */
0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x01, /* [ 2587] OBJ_id_on_personalData */
0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x01, /* [ 2595] OBJ_id_pda_dateOfBirth */
0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x02, /* [ 2603] OBJ_id_pda_placeOfBirth */
0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x03, /* [ 2611] OBJ_id_pda_gender */
0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x04, /* [ 2619] OBJ_id_pda_countryOfCitizenship */
0x2B,0x06,0x01,0x05,0x05,0x07,0x09,0x05, /* [ 2627] OBJ_id_pda_countryOfResidence */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x01, /* [ 2635] OBJ_id_aca_authenticationInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x02, /* [ 2643] OBJ_id_aca_accessIdentity */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x03, /* [ 2651] OBJ_id_aca_chargingIdentity */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x04, /* [ 2659] OBJ_id_aca_group */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x05, /* [ 2667] OBJ_id_aca_role */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0B,0x01, /* [ 2675] OBJ_id_qcs_pkixQCSyntax_v1 */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x01, /* [ 2683] OBJ_id_cct_crs */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x02, /* [ 2691] OBJ_id_cct_PKIData */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0C,0x03, /* [ 2699] OBJ_id_cct_PKIResponse */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x03, /* [ 2707] OBJ_ad_timeStamping */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x04, /* [ 2715] OBJ_ad_dvcs */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x01, /* [ 2723] OBJ_id_pkix_OCSP_basic */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x02, /* [ 2732] OBJ_id_pkix_OCSP_Nonce */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x03, /* [ 2741] OBJ_id_pkix_OCSP_CrlID */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x04, /* [ 2750] OBJ_id_pkix_OCSP_acceptableResponses */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x05, /* [ 2759] OBJ_id_pkix_OCSP_noCheck */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x06, /* [ 2768] OBJ_id_pkix_OCSP_archiveCutoff */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x07, /* [ 2777] OBJ_id_pkix_OCSP_serviceLocator */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x08, /* [ 2786] OBJ_id_pkix_OCSP_extendedStatus */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x09, /* [ 2795] OBJ_id_pkix_OCSP_valid */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x0A, /* [ 2804] OBJ_id_pkix_OCSP_path */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x0B, /* [ 2813] OBJ_id_pkix_OCSP_trustRoot */
0x2B,0x0E,0x03,0x02, /* [ 2822] OBJ_algorithm */
0x2B,0x0E,0x03,0x02,0x0B, /* [ 2826] OBJ_rsaSignature */
0x55,0x08, /* [ 2831] OBJ_X500algorithms */
0x2B, /* [ 2833] OBJ_org */
0x2B,0x06, /* [ 2834] OBJ_dod */
0x2B,0x06,0x01, /* [ 2836] OBJ_iana */
0x2B,0x06,0x01,0x01, /* [ 2839] OBJ_Directory */
0x2B,0x06,0x01,0x02, /* [ 2843] OBJ_Management */
0x2B,0x06,0x01,0x03, /* [ 2847] OBJ_Experimental */
0x2B,0x06,0x01,0x04, /* [ 2851] OBJ_Private */
0x2B,0x06,0x01,0x05, /* [ 2855] OBJ_Security */
0x2B,0x06,0x01,0x06, /* [ 2859] OBJ_SNMPv2 */
0x2B,0x06,0x01,0x07, /* [ 2863] OBJ_Mail */
0x2B,0x06,0x01,0x04,0x01, /* [ 2867] OBJ_Enterprises */
0x2B,0x06,0x01,0x04,0x01,0x8B,0x3A,0x82,0x58, /* [ 2872] OBJ_dcObject */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x19, /* [ 2881] OBJ_domainComponent */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0D, /* [ 2891] OBJ_Domain */
0x55,0x01,0x05, /* [ 2901] OBJ_selected_attribute_types */
0x55,0x01,0x05,0x37, /* [ 2904] OBJ_clearance */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x03, /* [ 2908] OBJ_md4WithRSAEncryption */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0A, /* [ 2917] OBJ_ac_proxying */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0B, /* [ 2925] OBJ_sinfo_access */
0x2B,0x06,0x01,0x05,0x05,0x07,0x0A,0x06, /* [ 2933] OBJ_id_aca_encAttrs */
0x55,0x04,0x48, /* [ 2941] OBJ_role */
0x55,0x1D,0x24, /* [ 2944] OBJ_policy_constraints */
0x55,0x1D,0x37, /* [ 2947] OBJ_target_information */
0x55,0x1D,0x38, /* [ 2950] OBJ_no_rev_avail */
0x2A,0x86,0x48,0xCE,0x3D, /* [ 2953] OBJ_ansi_X9_62 */
0x2A,0x86,0x48,0xCE,0x3D,0x01,0x01, /* [ 2958] OBJ_X9_62_prime_field */
0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02, /* [ 2965] OBJ_X9_62_characteristic_two_field */
0x2A,0x86,0x48,0xCE,0x3D,0x02,0x01, /* [ 2972] OBJ_X9_62_id_ecPublicKey */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01, /* [ 2979] OBJ_X9_62_prime192v1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02, /* [ 2987] OBJ_X9_62_prime192v2 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03, /* [ 2995] OBJ_X9_62_prime192v3 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04, /* [ 3003] OBJ_X9_62_prime239v1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05, /* [ 3011] OBJ_X9_62_prime239v2 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06, /* [ 3019] OBJ_X9_62_prime239v3 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07, /* [ 3027] OBJ_X9_62_prime256v1 */
0x2A,0x86,0x48,0xCE,0x3D,0x04,0x01, /* [ 3035] OBJ_ecdsa_with_SHA1 */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x11,0x01, /* [ 3042] OBJ_ms_csp_name */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x01, /* [ 3051] OBJ_aes_128_ecb */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x02, /* [ 3060] OBJ_aes_128_cbc */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x03, /* [ 3069] OBJ_aes_128_ofb128 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x04, /* [ 3078] OBJ_aes_128_cfb128 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x15, /* [ 3087] OBJ_aes_192_ecb */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x16, /* [ 3096] OBJ_aes_192_cbc */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x17, /* [ 3105] OBJ_aes_192_ofb128 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x18, /* [ 3114] OBJ_aes_192_cfb128 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x29, /* [ 3123] OBJ_aes_256_ecb */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2A, /* [ 3132] OBJ_aes_256_cbc */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2B, /* [ 3141] OBJ_aes_256_ofb128 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2C, /* [ 3150] OBJ_aes_256_cfb128 */
0x55,0x1D,0x17, /* [ 3159] OBJ_hold_instruction_code */
0x2A,0x86,0x48,0xCE,0x38,0x02,0x01, /* [ 3162] OBJ_hold_instruction_none */
0x2A,0x86,0x48,0xCE,0x38,0x02,0x02, /* [ 3169] OBJ_hold_instruction_call_issuer */
0x2A,0x86,0x48,0xCE,0x38,0x02,0x03, /* [ 3176] OBJ_hold_instruction_reject */
0x09, /* [ 3183] OBJ_data */
0x09,0x92,0x26, /* [ 3184] OBJ_pss */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C, /* [ 3187] OBJ_ucl */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64, /* [ 3194] OBJ_pilot */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01, /* [ 3202] OBJ_pilotAttributeType */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03, /* [ 3211] OBJ_pilotAttributeSyntax */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04, /* [ 3220] OBJ_pilotObjectClass */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x0A, /* [ 3229] OBJ_pilotGroups */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,0x04, /* [ 3238] OBJ_iA5StringSyntax */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x03,0x05, /* [ 3248] OBJ_caseIgnoreIA5StringSyntax */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x03, /* [ 3258] OBJ_pilotObject */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x04, /* [ 3268] OBJ_pilotPerson */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x05, /* [ 3278] OBJ_account */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x06, /* [ 3288] OBJ_document */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x07, /* [ 3298] OBJ_room */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x09, /* [ 3308] OBJ_documentSeries */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0E, /* [ 3318] OBJ_rFC822localPart */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x0F, /* [ 3328] OBJ_dNSDomain */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x11, /* [ 3338] OBJ_domainRelatedObject */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x12, /* [ 3348] OBJ_friendlyCountry */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x13, /* [ 3358] OBJ_simpleSecurityObject */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x14, /* [ 3368] OBJ_pilotOrganization */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x15, /* [ 3378] OBJ_pilotDSA */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x04,0x16, /* [ 3388] OBJ_qualityLabelledData */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x01, /* [ 3398] OBJ_userId */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x02, /* [ 3408] OBJ_textEncodedORAddress */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x03, /* [ 3418] OBJ_rfc822Mailbox */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x04, /* [ 3428] OBJ_info */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x05, /* [ 3438] OBJ_favouriteDrink */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x06, /* [ 3448] OBJ_roomNumber */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x07, /* [ 3458] OBJ_photo */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x08, /* [ 3468] OBJ_userClass */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x09, /* [ 3478] OBJ_host */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0A, /* [ 3488] OBJ_manager */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0B, /* [ 3498] OBJ_documentIdentifier */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0C, /* [ 3508] OBJ_documentTitle */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0D, /* [ 3518] OBJ_documentVersion */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0E, /* [ 3528] OBJ_documentAuthor */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x0F, /* [ 3538] OBJ_documentLocation */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x14, /* [ 3548] OBJ_homeTelephoneNumber */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x15, /* [ 3558] OBJ_secretary */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x16, /* [ 3568] OBJ_otherMailbox */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x17, /* [ 3578] OBJ_lastModifiedTime */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x18, /* [ 3588] OBJ_lastModifiedBy */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1A, /* [ 3598] OBJ_aRecord */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1B, /* [ 3608] OBJ_pilotAttributeType27 */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1C, /* [ 3618] OBJ_mXRecord */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1D, /* [ 3628] OBJ_nSRecord */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1E, /* [ 3638] OBJ_sOARecord */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x1F, /* [ 3648] OBJ_cNAMERecord */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x25, /* [ 3658] OBJ_associatedDomain */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x26, /* [ 3668] OBJ_associatedName */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x27, /* [ 3678] OBJ_homePostalAddress */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x28, /* [ 3688] OBJ_personalTitle */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x29, /* [ 3698] OBJ_mobileTelephoneNumber */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2A, /* [ 3708] OBJ_pagerTelephoneNumber */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2B, /* [ 3718] OBJ_friendlyCountryName */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2D, /* [ 3728] OBJ_organizationalStatus */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2E, /* [ 3738] OBJ_janetMailbox */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x2F, /* [ 3748] OBJ_mailPreferenceOption */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x30, /* [ 3758] OBJ_buildingName */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x31, /* [ 3768] OBJ_dSAQuality */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x32, /* [ 3778] OBJ_singleLevelQuality */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x33, /* [ 3788] OBJ_subtreeMinimumQuality */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x34, /* [ 3798] OBJ_subtreeMaximumQuality */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x35, /* [ 3808] OBJ_personalSignature */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x36, /* [ 3818] OBJ_dITRedirect */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x37, /* [ 3828] OBJ_audio */
0x09,0x92,0x26,0x89,0x93,0xF2,0x2C,0x64,0x01,0x38, /* [ 3838] OBJ_documentPublisher */
0x55,0x04,0x2D, /* [ 3848] OBJ_x500UniqueIdentifier */
0x2B,0x06,0x01,0x07,0x01, /* [ 3851] OBJ_mime_mhs */
0x2B,0x06,0x01,0x07,0x01,0x01, /* [ 3856] OBJ_mime_mhs_headings */
0x2B,0x06,0x01,0x07,0x01,0x02, /* [ 3862] OBJ_mime_mhs_bodies */
0x2B,0x06,0x01,0x07,0x01,0x01,0x01, /* [ 3868] OBJ_id_hex_partial_message */
0x2B,0x06,0x01,0x07,0x01,0x01,0x02, /* [ 3875] OBJ_id_hex_multipart_message */
0x55,0x04,0x2C, /* [ 3882] OBJ_generationQualifier */
0x55,0x04,0x41, /* [ 3885] OBJ_pseudonym */
0x67,0x2A, /* [ 3888] OBJ_id_set */
0x67,0x2A,0x00, /* [ 3890] OBJ_set_ctype */
0x67,0x2A,0x01, /* [ 3893] OBJ_set_msgExt */
0x67,0x2A,0x03, /* [ 3896] OBJ_set_attr */
0x67,0x2A,0x05, /* [ 3899] OBJ_set_policy */
0x67,0x2A,0x07, /* [ 3902] OBJ_set_certExt */
0x67,0x2A,0x08, /* [ 3905] OBJ_set_brand */
0x67,0x2A,0x00,0x00, /* [ 3908] OBJ_setct_PANData */
0x67,0x2A,0x00,0x01, /* [ 3912] OBJ_setct_PANToken */
0x67,0x2A,0x00,0x02, /* [ 3916] OBJ_setct_PANOnly */
0x67,0x2A,0x00,0x03, /* [ 3920] OBJ_setct_OIData */
0x67,0x2A,0x00,0x04, /* [ 3924] OBJ_setct_PI */
0x67,0x2A,0x00,0x05, /* [ 3928] OBJ_setct_PIData */
0x67,0x2A,0x00,0x06, /* [ 3932] OBJ_setct_PIDataUnsigned */
0x67,0x2A,0x00,0x07, /* [ 3936] OBJ_setct_HODInput */
0x67,0x2A,0x00,0x08, /* [ 3940] OBJ_setct_AuthResBaggage */
0x67,0x2A,0x00,0x09, /* [ 3944] OBJ_setct_AuthRevReqBaggage */
0x67,0x2A,0x00,0x0A, /* [ 3948] OBJ_setct_AuthRevResBaggage */
0x67,0x2A,0x00,0x0B, /* [ 3952] OBJ_setct_CapTokenSeq */
0x67,0x2A,0x00,0x0C, /* [ 3956] OBJ_setct_PInitResData */
0x67,0x2A,0x00,0x0D, /* [ 3960] OBJ_setct_PI_TBS */
0x67,0x2A,0x00,0x0E, /* [ 3964] OBJ_setct_PResData */
0x67,0x2A,0x00,0x10, /* [ 3968] OBJ_setct_AuthReqTBS */
0x67,0x2A,0x00,0x11, /* [ 3972] OBJ_setct_AuthResTBS */
0x67,0x2A,0x00,0x12, /* [ 3976] OBJ_setct_AuthResTBSX */
0x67,0x2A,0x00,0x13, /* [ 3980] OBJ_setct_AuthTokenTBS */
0x67,0x2A,0x00,0x14, /* [ 3984] OBJ_setct_CapTokenData */
0x67,0x2A,0x00,0x15, /* [ 3988] OBJ_setct_CapTokenTBS */
0x67,0x2A,0x00,0x16, /* [ 3992] OBJ_setct_AcqCardCodeMsg */
0x67,0x2A,0x00,0x17, /* [ 3996] OBJ_setct_AuthRevReqTBS */
0x67,0x2A,0x00,0x18, /* [ 4000] OBJ_setct_AuthRevResData */
0x67,0x2A,0x00,0x19, /* [ 4004] OBJ_setct_AuthRevResTBS */
0x67,0x2A,0x00,0x1A, /* [ 4008] OBJ_setct_CapReqTBS */
0x67,0x2A,0x00,0x1B, /* [ 4012] OBJ_setct_CapReqTBSX */
0x67,0x2A,0x00,0x1C, /* [ 4016] OBJ_setct_CapResData */
0x67,0x2A,0x00,0x1D, /* [ 4020] OBJ_setct_CapRevReqTBS */
0x67,0x2A,0x00,0x1E, /* [ 4024] OBJ_setct_CapRevReqTBSX */
0x67,0x2A,0x00,0x1F, /* [ 4028] OBJ_setct_CapRevResData */
0x67,0x2A,0x00,0x20, /* [ 4032] OBJ_setct_CredReqTBS */
0x67,0x2A,0x00,0x21, /* [ 4036] OBJ_setct_CredReqTBSX */
0x67,0x2A,0x00,0x22, /* [ 4040] OBJ_setct_CredResData */
0x67,0x2A,0x00,0x23, /* [ 4044] OBJ_setct_CredRevReqTBS */
0x67,0x2A,0x00,0x24, /* [ 4048] OBJ_setct_CredRevReqTBSX */
0x67,0x2A,0x00,0x25, /* [ 4052] OBJ_setct_CredRevResData */
0x67,0x2A,0x00,0x26, /* [ 4056] OBJ_setct_PCertReqData */
0x67,0x2A,0x00,0x27, /* [ 4060] OBJ_setct_PCertResTBS */
0x67,0x2A,0x00,0x28, /* [ 4064] OBJ_setct_BatchAdminReqData */
0x67,0x2A,0x00,0x29, /* [ 4068] OBJ_setct_BatchAdminResData */
0x67,0x2A,0x00,0x2A, /* [ 4072] OBJ_setct_CardCInitResTBS */
0x67,0x2A,0x00,0x2B, /* [ 4076] OBJ_setct_MeAqCInitResTBS */
0x67,0x2A,0x00,0x2C, /* [ 4080] OBJ_setct_RegFormResTBS */
0x67,0x2A,0x00,0x2D, /* [ 4084] OBJ_setct_CertReqData */
0x67,0x2A,0x00,0x2E, /* [ 4088] OBJ_setct_CertReqTBS */
0x67,0x2A,0x00,0x2F, /* [ 4092] OBJ_setct_CertResData */
0x67,0x2A,0x00,0x30, /* [ 4096] OBJ_setct_CertInqReqTBS */
0x67,0x2A,0x00,0x31, /* [ 4100] OBJ_setct_ErrorTBS */
0x67,0x2A,0x00,0x32, /* [ 4104] OBJ_setct_PIDualSignedTBE */
0x67,0x2A,0x00,0x33, /* [ 4108] OBJ_setct_PIUnsignedTBE */
0x67,0x2A,0x00,0x34, /* [ 4112] OBJ_setct_AuthReqTBE */
0x67,0x2A,0x00,0x35, /* [ 4116] OBJ_setct_AuthResTBE */
0x67,0x2A,0x00,0x36, /* [ 4120] OBJ_setct_AuthResTBEX */
0x67,0x2A,0x00,0x37, /* [ 4124] OBJ_setct_AuthTokenTBE */
0x67,0x2A,0x00,0x38, /* [ 4128] OBJ_setct_CapTokenTBE */
0x67,0x2A,0x00,0x39, /* [ 4132] OBJ_setct_CapTokenTBEX */
0x67,0x2A,0x00,0x3A, /* [ 4136] OBJ_setct_AcqCardCodeMsgTBE */
0x67,0x2A,0x00,0x3B, /* [ 4140] OBJ_setct_AuthRevReqTBE */
0x67,0x2A,0x00,0x3C, /* [ 4144] OBJ_setct_AuthRevResTBE */
0x67,0x2A,0x00,0x3D, /* [ 4148] OBJ_setct_AuthRevResTBEB */
0x67,0x2A,0x00,0x3E, /* [ 4152] OBJ_setct_CapReqTBE */
0x67,0x2A,0x00,0x3F, /* [ 4156] OBJ_setct_CapReqTBEX */
0x67,0x2A,0x00,0x40, /* [ 4160] OBJ_setct_CapResTBE */
0x67,0x2A,0x00,0x41, /* [ 4164] OBJ_setct_CapRevReqTBE */
0x67,0x2A,0x00,0x42, /* [ 4168] OBJ_setct_CapRevReqTBEX */
0x67,0x2A,0x00,0x43, /* [ 4172] OBJ_setct_CapRevResTBE */
0x67,0x2A,0x00,0x44, /* [ 4176] OBJ_setct_CredReqTBE */
0x67,0x2A,0x00,0x45, /* [ 4180] OBJ_setct_CredReqTBEX */
0x67,0x2A,0x00,0x46, /* [ 4184] OBJ_setct_CredResTBE */
0x67,0x2A,0x00,0x47, /* [ 4188] OBJ_setct_CredRevReqTBE */
0x67,0x2A,0x00,0x48, /* [ 4192] OBJ_setct_CredRevReqTBEX */
0x67,0x2A,0x00,0x49, /* [ 4196] OBJ_setct_CredRevResTBE */
0x67,0x2A,0x00,0x4A, /* [ 4200] OBJ_setct_BatchAdminReqTBE */
0x67,0x2A,0x00,0x4B, /* [ 4204] OBJ_setct_BatchAdminResTBE */
0x67,0x2A,0x00,0x4C, /* [ 4208] OBJ_setct_RegFormReqTBE */
0x67,0x2A,0x00,0x4D, /* [ 4212] OBJ_setct_CertReqTBE */
0x67,0x2A,0x00,0x4E, /* [ 4216] OBJ_setct_CertReqTBEX */
0x67,0x2A,0x00,0x4F, /* [ 4220] OBJ_setct_CertResTBE */
0x67,0x2A,0x00,0x50, /* [ 4224] OBJ_setct_CRLNotificationTBS */
0x67,0x2A,0x00,0x51, /* [ 4228] OBJ_setct_CRLNotificationResTBS */
0x67,0x2A,0x00,0x52, /* [ 4232] OBJ_setct_BCIDistributionTBS */
0x67,0x2A,0x01,0x01, /* [ 4236] OBJ_setext_genCrypt */
0x67,0x2A,0x01,0x03, /* [ 4240] OBJ_setext_miAuth */
0x67,0x2A,0x01,0x04, /* [ 4244] OBJ_setext_pinSecure */
0x67,0x2A,0x01,0x05, /* [ 4248] OBJ_setext_pinAny */
0x67,0x2A,0x01,0x07, /* [ 4252] OBJ_setext_track2 */
0x67,0x2A,0x01,0x08, /* [ 4256] OBJ_setext_cv */
0x67,0x2A,0x05,0x00, /* [ 4260] OBJ_set_policy_root */
0x67,0x2A,0x07,0x00, /* [ 4264] OBJ_setCext_hashedRoot */
0x67,0x2A,0x07,0x01, /* [ 4268] OBJ_setCext_certType */
0x67,0x2A,0x07,0x02, /* [ 4272] OBJ_setCext_merchData */
0x67,0x2A,0x07,0x03, /* [ 4276] OBJ_setCext_cCertRequired */
0x67,0x2A,0x07,0x04, /* [ 4280] OBJ_setCext_tunneling */
0x67,0x2A,0x07,0x05, /* [ 4284] OBJ_setCext_setExt */
0x67,0x2A,0x07,0x06, /* [ 4288] OBJ_setCext_setQualf */
0x67,0x2A,0x07,0x07, /* [ 4292] OBJ_setCext_PGWYcapabilities */
0x67,0x2A,0x07,0x08, /* [ 4296] OBJ_setCext_TokenIdentifier */
0x67,0x2A,0x07,0x09, /* [ 4300] OBJ_setCext_Track2Data */
0x67,0x2A,0x07,0x0A, /* [ 4304] OBJ_setCext_TokenType */
0x67,0x2A,0x07,0x0B, /* [ 4308] OBJ_setCext_IssuerCapabilities */
0x67,0x2A,0x03,0x00, /* [ 4312] OBJ_setAttr_Cert */
0x67,0x2A,0x03,0x01, /* [ 4316] OBJ_setAttr_PGWYcap */
0x67,0x2A,0x03,0x02, /* [ 4320] OBJ_setAttr_TokenType */
0x67,0x2A,0x03,0x03, /* [ 4324] OBJ_setAttr_IssCap */
0x67,0x2A,0x03,0x00,0x00, /* [ 4328] OBJ_set_rootKeyThumb */
0x67,0x2A,0x03,0x00,0x01, /* [ 4333] OBJ_set_addPolicy */
0x67,0x2A,0x03,0x02,0x01, /* [ 4338] OBJ_setAttr_Token_EMV */
0x67,0x2A,0x03,0x02,0x02, /* [ 4343] OBJ_setAttr_Token_B0Prime */
0x67,0x2A,0x03,0x03,0x03, /* [ 4348] OBJ_setAttr_IssCap_CVM */
0x67,0x2A,0x03,0x03,0x04, /* [ 4353] OBJ_setAttr_IssCap_T2 */
0x67,0x2A,0x03,0x03,0x05, /* [ 4358] OBJ_setAttr_IssCap_Sig */
0x67,0x2A,0x03,0x03,0x03,0x01, /* [ 4363] OBJ_setAttr_GenCryptgrm */
0x67,0x2A,0x03,0x03,0x04,0x01, /* [ 4369] OBJ_setAttr_T2Enc */
0x67,0x2A,0x03,0x03,0x04,0x02, /* [ 4375] OBJ_setAttr_T2cleartxt */
0x67,0x2A,0x03,0x03,0x05,0x01, /* [ 4381] OBJ_setAttr_TokICCsig */
0x67,0x2A,0x03,0x03,0x05,0x02, /* [ 4387] OBJ_setAttr_SecDevSig */
0x67,0x2A,0x08,0x01, /* [ 4393] OBJ_set_brand_IATA_ATA */
0x67,0x2A,0x08,0x1E, /* [ 4397] OBJ_set_brand_Diners */
0x67,0x2A,0x08,0x22, /* [ 4401] OBJ_set_brand_AmericanExpress */
0x67,0x2A,0x08,0x23, /* [ 4405] OBJ_set_brand_JCB */
0x67,0x2A,0x08,0x04, /* [ 4409] OBJ_set_brand_Visa */
0x67,0x2A,0x08,0x05, /* [ 4413] OBJ_set_brand_MasterCard */
0x67,0x2A,0x08,0xAE,0x7B, /* [ 4417] OBJ_set_brand_Novus */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x03,0x0A, /* [ 4422] OBJ_des_cdmf */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x06, /* [ 4430] OBJ_rsaOAEPEncryptionSET */
0x67, /* [ 4439] OBJ_international_organizations */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x02, /* [ 4440] OBJ_ms_smartcard_login */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x14,0x02,0x03, /* [ 4450] OBJ_ms_upn */
0x55,0x04,0x09, /* [ 4460] OBJ_streetAddress */
0x55,0x04,0x11, /* [ 4463] OBJ_postalCode */
0x2B,0x06,0x01,0x05,0x05,0x07,0x15, /* [ 4466] OBJ_id_ppl */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x0E, /* [ 4473] OBJ_proxyCertInfo */
0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x00, /* [ 4481] OBJ_id_ppl_anyLanguage */
0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x01, /* [ 4489] OBJ_id_ppl_inheritAll */
0x55,0x1D,0x1E, /* [ 4497] OBJ_name_constraints */
0x2B,0x06,0x01,0x05,0x05,0x07,0x15,0x02, /* [ 4500] OBJ_Independent */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0B, /* [ 4508] OBJ_sha256WithRSAEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0C, /* [ 4517] OBJ_sha384WithRSAEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0D, /* [ 4526] OBJ_sha512WithRSAEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0E, /* [ 4535] OBJ_sha224WithRSAEncryption */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x01, /* [ 4544] OBJ_sha256 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x02, /* [ 4553] OBJ_sha384 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x03, /* [ 4562] OBJ_sha512 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x04, /* [ 4571] OBJ_sha224 */
0x2B, /* [ 4580] OBJ_identified_organization */
0x2B,0x81,0x04, /* [ 4581] OBJ_certicom_arc */
0x67,0x2B, /* [ 4584] OBJ_wap */
0x67,0x2B,0x01, /* [ 4586] OBJ_wap_wsg */
0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03, /* [ 4589] OBJ_X9_62_id_characteristic_two_basis */
0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x01, /* [ 4597] OBJ_X9_62_onBasis */
0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x02, /* [ 4606] OBJ_X9_62_tpBasis */
0x2A,0x86,0x48,0xCE,0x3D,0x01,0x02,0x03,0x03, /* [ 4615] OBJ_X9_62_ppBasis */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x01, /* [ 4624] OBJ_X9_62_c2pnb163v1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x02, /* [ 4632] OBJ_X9_62_c2pnb163v2 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x03, /* [ 4640] OBJ_X9_62_c2pnb163v3 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x04, /* [ 4648] OBJ_X9_62_c2pnb176v1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x05, /* [ 4656] OBJ_X9_62_c2tnb191v1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x06, /* [ 4664] OBJ_X9_62_c2tnb191v2 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x07, /* [ 4672] OBJ_X9_62_c2tnb191v3 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x08, /* [ 4680] OBJ_X9_62_c2onb191v4 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x09, /* [ 4688] OBJ_X9_62_c2onb191v5 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0A, /* [ 4696] OBJ_X9_62_c2pnb208w1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0B, /* [ 4704] OBJ_X9_62_c2tnb239v1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0C, /* [ 4712] OBJ_X9_62_c2tnb239v2 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0D, /* [ 4720] OBJ_X9_62_c2tnb239v3 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0E, /* [ 4728] OBJ_X9_62_c2onb239v4 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x0F, /* [ 4736] OBJ_X9_62_c2onb239v5 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x10, /* [ 4744] OBJ_X9_62_c2pnb272w1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x11, /* [ 4752] OBJ_X9_62_c2pnb304w1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x12, /* [ 4760] OBJ_X9_62_c2tnb359v1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x13, /* [ 4768] OBJ_X9_62_c2pnb368w1 */
0x2A,0x86,0x48,0xCE,0x3D,0x03,0x00,0x14, /* [ 4776] OBJ_X9_62_c2tnb431r1 */
0x2B,0x81,0x04,0x00,0x06, /* [ 4784] OBJ_secp112r1 */
0x2B,0x81,0x04,0x00,0x07, /* [ 4789] OBJ_secp112r2 */
0x2B,0x81,0x04,0x00,0x1C, /* [ 4794] OBJ_secp128r1 */
0x2B,0x81,0x04,0x00,0x1D, /* [ 4799] OBJ_secp128r2 */
0x2B,0x81,0x04,0x00,0x09, /* [ 4804] OBJ_secp160k1 */
0x2B,0x81,0x04,0x00,0x08, /* [ 4809] OBJ_secp160r1 */
0x2B,0x81,0x04,0x00,0x1E, /* [ 4814] OBJ_secp160r2 */
0x2B,0x81,0x04,0x00,0x1F, /* [ 4819] OBJ_secp192k1 */
0x2B,0x81,0x04,0x00,0x20, /* [ 4824] OBJ_secp224k1 */
0x2B,0x81,0x04,0x00,0x21, /* [ 4829] OBJ_secp224r1 */
0x2B,0x81,0x04,0x00,0x0A, /* [ 4834] OBJ_secp256k1 */
0x2B,0x81,0x04,0x00,0x22, /* [ 4839] OBJ_secp384r1 */
0x2B,0x81,0x04,0x00,0x23, /* [ 4844] OBJ_secp521r1 */
0x2B,0x81,0x04,0x00,0x04, /* [ 4849] OBJ_sect113r1 */
0x2B,0x81,0x04,0x00,0x05, /* [ 4854] OBJ_sect113r2 */
0x2B,0x81,0x04,0x00,0x16, /* [ 4859] OBJ_sect131r1 */
0x2B,0x81,0x04,0x00,0x17, /* [ 4864] OBJ_sect131r2 */
0x2B,0x81,0x04,0x00,0x01, /* [ 4869] OBJ_sect163k1 */
0x2B,0x81,0x04,0x00,0x02, /* [ 4874] OBJ_sect163r1 */
0x2B,0x81,0x04,0x00,0x0F, /* [ 4879] OBJ_sect163r2 */
0x2B,0x81,0x04,0x00,0x18, /* [ 4884] OBJ_sect193r1 */
0x2B,0x81,0x04,0x00,0x19, /* [ 4889] OBJ_sect193r2 */
0x2B,0x81,0x04,0x00,0x1A, /* [ 4894] OBJ_sect233k1 */
0x2B,0x81,0x04,0x00,0x1B, /* [ 4899] OBJ_sect233r1 */
0x2B,0x81,0x04,0x00,0x03, /* [ 4904] OBJ_sect239k1 */
0x2B,0x81,0x04,0x00,0x10, /* [ 4909] OBJ_sect283k1 */
0x2B,0x81,0x04,0x00,0x11, /* [ 4914] OBJ_sect283r1 */
0x2B,0x81,0x04,0x00,0x24, /* [ 4919] OBJ_sect409k1 */
0x2B,0x81,0x04,0x00,0x25, /* [ 4924] OBJ_sect409r1 */
0x2B,0x81,0x04,0x00,0x26, /* [ 4929] OBJ_sect571k1 */
0x2B,0x81,0x04,0x00,0x27, /* [ 4934] OBJ_sect571r1 */
0x67,0x2B,0x01,0x04,0x01, /* [ 4939] OBJ_wap_wsg_idm_ecid_wtls1 */
0x67,0x2B,0x01,0x04,0x03, /* [ 4944] OBJ_wap_wsg_idm_ecid_wtls3 */
0x67,0x2B,0x01,0x04,0x04, /* [ 4949] OBJ_wap_wsg_idm_ecid_wtls4 */
0x67,0x2B,0x01,0x04,0x05, /* [ 4954] OBJ_wap_wsg_idm_ecid_wtls5 */
0x67,0x2B,0x01,0x04,0x06, /* [ 4959] OBJ_wap_wsg_idm_ecid_wtls6 */
0x67,0x2B,0x01,0x04,0x07, /* [ 4964] OBJ_wap_wsg_idm_ecid_wtls7 */
0x67,0x2B,0x01,0x04,0x08, /* [ 4969] OBJ_wap_wsg_idm_ecid_wtls8 */
0x67,0x2B,0x01,0x04,0x09, /* [ 4974] OBJ_wap_wsg_idm_ecid_wtls9 */
0x67,0x2B,0x01,0x04,0x0A, /* [ 4979] OBJ_wap_wsg_idm_ecid_wtls10 */
0x67,0x2B,0x01,0x04,0x0B, /* [ 4984] OBJ_wap_wsg_idm_ecid_wtls11 */
0x67,0x2B,0x01,0x04,0x0C, /* [ 4989] OBJ_wap_wsg_idm_ecid_wtls12 */
0x55,0x1D,0x20,0x00, /* [ 4994] OBJ_any_policy */
0x55,0x1D,0x21, /* [ 4998] OBJ_policy_mappings */
0x55,0x1D,0x36, /* [ 5001] OBJ_inhibit_any_policy */
0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x02, /* [ 5004] OBJ_camellia_128_cbc */
0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x03, /* [ 5015] OBJ_camellia_192_cbc */
0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x01,0x04, /* [ 5026] OBJ_camellia_256_cbc */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x01, /* [ 5037] OBJ_camellia_128_ecb */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x15, /* [ 5045] OBJ_camellia_192_ecb */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x29, /* [ 5053] OBJ_camellia_256_ecb */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x04, /* [ 5061] OBJ_camellia_128_cfb128 */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x18, /* [ 5069] OBJ_camellia_192_cfb128 */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2C, /* [ 5077] OBJ_camellia_256_cfb128 */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x03, /* [ 5085] OBJ_camellia_128_ofb128 */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x17, /* [ 5093] OBJ_camellia_192_ofb128 */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2B, /* [ 5101] OBJ_camellia_256_ofb128 */
0x55,0x1D,0x09, /* [ 5109] OBJ_subject_directory_attributes */
0x55,0x1D,0x1C, /* [ 5112] OBJ_issuing_distribution_point */
0x55,0x1D,0x1D, /* [ 5115] OBJ_certificate_issuer */
0x2A,0x83,0x1A,0x8C,0x9A,0x44, /* [ 5118] OBJ_kisa */
0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x03, /* [ 5124] OBJ_seed_ecb */
0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x04, /* [ 5132] OBJ_seed_cbc */
0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x06, /* [ 5140] OBJ_seed_ofb128 */
0x2A,0x83,0x1A,0x8C,0x9A,0x44,0x01,0x05, /* [ 5148] OBJ_seed_cfb128 */
0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x01, /* [ 5156] OBJ_hmac_md5 */
0x2B,0x06,0x01,0x05,0x05,0x08,0x01,0x02, /* [ 5164] OBJ_hmac_sha1 */
0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x0D, /* [ 5172] OBJ_id_PasswordBasedMAC */
0x2A,0x86,0x48,0x86,0xF6,0x7D,0x07,0x42,0x1E, /* [ 5181] OBJ_id_DHBasedMac */
0x2B,0x06,0x01,0x05,0x05,0x07,0x04,0x10, /* [ 5190] OBJ_id_it_suppLangTags */
0x2B,0x06,0x01,0x05,0x05,0x07,0x30,0x05, /* [ 5198] OBJ_caRepository */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x09, /* [ 5206] OBJ_id_smime_ct_compressedData */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1B, /* [ 5217] OBJ_id_ct_asciiTextWithCRLF */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x05, /* [ 5228] OBJ_id_aes128_wrap */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x19, /* [ 5237] OBJ_id_aes192_wrap */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2D, /* [ 5246] OBJ_id_aes256_wrap */
0x2A,0x86,0x48,0xCE,0x3D,0x04,0x02, /* [ 5255] OBJ_ecdsa_with_Recommended */
0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03, /* [ 5262] OBJ_ecdsa_with_Specified */
0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x01, /* [ 5269] OBJ_ecdsa_with_SHA224 */
0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x02, /* [ 5277] OBJ_ecdsa_with_SHA256 */
0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x03, /* [ 5285] OBJ_ecdsa_with_SHA384 */
0x2A,0x86,0x48,0xCE,0x3D,0x04,0x03,0x04, /* [ 5293] OBJ_ecdsa_with_SHA512 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x06, /* [ 5301] OBJ_hmacWithMD5 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x08, /* [ 5309] OBJ_hmacWithSHA224 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x09, /* [ 5317] OBJ_hmacWithSHA256 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0A, /* [ 5325] OBJ_hmacWithSHA384 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0B, /* [ 5333] OBJ_hmacWithSHA512 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x01, /* [ 5341] OBJ_dsa_with_SHA224 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x02, /* [ 5350] OBJ_dsa_with_SHA256 */
0x28,0xCF,0x06,0x03,0x00,0x37, /* [ 5359] OBJ_whirlpool */
0x2A,0x85,0x03,0x02,0x02, /* [ 5365] OBJ_cryptopro */
0x2A,0x85,0x03,0x02,0x09, /* [ 5370] OBJ_cryptocom */
0x2A,0x85,0x03,0x02,0x02,0x03, /* [ 5375] OBJ_id_GostR3411_94_with_GostR3410_2001 */
0x2A,0x85,0x03,0x02,0x02,0x04, /* [ 5381] OBJ_id_GostR3411_94_with_GostR3410_94 */
0x2A,0x85,0x03,0x02,0x02,0x09, /* [ 5387] OBJ_id_GostR3411_94 */
0x2A,0x85,0x03,0x02,0x02,0x0A, /* [ 5393] OBJ_id_HMACGostR3411_94 */
0x2A,0x85,0x03,0x02,0x02,0x13, /* [ 5399] OBJ_id_GostR3410_2001 */
0x2A,0x85,0x03,0x02,0x02,0x14, /* [ 5405] OBJ_id_GostR3410_94 */
0x2A,0x85,0x03,0x02,0x02,0x15, /* [ 5411] OBJ_id_Gost28147_89 */
0x2A,0x85,0x03,0x02,0x02,0x16, /* [ 5417] OBJ_id_Gost28147_89_MAC */
0x2A,0x85,0x03,0x02,0x02,0x17, /* [ 5423] OBJ_id_GostR3411_94_prf */
0x2A,0x85,0x03,0x02,0x02,0x62, /* [ 5429] OBJ_id_GostR3410_2001DH */
0x2A,0x85,0x03,0x02,0x02,0x63, /* [ 5435] OBJ_id_GostR3410_94DH */
0x2A,0x85,0x03,0x02,0x02,0x0E,0x01, /* [ 5441] OBJ_id_Gost28147_89_CryptoPro_KeyMeshing */
0x2A,0x85,0x03,0x02,0x02,0x0E,0x00, /* [ 5448] OBJ_id_Gost28147_89_None_KeyMeshing */
0x2A,0x85,0x03,0x02,0x02,0x1E,0x00, /* [ 5455] OBJ_id_GostR3411_94_TestParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1E,0x01, /* [ 5462] OBJ_id_GostR3411_94_CryptoProParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1F,0x00, /* [ 5469] OBJ_id_Gost28147_89_TestParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1F,0x01, /* [ 5476] OBJ_id_Gost28147_89_CryptoPro_A_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1F,0x02, /* [ 5483] OBJ_id_Gost28147_89_CryptoPro_B_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1F,0x03, /* [ 5490] OBJ_id_Gost28147_89_CryptoPro_C_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1F,0x04, /* [ 5497] OBJ_id_Gost28147_89_CryptoPro_D_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1F,0x05, /* [ 5504] OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1F,0x06, /* [ 5511] OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x1F,0x07, /* [ 5518] OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x20,0x00, /* [ 5525] OBJ_id_GostR3410_94_TestParamSet */
0x2A,0x85,0x03,0x02,0x02,0x20,0x02, /* [ 5532] OBJ_id_GostR3410_94_CryptoPro_A_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x20,0x03, /* [ 5539] OBJ_id_GostR3410_94_CryptoPro_B_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x20,0x04, /* [ 5546] OBJ_id_GostR3410_94_CryptoPro_C_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x20,0x05, /* [ 5553] OBJ_id_GostR3410_94_CryptoPro_D_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x21,0x01, /* [ 5560] OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x21,0x02, /* [ 5567] OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x21,0x03, /* [ 5574] OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x23,0x00, /* [ 5581] OBJ_id_GostR3410_2001_TestParamSet */
0x2A,0x85,0x03,0x02,0x02,0x23,0x01, /* [ 5588] OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x23,0x02, /* [ 5595] OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x23,0x03, /* [ 5602] OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x24,0x00, /* [ 5609] OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x24,0x01, /* [ 5616] OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet */
0x2A,0x85,0x03,0x02,0x02,0x14,0x01, /* [ 5623] OBJ_id_GostR3410_94_a */
0x2A,0x85,0x03,0x02,0x02,0x14,0x02, /* [ 5630] OBJ_id_GostR3410_94_aBis */
0x2A,0x85,0x03,0x02,0x02,0x14,0x03, /* [ 5637] OBJ_id_GostR3410_94_b */
0x2A,0x85,0x03,0x02,0x02,0x14,0x04, /* [ 5644] OBJ_id_GostR3410_94_bBis */
0x2A,0x85,0x03,0x02,0x09,0x01,0x06,0x01, /* [ 5651] OBJ_id_Gost28147_89_cc */
0x2A,0x85,0x03,0x02,0x09,0x01,0x05,0x03, /* [ 5659] OBJ_id_GostR3410_94_cc */
0x2A,0x85,0x03,0x02,0x09,0x01,0x05,0x04, /* [ 5667] OBJ_id_GostR3410_2001_cc */
0x2A,0x85,0x03,0x02,0x09,0x01,0x03,0x03, /* [ 5675] OBJ_id_GostR3411_94_with_GostR3410_94_cc */
0x2A,0x85,0x03,0x02,0x09,0x01,0x03,0x04, /* [ 5683] OBJ_id_GostR3411_94_with_GostR3410_2001_cc */
0x2A,0x85,0x03,0x02,0x09,0x01,0x08,0x01, /* [ 5691] OBJ_id_GostR3410_2001_ParamSet_cc */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x11,0x02, /* [ 5699] OBJ_LocalKeySet */
0x55,0x1D,0x2E, /* [ 5708] OBJ_freshest_crl */
0x2B,0x06,0x01,0x05,0x05,0x07,0x08,0x03, /* [ 5711] OBJ_id_on_permanentIdentifier */
0x55,0x04,0x0E, /* [ 5719] OBJ_searchGuide */
0x55,0x04,0x0F, /* [ 5722] OBJ_businessCategory */
0x55,0x04,0x10, /* [ 5725] OBJ_postalAddress */
0x55,0x04,0x12, /* [ 5728] OBJ_postOfficeBox */
0x55,0x04,0x13, /* [ 5731] OBJ_physicalDeliveryOfficeName */
0x55,0x04,0x14, /* [ 5734] OBJ_telephoneNumber */
0x55,0x04,0x15, /* [ 5737] OBJ_telexNumber */
0x55,0x04,0x16, /* [ 5740] OBJ_teletexTerminalIdentifier */
0x55,0x04,0x17, /* [ 5743] OBJ_facsimileTelephoneNumber */
0x55,0x04,0x18, /* [ 5746] OBJ_x121Address */
0x55,0x04,0x19, /* [ 5749] OBJ_internationaliSDNNumber */
0x55,0x04,0x1A, /* [ 5752] OBJ_registeredAddress */
0x55,0x04,0x1B, /* [ 5755] OBJ_destinationIndicator */
0x55,0x04,0x1C, /* [ 5758] OBJ_preferredDeliveryMethod */
0x55,0x04,0x1D, /* [ 5761] OBJ_presentationAddress */
0x55,0x04,0x1E, /* [ 5764] OBJ_supportedApplicationContext */
0x55,0x04,0x1F, /* [ 5767] OBJ_member */
0x55,0x04,0x20, /* [ 5770] OBJ_owner */
0x55,0x04,0x21, /* [ 5773] OBJ_roleOccupant */
0x55,0x04,0x22, /* [ 5776] OBJ_seeAlso */
0x55,0x04,0x23, /* [ 5779] OBJ_userPassword */
0x55,0x04,0x24, /* [ 5782] OBJ_userCertificate */
0x55,0x04,0x25, /* [ 5785] OBJ_cACertificate */
0x55,0x04,0x26, /* [ 5788] OBJ_authorityRevocationList */
0x55,0x04,0x27, /* [ 5791] OBJ_certificateRevocationList */
0x55,0x04,0x28, /* [ 5794] OBJ_crossCertificatePair */
0x55,0x04,0x2F, /* [ 5797] OBJ_enhancedSearchGuide */
0x55,0x04,0x30, /* [ 5800] OBJ_protocolInformation */
0x55,0x04,0x31, /* [ 5803] OBJ_distinguishedName */
0x55,0x04,0x32, /* [ 5806] OBJ_uniqueMember */
0x55,0x04,0x33, /* [ 5809] OBJ_houseIdentifier */
0x55,0x04,0x34, /* [ 5812] OBJ_supportedAlgorithms */
0x55,0x04,0x35, /* [ 5815] OBJ_deltaRevocationList */
0x55,0x04,0x36, /* [ 5818] OBJ_dmdName */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x03,0x09, /* [ 5821] OBJ_id_alg_PWRI_KEK */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x06, /* [ 5832] OBJ_aes_128_gcm */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x07, /* [ 5841] OBJ_aes_128_ccm */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x08, /* [ 5850] OBJ_id_aes128_wrap_pad */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1A, /* [ 5859] OBJ_aes_192_gcm */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1B, /* [ 5868] OBJ_aes_192_ccm */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x1C, /* [ 5877] OBJ_id_aes192_wrap_pad */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2E, /* [ 5886] OBJ_aes_256_gcm */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x2F, /* [ 5895] OBJ_aes_256_ccm */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x01,0x30, /* [ 5904] OBJ_id_aes256_wrap_pad */
0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x02, /* [ 5913] OBJ_id_camellia128_wrap */
0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x03, /* [ 5924] OBJ_id_camellia192_wrap */
0x2A,0x83,0x08,0x8C,0x9A,0x4B,0x3D,0x01,0x01,0x03,0x04, /* [ 5935] OBJ_id_camellia256_wrap */
0x55,0x1D,0x25,0x00, /* [ 5946] OBJ_anyExtendedKeyUsage */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x08, /* [ 5950] OBJ_mgf1 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0A, /* [ 5959] OBJ_rsassaPss */
0x2B,0x6F,0x02,0x8C,0x53,0x00,0x01,0x01, /* [ 5968] OBJ_aes_128_xts */
0x2B,0x6F,0x02,0x8C,0x53,0x00,0x01,0x02, /* [ 5976] OBJ_aes_256_xts */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x07, /* [ 5984] OBJ_rsaesOaep */
0x2A,0x86,0x48,0xCE,0x3E,0x02,0x01, /* [ 5993] OBJ_dhpublicnumber */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01, /* [ 6000] OBJ_brainpoolP160r1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x02, /* [ 6009] OBJ_brainpoolP160t1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03, /* [ 6018] OBJ_brainpoolP192r1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x04, /* [ 6027] OBJ_brainpoolP192t1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05, /* [ 6036] OBJ_brainpoolP224r1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x06, /* [ 6045] OBJ_brainpoolP224t1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07, /* [ 6054] OBJ_brainpoolP256r1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x08, /* [ 6063] OBJ_brainpoolP256t1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09, /* [ 6072] OBJ_brainpoolP320r1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0A, /* [ 6081] OBJ_brainpoolP320t1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B, /* [ 6090] OBJ_brainpoolP384r1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0C, /* [ 6099] OBJ_brainpoolP384t1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D, /* [ 6108] OBJ_brainpoolP512r1 */
0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0E, /* [ 6117] OBJ_brainpoolP512t1 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x09, /* [ 6126] OBJ_pSpecified */
0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x02, /* [ 6135] OBJ_dhSinglePass_stdDH_sha1kdf_scheme */
0x2B,0x81,0x04,0x01,0x0B,0x00, /* [ 6144] OBJ_dhSinglePass_stdDH_sha224kdf_scheme */
0x2B,0x81,0x04,0x01,0x0B,0x01, /* [ 6150] OBJ_dhSinglePass_stdDH_sha256kdf_scheme */
0x2B,0x81,0x04,0x01,0x0B,0x02, /* [ 6156] OBJ_dhSinglePass_stdDH_sha384kdf_scheme */
0x2B,0x81,0x04,0x01,0x0B,0x03, /* [ 6162] OBJ_dhSinglePass_stdDH_sha512kdf_scheme */
0x2B,0x81,0x05,0x10,0x86,0x48,0x3F,0x00,0x03, /* [ 6168] OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme */
0x2B,0x81,0x04,0x01,0x0E,0x00, /* [ 6177] OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme */
0x2B,0x81,0x04,0x01,0x0E,0x01, /* [ 6183] OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme */
0x2B,0x81,0x04,0x01,0x0E,0x02, /* [ 6189] OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme */
0x2B,0x81,0x04,0x01,0x0E,0x03, /* [ 6195] OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme */
0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x02, /* [ 6201] OBJ_ct_precert_scts */
0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x03, /* [ 6211] OBJ_ct_precert_poison */
0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x04, /* [ 6221] OBJ_ct_precert_signer */
0x2B,0x06,0x01,0x04,0x01,0xD6,0x79,0x02,0x04,0x05, /* [ 6231] OBJ_ct_cert_scts */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x01, /* [ 6241] OBJ_jurisdictionLocalityName */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x02, /* [ 6252] OBJ_jurisdictionStateOrProvinceName */
0x2B,0x06,0x01,0x04,0x01,0x82,0x37,0x3C,0x02,0x01,0x03, /* [ 6263] OBJ_jurisdictionCountryName */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x06, /* [ 6274] OBJ_camellia_128_gcm */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x07, /* [ 6282] OBJ_camellia_128_ccm */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x09, /* [ 6290] OBJ_camellia_128_ctr */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x0A, /* [ 6298] OBJ_camellia_128_cmac */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x1A, /* [ 6306] OBJ_camellia_192_gcm */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x1B, /* [ 6314] OBJ_camellia_192_ccm */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x1D, /* [ 6322] OBJ_camellia_192_ctr */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x1E, /* [ 6330] OBJ_camellia_192_cmac */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2E, /* [ 6338] OBJ_camellia_256_gcm */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x2F, /* [ 6346] OBJ_camellia_256_ccm */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x31, /* [ 6354] OBJ_camellia_256_ctr */
0x03,0xA2,0x31,0x05,0x03,0x01,0x09,0x32, /* [ 6362] OBJ_camellia_256_cmac */
0x2B,0x06,0x01,0x04,0x01,0xDA,0x47,0x04,0x0B, /* [ 6370] OBJ_id_scrypt */
0x2A,0x85,0x03,0x07,0x01, /* [ 6379] OBJ_id_tc26 */
0x2A,0x85,0x03,0x07,0x01,0x01, /* [ 6384] OBJ_id_tc26_algorithms */
0x2A,0x85,0x03,0x07,0x01,0x01,0x01, /* [ 6390] OBJ_id_tc26_sign */
0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x01, /* [ 6397] OBJ_id_GostR3410_2012_256 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x01,0x02, /* [ 6405] OBJ_id_GostR3410_2012_512 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x02, /* [ 6413] OBJ_id_tc26_digest */
0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x02, /* [ 6420] OBJ_id_GostR3411_2012_256 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x02,0x03, /* [ 6428] OBJ_id_GostR3411_2012_512 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x03, /* [ 6436] OBJ_id_tc26_signwithdigest */
0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x02, /* [ 6443] OBJ_id_tc26_signwithdigest_gost3410_2012_256 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x03,0x03, /* [ 6451] OBJ_id_tc26_signwithdigest_gost3410_2012_512 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x04, /* [ 6459] OBJ_id_tc26_mac */
0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x01, /* [ 6466] OBJ_id_tc26_hmac_gost_3411_2012_256 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x04,0x02, /* [ 6474] OBJ_id_tc26_hmac_gost_3411_2012_512 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05, /* [ 6482] OBJ_id_tc26_cipher */
0x2A,0x85,0x03,0x07,0x01,0x01,0x06, /* [ 6489] OBJ_id_tc26_agreement */
0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x01, /* [ 6496] OBJ_id_tc26_agreement_gost_3410_2012_256 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x06,0x02, /* [ 6504] OBJ_id_tc26_agreement_gost_3410_2012_512 */
0x2A,0x85,0x03,0x07,0x01,0x02, /* [ 6512] OBJ_id_tc26_constants */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01, /* [ 6518] OBJ_id_tc26_sign_constants */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02, /* [ 6525] OBJ_id_tc26_gost_3410_2012_512_constants */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x00, /* [ 6533] OBJ_id_tc26_gost_3410_2012_512_paramSetTest */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x01, /* [ 6542] OBJ_id_tc26_gost_3410_2012_512_paramSetA */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x02, /* [ 6551] OBJ_id_tc26_gost_3410_2012_512_paramSetB */
0x2A,0x85,0x03,0x07,0x01,0x02,0x02, /* [ 6560] OBJ_id_tc26_digest_constants */
0x2A,0x85,0x03,0x07,0x01,0x02,0x05, /* [ 6567] OBJ_id_tc26_cipher_constants */
0x2A,0x85,0x03,0x07,0x01,0x02,0x05,0x01, /* [ 6574] OBJ_id_tc26_gost_28147_constants */
0x2A,0x85,0x03,0x07,0x01,0x02,0x05,0x01,0x01, /* [ 6582] OBJ_id_tc26_gost_28147_param_Z */
0x2A,0x85,0x03,0x03,0x81,0x03,0x01,0x01, /* [ 6591] OBJ_INN */
0x2A,0x85,0x03,0x64,0x01, /* [ 6599] OBJ_OGRN */
0x2A,0x85,0x03,0x64,0x03, /* [ 6604] OBJ_SNILS */
0x2A,0x85,0x03,0x64,0x6F, /* [ 6609] OBJ_subjectSignTool */
0x2A,0x85,0x03,0x64,0x70, /* [ 6614] OBJ_issuerSignTool */
0x2B,0x06,0x01,0x05,0x05,0x07,0x01,0x18, /* [ 6619] OBJ_tlsfeature */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x11, /* [ 6627] OBJ_ipsec_IKE */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x12, /* [ 6635] OBJ_capwapAC */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x13, /* [ 6643] OBJ_capwapWTP */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x15, /* [ 6651] OBJ_sshClient */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x16, /* [ 6659] OBJ_sshServer */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x17, /* [ 6667] OBJ_sendRouter */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x18, /* [ 6675] OBJ_sendProxiedRouter */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x19, /* [ 6683] OBJ_sendOwner */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1A, /* [ 6691] OBJ_sendProxiedOwner */
0x2B,0x06,0x01,0x05,0x02,0x03, /* [ 6699] OBJ_id_pkinit */
0x2B,0x06,0x01,0x05,0x02,0x03,0x04, /* [ 6705] OBJ_pkInitClientAuth */
0x2B,0x06,0x01,0x05,0x02,0x03,0x05, /* [ 6712] OBJ_pkInitKDC */
0x2B,0x65,0x6E, /* [ 6719] OBJ_X25519 */
0x2B,0x65,0x6F, /* [ 6722] OBJ_X448 */
0x2B,0x06,0x01,0x04,0x01,0x8D,0x3A,0x0C,0x02,0x01,0x10, /* [ 6725] OBJ_blake2b512 */
0x2B,0x06,0x01,0x04,0x01,0x8D,0x3A,0x0C,0x02,0x02,0x08, /* [ 6736] OBJ_blake2s256 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x13, /* [ 6747] OBJ_id_smime_ct_contentCollection */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x17, /* [ 6758] OBJ_id_smime_ct_authEnvelopedData */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x01,0x1C, /* [ 6769] OBJ_id_ct_xml */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x01, /* [ 6780] OBJ_aria_128_ecb */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x02, /* [ 6789] OBJ_aria_128_cbc */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x03, /* [ 6798] OBJ_aria_128_cfb128 */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x04, /* [ 6807] OBJ_aria_128_ofb128 */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x05, /* [ 6816] OBJ_aria_128_ctr */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x06, /* [ 6825] OBJ_aria_192_ecb */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x07, /* [ 6834] OBJ_aria_192_cbc */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x08, /* [ 6843] OBJ_aria_192_cfb128 */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x09, /* [ 6852] OBJ_aria_192_ofb128 */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0A, /* [ 6861] OBJ_aria_192_ctr */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0B, /* [ 6870] OBJ_aria_256_ecb */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0C, /* [ 6879] OBJ_aria_256_cbc */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0D, /* [ 6888] OBJ_aria_256_cfb128 */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0E, /* [ 6897] OBJ_aria_256_ofb128 */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x0F, /* [ 6906] OBJ_aria_256_ctr */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x09,0x10,0x02,0x2F, /* [ 6915] OBJ_id_smime_aa_signingCertificateV2 */
0x2B,0x65,0x70, /* [ 6926] OBJ_ED25519 */
0x2B,0x65,0x71, /* [ 6929] OBJ_ED448 */
0x55,0x04,0x61, /* [ 6932] OBJ_organizationIdentifier */
0x55,0x04,0x62, /* [ 6935] OBJ_countryCode3c */
0x55,0x04,0x63, /* [ 6938] OBJ_countryCode3n */
0x55,0x04,0x64, /* [ 6941] OBJ_dnsName */
0x2B,0x24,0x08,0x03,0x03, /* [ 6944] OBJ_x509ExtAdmission */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x05, /* [ 6949] OBJ_sha512_224 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x06, /* [ 6958] OBJ_sha512_256 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x07, /* [ 6967] OBJ_sha3_224 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x08, /* [ 6976] OBJ_sha3_256 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x09, /* [ 6985] OBJ_sha3_384 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0A, /* [ 6994] OBJ_sha3_512 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0B, /* [ 7003] OBJ_shake128 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0C, /* [ 7012] OBJ_shake256 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0D, /* [ 7021] OBJ_hmac_sha3_224 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0E, /* [ 7030] OBJ_hmac_sha3_256 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x0F, /* [ 7039] OBJ_hmac_sha3_384 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x02,0x10, /* [ 7048] OBJ_hmac_sha3_512 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x03, /* [ 7057] OBJ_dsa_with_SHA384 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x04, /* [ 7066] OBJ_dsa_with_SHA512 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x05, /* [ 7075] OBJ_dsa_with_SHA3_224 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x06, /* [ 7084] OBJ_dsa_with_SHA3_256 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x07, /* [ 7093] OBJ_dsa_with_SHA3_384 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x08, /* [ 7102] OBJ_dsa_with_SHA3_512 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x09, /* [ 7111] OBJ_ecdsa_with_SHA3_224 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0A, /* [ 7120] OBJ_ecdsa_with_SHA3_256 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0B, /* [ 7129] OBJ_ecdsa_with_SHA3_384 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0C, /* [ 7138] OBJ_ecdsa_with_SHA3_512 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0D, /* [ 7147] OBJ_RSA_SHA3_224 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0E, /* [ 7156] OBJ_RSA_SHA3_256 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x0F, /* [ 7165] OBJ_RSA_SHA3_384 */
0x60,0x86,0x48,0x01,0x65,0x03,0x04,0x03,0x10, /* [ 7174] OBJ_RSA_SHA3_512 */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x25, /* [ 7183] OBJ_aria_128_ccm */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x26, /* [ 7192] OBJ_aria_192_ccm */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x27, /* [ 7201] OBJ_aria_256_ccm */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x22, /* [ 7210] OBJ_aria_128_gcm */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x23, /* [ 7219] OBJ_aria_192_gcm */
0x2A,0x83,0x1A,0x8C,0x9A,0x6E,0x01,0x01,0x24, /* [ 7228] OBJ_aria_256_gcm */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1B, /* [ 7237] OBJ_cmcCA */
0x2B,0x06,0x01,0x05,0x05,0x07,0x03,0x1C, /* [ 7245] OBJ_cmcRA */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x01, /* [ 7253] OBJ_sm4_ecb */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x02, /* [ 7261] OBJ_sm4_cbc */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x03, /* [ 7269] OBJ_sm4_ofb128 */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x05, /* [ 7277] OBJ_sm4_cfb1 */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x04, /* [ 7285] OBJ_sm4_cfb128 */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x06, /* [ 7293] OBJ_sm4_cfb8 */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x68,0x07, /* [ 7301] OBJ_sm4_ctr */
0x2A,0x81,0x1C, /* [ 7309] OBJ_ISO_CN */
0x2A,0x81,0x1C,0xCF,0x55, /* [ 7312] OBJ_oscca */
0x2A,0x81,0x1C,0xCF,0x55,0x01, /* [ 7317] OBJ_sm_scheme */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x11, /* [ 7323] OBJ_sm3 */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x83,0x78, /* [ 7331] OBJ_sm3WithRSAEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x0F, /* [ 7339] OBJ_sha512_224WithRSAEncryption */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x01,0x01,0x10, /* [ 7348] OBJ_sha512_256WithRSAEncryption */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01, /* [ 7357] OBJ_id_tc26_gost_3410_2012_256_constants */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x01, /* [ 7365] OBJ_id_tc26_gost_3410_2012_256_paramSetA */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x02,0x03, /* [ 7374] OBJ_id_tc26_gost_3410_2012_512_paramSetC */
0x2A,0x86,0x24, /* [ 7383] OBJ_ISO_UA */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01, /* [ 7386] OBJ_ua_pki */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x01, /* [ 7393] OBJ_dstu28147 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x02, /* [ 7403] OBJ_dstu28147_ofb */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x03, /* [ 7414] OBJ_dstu28147_cfb */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x05, /* [ 7425] OBJ_dstu28147_wrap */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x01,0x02, /* [ 7436] OBJ_hmacWithDstu34311 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x02,0x01, /* [ 7446] OBJ_dstu34311 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01, /* [ 7456] OBJ_dstu4145le */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x01,0x01, /* [ 7467] OBJ_dstu4145be */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x00, /* [ 7480] OBJ_uacurve0 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x01, /* [ 7493] OBJ_uacurve1 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x02, /* [ 7506] OBJ_uacurve2 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x03, /* [ 7519] OBJ_uacurve3 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x04, /* [ 7532] OBJ_uacurve4 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x05, /* [ 7545] OBJ_uacurve5 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x06, /* [ 7558] OBJ_uacurve6 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x07, /* [ 7571] OBJ_uacurve7 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x08, /* [ 7584] OBJ_uacurve8 */
0x2A,0x86,0x24,0x02,0x01,0x01,0x01,0x01,0x03,0x01,0x01,0x02,0x09, /* [ 7597] OBJ_uacurve9 */
0x2B,0x6F, /* [ 7610] OBJ_ieee */
0x2B,0x6F,0x02,0x8C,0x53, /* [ 7612] OBJ_ieee_siswg */
0x2A,0x81,0x1C,0xCF,0x55,0x01,0x82,0x2D, /* [ 7617] OBJ_sm2 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01, /* [ 7625] OBJ_id_tc26_cipher_gostr3412_2015_magma */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01,0x01, /* [ 7633] OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x01,0x02, /* [ 7642] OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02, /* [ 7651] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02,0x01, /* [ 7659] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm */
0x2A,0x85,0x03,0x07,0x01,0x01,0x05,0x02,0x02, /* [ 7668] OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07, /* [ 7677] OBJ_id_tc26_wrap */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01, /* [ 7684] OBJ_id_tc26_wrap_gostr3412_2015_magma */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7692] OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 */
0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02, /* [ 7701] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik */
- 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x01,0x01, /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */
+ 0x2A,0x85,0x03,0x07,0x01,0x01,0x07,0x02,0x01, /* [ 7709] OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x02, /* [ 7718] OBJ_id_tc26_gost_3410_2012_256_paramSetB */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x03, /* [ 7727] OBJ_id_tc26_gost_3410_2012_256_paramSetC */
0x2A,0x85,0x03,0x07,0x01,0x02,0x01,0x01,0x04, /* [ 7736] OBJ_id_tc26_gost_3410_2012_256_paramSetD */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0C, /* [ 7745] OBJ_hmacWithSHA512_224 */
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */
};
#define NUM_NID 1195
static const ASN1_OBJECT nid_objs[NUM_NID] = {
{"UNDEF", "undefined", NID_undef},
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
{"pkcs", "RSA Data Security, Inc. PKCS", NID_pkcs, 7, &so[6]},
{"MD2", "md2", NID_md2, 8, &so[13]},
{"MD5", "md5", NID_md5, 8, &so[21]},
{"RC4", "rc4", NID_rc4, 8, &so[29]},
{"rsaEncryption", "rsaEncryption", NID_rsaEncryption, 9, &so[37]},
{"RSA-MD2", "md2WithRSAEncryption", NID_md2WithRSAEncryption, 9, &so[46]},
{"RSA-MD5", "md5WithRSAEncryption", NID_md5WithRSAEncryption, 9, &so[55]},
{"PBE-MD2-DES", "pbeWithMD2AndDES-CBC", NID_pbeWithMD2AndDES_CBC, 9, &so[64]},
{"PBE-MD5-DES", "pbeWithMD5AndDES-CBC", NID_pbeWithMD5AndDES_CBC, 9, &so[73]},
{"X500", "directory services (X.500)", NID_X500, 1, &so[82]},
{"X509", "X509", NID_X509, 2, &so[83]},
{"CN", "commonName", NID_commonName, 3, &so[85]},
{"C", "countryName", NID_countryName, 3, &so[88]},
{"L", "localityName", NID_localityName, 3, &so[91]},
{"ST", "stateOrProvinceName", NID_stateOrProvinceName, 3, &so[94]},
{"O", "organizationName", NID_organizationName, 3, &so[97]},
{"OU", "organizationalUnitName", NID_organizationalUnitName, 3, &so[100]},
{"RSA", "rsa", NID_rsa, 4, &so[103]},
{"pkcs7", "pkcs7", NID_pkcs7, 8, &so[107]},
{"pkcs7-data", "pkcs7-data", NID_pkcs7_data, 9, &so[115]},
{"pkcs7-signedData", "pkcs7-signedData", NID_pkcs7_signed, 9, &so[124]},
{"pkcs7-envelopedData", "pkcs7-envelopedData", NID_pkcs7_enveloped, 9, &so[133]},
{"pkcs7-signedAndEnvelopedData", "pkcs7-signedAndEnvelopedData", NID_pkcs7_signedAndEnveloped, 9, &so[142]},
{"pkcs7-digestData", "pkcs7-digestData", NID_pkcs7_digest, 9, &so[151]},
{"pkcs7-encryptedData", "pkcs7-encryptedData", NID_pkcs7_encrypted, 9, &so[160]},
{"pkcs3", "pkcs3", NID_pkcs3, 8, &so[169]},
{"dhKeyAgreement", "dhKeyAgreement", NID_dhKeyAgreement, 9, &so[177]},
{"DES-ECB", "des-ecb", NID_des_ecb, 5, &so[186]},
{"DES-CFB", "des-cfb", NID_des_cfb64, 5, &so[191]},
{"DES-CBC", "des-cbc", NID_des_cbc, 5, &so[196]},
{"DES-EDE", "des-ede", NID_des_ede_ecb, 5, &so[201]},
{"DES-EDE3", "des-ede3", NID_des_ede3_ecb},
{"IDEA-CBC", "idea-cbc", NID_idea_cbc, 11, &so[206]},
{"IDEA-CFB", "idea-cfb", NID_idea_cfb64},
{"IDEA-ECB", "idea-ecb", NID_idea_ecb},
{"RC2-CBC", "rc2-cbc", NID_rc2_cbc, 8, &so[217]},
{"RC2-ECB", "rc2-ecb", NID_rc2_ecb},
{"RC2-CFB", "rc2-cfb", NID_rc2_cfb64},
{"RC2-OFB", "rc2-ofb", NID_rc2_ofb64},
{"SHA", "sha", NID_sha, 5, &so[225]},
{"RSA-SHA", "shaWithRSAEncryption", NID_shaWithRSAEncryption, 5, &so[230]},
{"DES-EDE-CBC", "des-ede-cbc", NID_des_ede_cbc},
{"DES-EDE3-CBC", "des-ede3-cbc", NID_des_ede3_cbc, 8, &so[235]},
{"DES-OFB", "des-ofb", NID_des_ofb64, 5, &so[243]},
{"IDEA-OFB", "idea-ofb", NID_idea_ofb64},
{"pkcs9", "pkcs9", NID_pkcs9, 8, &so[248]},
{"emailAddress", "emailAddress", NID_pkcs9_emailAddress, 9, &so[256]},
{"unstructuredName", "unstructuredName", NID_pkcs9_unstructuredName, 9, &so[265]},
{"contentType", "contentType", NID_pkcs9_contentType, 9, &so[274]},
{"messageDigest", "messageDigest", NID_pkcs9_messageDigest, 9, &so[283]},
{"signingTime", "signingTime", NID_pkcs9_signingTime, 9, &so[292]},
{"countersignature", "countersignature", NID_pkcs9_countersignature, 9, &so[301]},
{"challengePassword", "challengePassword", NID_pkcs9_challengePassword, 9, &so[310]},
{"unstructuredAddress", "unstructuredAddress", NID_pkcs9_unstructuredAddress, 9, &so[319]},
{"extendedCertificateAttributes", "extendedCertificateAttributes", NID_pkcs9_extCertAttributes, 9, &so[328]},
{"Netscape", "Netscape Communications Corp.", NID_netscape, 7, &so[337]},
{"nsCertExt", "Netscape Certificate Extension", NID_netscape_cert_extension, 8, &so[344]},
{"nsDataType", "Netscape Data Type", NID_netscape_data_type, 8, &so[352]},
{"DES-EDE-CFB", "des-ede-cfb", NID_des_ede_cfb64},
{"DES-EDE3-CFB", "des-ede3-cfb", NID_des_ede3_cfb64},
{"DES-EDE-OFB", "des-ede-ofb", NID_des_ede_ofb64},
{"DES-EDE3-OFB", "des-ede3-ofb", NID_des_ede3_ofb64},
{"SHA1", "sha1", NID_sha1, 5, &so[360]},
{"RSA-SHA1", "sha1WithRSAEncryption", NID_sha1WithRSAEncryption, 9, &so[365]},
{"DSA-SHA", "dsaWithSHA", NID_dsaWithSHA, 5, &so[374]},
{"DSA-old", "dsaEncryption-old", NID_dsa_2, 5, &so[379]},
{"PBE-SHA1-RC2-64", "pbeWithSHA1AndRC2-CBC", NID_pbeWithSHA1AndRC2_CBC, 9, &so[384]},
{"PBKDF2", "PBKDF2", NID_id_pbkdf2, 9, &so[393]},
{"DSA-SHA1-old", "dsaWithSHA1-old", NID_dsaWithSHA1_2, 5, &so[402]},
{"nsCertType", "Netscape Cert Type", NID_netscape_cert_type, 9, &so[407]},
{"nsBaseUrl", "Netscape Base Url", NID_netscape_base_url, 9, &so[416]},
{"nsRevocationUrl", "Netscape Revocation Url", NID_netscape_revocation_url, 9, &so[425]},
{"nsCaRevocationUrl", "Netscape CA Revocation Url", NID_netscape_ca_revocation_url, 9, &so[434]},
{"nsRenewalUrl", "Netscape Renewal Url", NID_netscape_renewal_url, 9, &so[443]},
{"nsCaPolicyUrl", "Netscape CA Policy Url", NID_netscape_ca_policy_url, 9, &so[452]},
{"nsSslServerName", "Netscape SSL Server Name", NID_netscape_ssl_server_name, 9, &so[461]},
{"nsComment", "Netscape Comment", NID_netscape_comment, 9, &so[470]},
{"nsCertSequence", "Netscape Certificate Sequence", NID_netscape_cert_sequence, 9, &so[479]},
{"DESX-CBC", "desx-cbc", NID_desx_cbc},
{"id-ce", "id-ce", NID_id_ce, 2, &so[488]},
{"subjectKeyIdentifier", "X509v3 Subject Key Identifier", NID_subject_key_identifier, 3, &so[490]},
{"keyUsage", "X509v3 Key Usage", NID_key_usage, 3, &so[493]},
{"privateKeyUsagePeriod", "X509v3 Private Key Usage Period", NID_private_key_usage_period, 3, &so[496]},
{"subjectAltName", "X509v3 Subject Alternative Name", NID_subject_alt_name, 3, &so[499]},
{"issuerAltName", "X509v3 Issuer Alternative Name", NID_issuer_alt_name, 3, &so[502]},
{"basicConstraints", "X509v3 Basic Constraints", NID_basic_constraints, 3, &so[505]},
{"crlNumber", "X509v3 CRL Number", NID_crl_number, 3, &so[508]},
{"certificatePolicies", "X509v3 Certificate Policies", NID_certificate_policies, 3, &so[511]},
{"authorityKeyIdentifier", "X509v3 Authority Key Identifier", NID_authority_key_identifier, 3, &so[514]},
{"BF-CBC", "bf-cbc", NID_bf_cbc, 9, &so[517]},
{"BF-ECB", "bf-ecb", NID_bf_ecb},
{"BF-CFB", "bf-cfb", NID_bf_cfb64},
{"BF-OFB", "bf-ofb", NID_bf_ofb64},
{"MDC2", "mdc2", NID_mdc2, 4, &so[526]},
{"RSA-MDC2", "mdc2WithRSA", NID_mdc2WithRSA, 4, &so[530]},
{"RC4-40", "rc4-40", NID_rc4_40},
{"RC2-40-CBC", "rc2-40-cbc", NID_rc2_40_cbc},
{"GN", "givenName", NID_givenName, 3, &so[534]},
{"SN", "surname", NID_surname, 3, &so[537]},
{"initials", "initials", NID_initials, 3, &so[540]},
{"uid", "uniqueIdentifier", NID_uniqueIdentifier, 10, &so[543]},
{"crlDistributionPoints", "X509v3 CRL Distribution Points", NID_crl_distribution_points, 3, &so[553]},
{"RSA-NP-MD5", "md5WithRSA", NID_md5WithRSA, 5, &so[556]},
{"serialNumber", "serialNumber", NID_serialNumber, 3, &so[561]},
{"title", "title", NID_title, 3, &so[564]},
{"description", "description", NID_description, 3, &so[567]},
{"CAST5-CBC", "cast5-cbc", NID_cast5_cbc, 9, &so[570]},
{"CAST5-ECB", "cast5-ecb", NID_cast5_ecb},
{"CAST5-CFB", "cast5-cfb", NID_cast5_cfb64},
{"CAST5-OFB", "cast5-ofb", NID_cast5_ofb64},
{"pbeWithMD5AndCast5CBC", "pbeWithMD5AndCast5CBC", NID_pbeWithMD5AndCast5_CBC, 9, &so[579]},
{"DSA-SHA1", "dsaWithSHA1", NID_dsaWithSHA1, 7, &so[588]},
{"MD5-SHA1", "md5-sha1", NID_md5_sha1},
{"RSA-SHA1-2", "sha1WithRSA", NID_sha1WithRSA, 5, &so[595]},
{"DSA", "dsaEncryption", NID_dsa, 7, &so[600]},
{"RIPEMD160", "ripemd160", NID_ripemd160, 5, &so[607]},
{ NULL, NULL, NID_undef },
{"RSA-RIPEMD160", "ripemd160WithRSA", NID_ripemd160WithRSA, 6, &so[612]},
{"RC5-CBC", "rc5-cbc", NID_rc5_cbc, 8, &so[618]},
{"RC5-ECB", "rc5-ecb", NID_rc5_ecb},
{"RC5-CFB", "rc5-cfb", NID_rc5_cfb64},
{"RC5-OFB", "rc5-ofb", NID_rc5_ofb64},
{ NULL, NULL, NID_undef },
{"ZLIB", "zlib compression", NID_zlib_compression, 11, &so[626]},
{"extendedKeyUsage", "X509v3 Extended Key Usage", NID_ext_key_usage, 3, &so[637]},
{"PKIX", "PKIX", NID_id_pkix, 6, &so[640]},
{"id-kp", "id-kp", NID_id_kp, 7, &so[646]},
{"serverAuth", "TLS Web Server Authentication", NID_server_auth, 8, &so[653]},
{"clientAuth", "TLS Web Client Authentication", NID_client_auth, 8, &so[661]},
{"codeSigning", "Code Signing", NID_code_sign, 8, &so[669]},
{"emailProtection", "E-mail Protection", NID_email_protect, 8, &so[677]},
{"timeStamping", "Time Stamping", NID_time_stamp, 8, &so[685]},
{"msCodeInd", "Microsoft Individual Code Signing", NID_ms_code_ind, 10, &so[693]},
{"msCodeCom", "Microsoft Commercial Code Signing", NID_ms_code_com, 10, &so[703]},
{"msCTLSign", "Microsoft Trust List Signing", NID_ms_ctl_sign, 10, &so[713]},
{"msSGC", "Microsoft Server Gated Crypto", NID_ms_sgc, 10, &so[723]},
{"msEFS", "Microsoft Encrypted File System", NID_ms_efs, 10, &so[733]},
{"nsSGC", "Netscape Server Gated Crypto", NID_ns_sgc, 9, &so[743]},
{"deltaCRL", "X509v3 Delta CRL Indicator", NID_delta_crl, 3, &so[752]},
{"CRLReason", "X509v3 CRL Reason Code", NID_crl_reason, 3, &so[755]},
{"invalidityDate", "Invalidity Date", NID_invalidity_date, 3, &so[758]},
{"SXNetID", "Strong Extranet ID", NID_sxnet, 5, &so[761]},
{"PBE-SHA1-RC4-128", "pbeWithSHA1And128BitRC4", NID_pbe_WithSHA1And128BitRC4, 10, &so[766]},
{"PBE-SHA1-RC4-40", "pbeWithSHA1And40BitRC4", NID_pbe_WithSHA1And40BitRC4, 10, &so[776]},
{"PBE-SHA1-3DES", "pbeWithSHA1And3-KeyTripleDES-CBC", NID_pbe_WithSHA1And3_Key_TripleDES_CBC, 10, &so[786]},
{"PBE-SHA1-2DES", "pbeWithSHA1And2-KeyTripleDES-CBC", NID_pbe_WithSHA1And2_Key_TripleDES_CBC, 10, &so[796]},
{"PBE-SHA1-RC2-128", "pbeWithSHA1And128BitRC2-CBC", NID_pbe_WithSHA1And128BitRC2_CBC, 10, &so[806]},
{"PBE-SHA1-RC2-40", "pbeWithSHA1And40BitRC2-CBC", NID_pbe_WithSHA1And40BitRC2_CBC, 10, &so[816]},
{"keyBag", "keyBag", NID_keyBag, 11, &so[826]},
{"pkcs8ShroudedKeyBag", "pkcs8ShroudedKeyBag", NID_pkcs8ShroudedKeyBag, 11, &so[837]},
{"certBag", "certBag", NID_certBag, 11, &so[848]},
{"crlBag", "crlBag", NID_crlBag, 11, &so[859]},
{"secretBag", "secretBag", NID_secretBag, 11, &so[870]},
{"safeContentsBag", "safeContentsBag", NID_safeContentsBag, 11, &so[881]},
{"friendlyName", "friendlyName", NID_friendlyName, 9, &so[892]},
{"localKeyID", "localKeyID", NID_localKeyID, 9, &so[901]},
{"x509Certificate", "x509Certificate", NID_x509Certificate, 10, &so[910]},
{"sdsiCertificate", "sdsiCertificate", NID_sdsiCertificate, 10, &so[920]},
{"x509Crl", "x509Crl", NID_x509Crl, 10, &so[930]},
{"PBES2", "PBES2", NID_pbes2, 9, &so[940]},
{"PBMAC1", "PBMAC1", NID_pbmac1, 9, &so[949]},
{"hmacWithSHA1", "hmacWithSHA1", NID_hmacWithSHA1, 8, &so[958]},
{"id-qt-cps", "Policy Qualifier CPS", NID_id_qt_cps, 8, &so[966]},
{"id-qt-unotice", "Policy Qualifier User Notice", NID_id_qt_unotice, 8, &so[974]},
{"RC2-64-CBC", "rc2-64-cbc", NID_rc2_64_cbc},
{"SMIME-CAPS", "S/MIME Capabilities", NID_SMIMECapabilities, 9, &so[982]},
{"PBE-MD2-RC2-64", "pbeWithMD2AndRC2-CBC", NID_pbeWithMD2AndRC2_CBC, 9, &so[991]},
{"PBE-MD5-RC2-64", "pbeWithMD5AndRC2-CBC", NID_pbeWithMD5AndRC2_CBC, 9, &so[1000]},
{"PBE-SHA1-DES", "pbeWithSHA1AndDES-CBC", NID_pbeWithSHA1AndDES_CBC, 9, &so[1009]},
{"msExtReq", "Microsoft Extension Request", NID_ms_ext_req, 10, &so[1018]},
{"extReq", "Extension Request", NID_ext_req, 9, &so[1028]},
{"name", "name", NID_name, 3, &so[1037]},
{"dnQualifier", "dnQualifier", NID_dnQualifier, 3, &so[1040]},
{"id-pe", "id-pe", NID_id_pe, 7, &so[1043]},
{"id-ad", "id-ad", NID_id_ad, 7, &so[1050]},
{"authorityInfoAccess", "Authority Information Access", NID_info_access, 8, &so[1057]},
{"OCSP", "OCSP", NID_ad_OCSP, 8, &so[1065]},
{"caIssuers", "CA Issuers", NID_ad_ca_issuers, 8, &so[1073]},
{"OCSPSigning", "OCSP Signing", NID_OCSP_sign, 8, &so[1081]},
{"ISO", "iso", NID_iso},
{"member-body", "ISO Member Body", NID_member_body, 1, &so[1089]},
{"ISO-US", "ISO US Member Body", NID_ISO_US, 3, &so[1090]},
{"X9-57", "X9.57", NID_X9_57, 5, &so[1093]},
{"X9cm", "X9.57 CM ?", NID_X9cm, 6, &so[1098]},
{"pkcs1", "pkcs1", NID_pkcs1, 8, &so[1104]},
{"pkcs5", "pkcs5", NID_pkcs5, 8, &so[1112]},
{"SMIME", "S/MIME", NID_SMIME, 9, &so[1120]},
{"id-smime-mod", "id-smime-mod", NID_id_smime_mod, 10, &so[1129]},
{"id-smime-ct", "id-smime-ct", NID_id_smime_ct, 10, &so[1139]},
{"id-smime-aa", "id-smime-aa", NID_id_smime_aa, 10, &so[1149]},
{"id-smime-alg", "id-smime-alg", NID_id_smime_alg, 10, &so[1159]},
{"id-smime-cd", "id-smime-cd", NID_id_smime_cd, 10, &so[1169]},
{"id-smime-spq", "id-smime-spq", NID_id_smime_spq, 10, &so[1179]},
{"id-smime-cti", "id-smime-cti", NID_id_smime_cti, 10, &so[1189]},
{"id-smime-mod-cms", "id-smime-mod-cms", NID_id_smime_mod_cms, 11, &so[1199]},
{"id-smime-mod-ess", "id-smime-mod-ess", NID_id_smime_mod_ess, 11, &so[1210]},
{"id-smime-mod-oid", "id-smime-mod-oid", NID_id_smime_mod_oid, 11, &so[1221]},
{"id-smime-mod-msg-v3", "id-smime-mod-msg-v3", NID_id_smime_mod_msg_v3, 11, &so[1232]},
{"id-smime-mod-ets-eSignature-88", "id-smime-mod-ets-eSignature-88", NID_id_smime_mod_ets_eSignature_88, 11, &so[1243]},
{"id-smime-mod-ets-eSignature-97", "id-smime-mod-ets-eSignature-97", NID_id_smime_mod_ets_eSignature_97, 11, &so[1254]},
{"id-smime-mod-ets-eSigPolicy-88", "id-smime-mod-ets-eSigPolicy-88", NID_id_smime_mod_ets_eSigPolicy_88, 11, &so[1265]},
{"id-smime-mod-ets-eSigPolicy-97", "id-smime-mod-ets-eSigPolicy-97", NID_id_smime_mod_ets_eSigPolicy_97, 11, &so[1276]},
{"id-smime-ct-receipt", "id-smime-ct-receipt", NID_id_smime_ct_receipt, 11, &so[1287]},
{"id-smime-ct-authData", "id-smime-ct-authData", NID_id_smime_ct_authData, 11, &so[1298]},
{"id-smime-ct-publishCert", "id-smime-ct-publishCert", NID_id_smime_ct_publishCert, 11, &so[1309]},
{"id-smime-ct-TSTInfo", "id-smime-ct-TSTInfo", NID_id_smime_ct_TSTInfo, 11, &so[1320]},
{"id-smime-ct-TDTInfo", "id-smime-ct-TDTInfo", NID_id_smime_ct_TDTInfo, 11, &so[1331]},
{"id-smime-ct-contentInfo", "id-smime-ct-contentInfo", NID_id_smime_ct_contentInfo, 11, &so[1342]},
{"id-smime-ct-DVCSRequestData", "id-smime-ct-DVCSRequestData", NID_id_smime_ct_DVCSRequestData, 11, &so[1353]},
{"id-smime-ct-DVCSResponseData", "id-smime-ct-DVCSResponseData", NID_id_smime_ct_DVCSResponseData, 11, &so[1364]},
{"id-smime-aa-receiptRequest", "id-smime-aa-receiptRequest", NID_id_smime_aa_receiptRequest, 11, &so[1375]},
{"id-smime-aa-securityLabel", "id-smime-aa-securityLabel", NID_id_smime_aa_securityLabel, 11, &so[1386]},
{"id-smime-aa-mlExpandHistory", "id-smime-aa-mlExpandHistory", NID_id_smime_aa_mlExpandHistory, 11, &so[1397]},
{"id-smime-aa-contentHint", "id-smime-aa-contentHint", NID_id_smime_aa_contentHint, 11, &so[1408]},
{"id-smime-aa-msgSigDigest", "id-smime-aa-msgSigDigest", NID_id_smime_aa_msgSigDigest, 11, &so[1419]},
{"id-smime-aa-encapContentType", "id-smime-aa-encapContentType", NID_id_smime_aa_encapContentType, 11, &so[1430]},
{"id-smime-aa-contentIdentifier", "id-smime-aa-contentIdentifier", NID_id_smime_aa_contentIdentifier, 11, &so[1441]},
{"id-smime-aa-macValue", "id-smime-aa-macValue", NID_id_smime_aa_macValue, 11, &so[1452]},
{"id-smime-aa-equivalentLabels", "id-smime-aa-equivalentLabels", NID_id_smime_aa_equivalentLabels, 11, &so[1463]},
{"id-smime-aa-contentReference", "id-smime-aa-contentReference", NID_id_smime_aa_contentReference, 11, &so[1474]},
{"id-smime-aa-encrypKeyPref", "id-smime-aa-encrypKeyPref", NID_id_smime_aa_encrypKeyPref, 11, &so[1485]},
{"id-smime-aa-signingCertificate", "id-smime-aa-signingCertificate", NID_id_smime_aa_signingCertificate, 11, &so[1496]},
{"id-smime-aa-smimeEncryptCerts", "id-smime-aa-smimeEncryptCerts", NID_id_smime_aa_smimeEncryptCerts, 11, &so[1507]},
{"id-smime-aa-timeStampToken", "id-smime-aa-timeStampToken", NID_id_smime_aa_timeStampToken, 11, &so[1518]},
{"id-smime-aa-ets-sigPolicyId", "id-smime-aa-ets-sigPolicyId", NID_id_smime_aa_ets_sigPolicyId, 11, &so[1529]},
{"id-smime-aa-ets-commitmentType", "id-smime-aa-ets-commitmentType", NID_id_smime_aa_ets_commitmentType, 11, &so[1540]},
{"id-smime-aa-ets-signerLocation", "id-smime-aa-ets-signerLocation", NID_id_smime_aa_ets_signerLocation, 11, &so[1551]},
{"id-smime-aa-ets-signerAttr", "id-smime-aa-ets-signerAttr", NID_id_smime_aa_ets_signerAttr, 11, &so[1562]},
{"id-smime-aa-ets-otherSigCert", "id-smime-aa-ets-otherSigCert", NID_id_smime_aa_ets_otherSigCert, 11, &so[1573]},
{"id-smime-aa-ets-contentTimestamp", "id-smime-aa-ets-contentTimestamp", NID_id_smime_aa_ets_contentTimestamp, 11, &so[1584]},
{"id-smime-aa-ets-CertificateRefs", "id-smime-aa-ets-CertificateRefs", NID_id_smime_aa_ets_CertificateRefs, 11, &so[1595]},
{"id-smime-aa-ets-RevocationRefs", "id-smime-aa-ets-RevocationRefs", NID_id_smime_aa_ets_RevocationRefs, 11, &so[1606]},
{"id-smime-aa-ets-certValues", "id-smime-aa-ets-certValues", NID_id_smime_aa_ets_certValues, 11, &so[1617]},
{"id-smime-aa-ets-revocationValues", "id-smime-aa-ets-revocationValues", NID_id_smime_aa_ets_revocationValues, 11, &so[1628]},
{"id-smime-aa-ets-escTimeStamp", "id-smime-aa-ets-escTimeStamp", NID_id_smime_aa_ets_escTimeStamp, 11, &so[1639]},
{"id-smime-aa-ets-certCRLTimestamp", "id-smime-aa-ets-certCRLTimestamp", NID_id_smime_aa_ets_certCRLTimestamp, 11, &so[1650]},
{"id-smime-aa-ets-archiveTimeStamp", "id-smime-aa-ets-archiveTimeStamp", NID_id_smime_aa_ets_archiveTimeStamp, 11, &so[1661]},
{"id-smime-aa-signatureType", "id-smime-aa-signatureType", NID_id_smime_aa_signatureType, 11, &so[1672]},
{"id-smime-aa-dvcs-dvc", "id-smime-aa-dvcs-dvc", NID_id_smime_aa_dvcs_dvc, 11, &so[1683]},
{"id-smime-alg-ESDHwith3DES", "id-smime-alg-ESDHwith3DES", NID_id_smime_alg_ESDHwith3DES, 11, &so[1694]},
{"id-smime-alg-ESDHwithRC2", "id-smime-alg-ESDHwithRC2", NID_id_smime_alg_ESDHwithRC2, 11, &so[1705]},
{"id-smime-alg-3DESwrap", "id-smime-alg-3DESwrap", NID_id_smime_alg_3DESwrap, 11, &so[1716]},
{"id-smime-alg-RC2wrap", "id-smime-alg-RC2wrap", NID_id_smime_alg_RC2wrap, 11, &so[1727]},
{"id-smime-alg-ESDH", "id-smime-alg-ESDH", NID_id_smime_alg_ESDH, 11, &so[1738]},
{"id-smime-alg-CMS3DESwrap", "id-smime-alg-CMS3DESwrap", NID_id_smime_alg_CMS3DESwrap, 11, &so[1749]},
{"id-smime-alg-CMSRC2wrap", "id-smime-alg-CMSRC2wrap", NID_id_smime_alg_CMSRC2wrap, 11, &so[1760]},
{"id-smime-cd-ldap", "id-smime-cd-ldap", NID_id_smime_cd_ldap, 11, &so[1771]},
{"id-smime-spq-ets-sqt-uri", "id-smime-spq-ets-sqt-uri", NID_id_smime_spq_ets_sqt_uri, 11, &so[1782]},
{"id-smime-spq-ets-sqt-unotice", "id-smime-spq-ets-sqt-unotice", NID_id_smime_spq_ets_sqt_unotice, 11, &so[1793]},
{"id-smime-cti-ets-proofOfOrigin", "id-smime-cti-ets-proofOfOrigin", NID_id_smime_cti_ets_proofOfOrigin, 11, &so[1804]},
{"id-smime-cti-ets-proofOfReceipt", "id-smime-cti-ets-proofOfReceipt", NID_id_smime_cti_ets_proofOfReceipt, 11, &so[1815]},
{"id-smime-cti-ets-proofOfDelivery", "id-smime-cti-ets-proofOfDelivery", NID_id_smime_cti_ets_proofOfDelivery, 11, &so[1826]},
{"id-smime-cti-ets-proofOfSender", "id-smime-cti-ets-proofOfSender", NID_id_smime_cti_ets_proofOfSender, 11, &so[1837]},
{"id-smime-cti-ets-proofOfApproval", "id-smime-cti-ets-proofOfApproval", NID_id_smime_cti_ets_proofOfApproval, 11, &so[1848]},
{"id-smime-cti-ets-proofOfCreation", "id-smime-cti-ets-proofOfCreation", NID_id_smime_cti_ets_proofOfCreation, 11, &so[1859]},
{"MD4", "md4", NID_md4, 8, &so[1870]},
{"id-pkix-mod", "id-pkix-mod", NID_id_pkix_mod, 7, &so[1878]},
{"id-qt", "id-qt", NID_id_qt, 7, &so[1885]},
{"id-it", "id-it", NID_id_it, 7, &so[1892]},
{"id-pkip", "id-pkip", NID_id_pkip, 7, &so[1899]},
{"id-alg", "id-alg", NID_id_alg, 7, &so[1906]},
{"id-cmc", "id-cmc", NID_id_cmc, 7, &so[1913]},
{"id-on", "id-on", NID_id_on, 7, &so[1920]},
{"id-pda", "id-pda", NID_id_pda, 7, &so[1927]},
{"id-aca", "id-aca", NID_id_aca, 7, &so[1934]},
{"id-qcs", "id-qcs", NID_id_qcs, 7, &so[1941]},
{"id-cct", "id-cct", NID_id_cct, 7, &so[1948]},
{"id-pkix1-explicit-88", "id-pkix1-explicit-88", NID_id_pkix1_explicit_88, 8, &so[1955]},
{"id-pkix1-implicit-88", "id-pkix1-implicit-88", NID_id_pkix1_implicit_88, 8, &so[1963]},
{"id-pkix1-explicit-93", "id-pkix1-explicit-93", NID_id_pkix1_explicit_93, 8, &so[1971]},
{"id-pkix1-implicit-93", "id-pkix1-implicit-93", NID_id_pkix1_implicit_93, 8, &so[1979]},
{"id-mod-crmf", "id-mod-crmf", NID_id_mod_crmf, 8, &so[1987]},
{"id-mod-cmc", "id-mod-cmc", NID_id_mod_cmc, 8, &so[1995]},
{"id-mod-kea-profile-88", "id-mod-kea-profile-88", NID_id_mod_kea_profile_88, 8, &so[2003]},
{"id-mod-kea-profile-93", "id-mod-kea-profile-93", NID_id_mod_kea_profile_93, 8, &so[2011]},
{"id-mod-cmp", "id-mod-cmp", NID_id_mod_cmp, 8, &so[2019]},
{"id-mod-qualified-cert-88", "id-mod-qualified-cert-88", NID_id_mod_qualified_cert_88, 8, &so[2027]},
{"id-mod-qualified-cert-93", "id-mod-qualified-cert-93", NID_id_mod_qualified_cert_93, 8, &so[2035]},
{"id-mod-attribute-cert", "id-mod-attribute-cert", NID_id_mod_attribute_cert, 8, &so[2043]},
{"id-mod-timestamp-protocol", "id-mod-timestamp-protocol", NID_id_mod_timestamp_protocol, 8, &so[2051]},
{"id-mod-ocsp", "id-mod-ocsp", NID_id_mod_ocsp, 8, &so[2059]},
{"id-mod-dvcs", "id-mod-dvcs", NID_id_mod_dvcs, 8, &so[2067]},
{"id-mod-cmp2000", "id-mod-cmp2000", NID_id_mod_cmp2000, 8, &so[2075]},
{"biometricInfo", "Biometric Info", NID_biometricInfo, 8, &so[2083]},
{"qcStatements", "qcStatements", NID_qcStatements, 8, &so[2091]},
{"ac-auditEntity", "ac-auditEntity", NID_ac_auditEntity, 8, &so[2099]},
{"ac-targeting", "ac-targeting", NID_ac_targeting, 8, &so[2107]},
{"aaControls", "aaControls", NID_aaControls, 8, &so[2115]},
{"sbgp-ipAddrBlock", "sbgp-ipAddrBlock", NID_sbgp_ipAddrBlock, 8, &so[2123]},
{"sbgp-autonomousSysNum", "sbgp-autonomousSysNum", NID_sbgp_autonomousSysNum, 8, &so[2131]},
{"sbgp-routerIdentifier", "sbgp-routerIdentifier", NID_sbgp_routerIdentifier, 8, &so[2139]},
{"textNotice", "textNotice", NID_textNotice, 8, &so[2147]},
{"ipsecEndSystem", "IPSec End System", NID_ipsecEndSystem, 8, &so[2155]},
{"ipsecTunnel", "IPSec Tunnel", NID_ipsecTunnel, 8, &so[2163]},
{"ipsecUser", "IPSec User", NID_ipsecUser, 8, &so[2171]},
{"DVCS", "dvcs", NID_dvcs, 8, &so[2179]},
{"id-it-caProtEncCert", "id-it-caProtEncCert", NID_id_it_caProtEncCert, 8, &so[2187]},
{"id-it-signKeyPairTypes", "id-it-signKeyPairTypes", NID_id_it_signKeyPairTypes, 8, &so[2195]},
{"id-it-encKeyPairTypes", "id-it-encKeyPairTypes", NID_id_it_encKeyPairTypes, 8, &so[2203]},
{"id-it-preferredSymmAlg", "id-it-preferredSymmAlg", NID_id_it_preferredSymmAlg, 8, &so[2211]},
{"id-it-caKeyUpdateInfo", "id-it-caKeyUpdateInfo", NID_id_it_caKeyUpdateInfo, 8, &so[2219]},
{"id-it-currentCRL", "id-it-currentCRL", NID_id_it_currentCRL, 8, &so[2227]},
{"id-it-unsupportedOIDs", "id-it-unsupportedOIDs", NID_id_it_unsupportedOIDs, 8, &so[2235]},
{"id-it-subscriptionRequest", "id-it-subscriptionRequest", NID_id_it_subscriptionRequest, 8, &so[2243]},
{"id-it-subscriptionResponse", "id-it-subscriptionResponse", NID_id_it_subscriptionResponse, 8, &so[2251]},
{"id-it-keyPairParamReq", "id-it-keyPairParamReq", NID_id_it_keyPairParamReq, 8, &so[2259]},
{"id-it-keyPairParamRep", "id-it-keyPairParamRep", NID_id_it_keyPairParamRep, 8, &so[2267]},
{"id-it-revPassphrase", "id-it-revPassphrase", NID_id_it_revPassphrase, 8, &so[2275]},
{"id-it-implicitConfirm", "id-it-implicitConfirm", NID_id_it_implicitConfirm, 8, &so[2283]},
{"id-it-confirmWaitTime", "id-it-confirmWaitTime", NID_id_it_confirmWaitTime, 8, &so[2291]},
{"id-it-origPKIMessage", "id-it-origPKIMessage", NID_id_it_origPKIMessage, 8, &so[2299]},
{"id-regCtrl", "id-regCtrl", NID_id_regCtrl, 8, &so[2307]},
{"id-regInfo", "id-regInfo", NID_id_regInfo, 8, &so[2315]},
{"id-regCtrl-regToken", "id-regCtrl-regToken", NID_id_regCtrl_regToken, 9, &so[2323]},
{"id-regCtrl-authenticator", "id-regCtrl-authenticator", NID_id_regCtrl_authenticator, 9, &so[2332]},
{"id-regCtrl-pkiPublicationInfo", "id-regCtrl-pkiPublicationInfo", NID_id_regCtrl_pkiPublicationInfo, 9, &so[2341]},
{"id-regCtrl-pkiArchiveOptions", "id-regCtrl-pkiArchiveOptions", NID_id_regCtrl_pkiArchiveOptions, 9, &so[2350]},
{"id-regCtrl-oldCertID", "id-regCtrl-oldCertID", NID_id_regCtrl_oldCertID, 9, &so[2359]},
{"id-regCtrl-protocolEncrKey", "id-regCtrl-protocolEncrKey", NID_id_regCtrl_protocolEncrKey, 9, &so[2368]},
{"id-regInfo-utf8Pairs", "id-regInfo-utf8Pairs", NID_id_regInfo_utf8Pairs, 9, &so[2377]},
{"id-regInfo-certReq", "id-regInfo-certReq", NID_id_regInfo_certReq, 9, &so[2386]},
{"id-alg-des40", "id-alg-des40", NID_id_alg_des40, 8, &so[2395]},
{"id-alg-noSignature", "id-alg-noSignature", NID_id_alg_noSignature, 8, &so[2403]},
{"id-alg-dh-sig-hmac-sha1", "id-alg-dh-sig-hmac-sha1", NID_id_alg_dh_sig_hmac_sha1, 8, &so[2411]},
{"id-alg-dh-pop", "id-alg-dh-pop", NID_id_alg_dh_pop, 8, &so[2419]},
{"id-cmc-statusInfo", "id-cmc-statusInfo", NID_id_cmc_statusInfo, 8, &so[2427]},
{"id-cmc-identification", "id-cmc-identification", NID_id_cmc_identification, 8, &so[2435]},
{"id-cmc-identityProof", "id-cmc-identityProof", NID_id_cmc_identityProof, 8, &so[2443]},
{"id-cmc-dataReturn", "id-cmc-dataReturn", NID_id_cmc_dataReturn, 8, &so[2451]},
{"id-cmc-transactionId", "id-cmc-transactionId", NID_id_cmc_transactionId, 8, &so[2459]},
{"id-cmc-senderNonce", "id-cmc-senderNonce", NID_id_cmc_senderNonce, 8, &so[2467]},
{"id-cmc-recipientNonce", "id-cmc-recipientNonce", NID_id_cmc_recipientNonce, 8, &so[2475]},
{"id-cmc-addExtensions", "id-cmc-addExtensions", NID_id_cmc_addExtensions, 8, &so[2483]},
{"id-cmc-encryptedPOP", "id-cmc-encryptedPOP", NID_id_cmc_encryptedPOP, 8, &so[2491]},
{"id-cmc-decryptedPOP", "id-cmc-decryptedPOP", NID_id_cmc_decryptedPOP, 8, &so[2499]},
{"id-cmc-lraPOPWitness", "id-cmc-lraPOPWitness", NID_id_cmc_lraPOPWitness, 8, &so[2507]},
{"id-cmc-getCert", "id-cmc-getCert", NID_id_cmc_getCert, 8, &so[2515]},
{"id-cmc-getCRL", "id-cmc-getCRL", NID_id_cmc_getCRL, 8, &so[2523]},
{"id-cmc-revokeRequest", "id-cmc-revokeRequest", NID_id_cmc_revokeRequest, 8, &so[2531]},
{"id-cmc-regInfo", "id-cmc-regInfo", NID_id_cmc_regInfo, 8, &so[2539]},
{"id-cmc-responseInfo", "id-cmc-responseInfo", NID_id_cmc_responseInfo, 8, &so[2547]},
{"id-cmc-queryPending", "id-cmc-queryPending", NID_id_cmc_queryPending, 8, &so[2555]},
{"id-cmc-popLinkRandom", "id-cmc-popLinkRandom", NID_id_cmc_popLinkRandom, 8, &so[2563]},
{"id-cmc-popLinkWitness", "id-cmc-popLinkWitness", NID_id_cmc_popLinkWitness, 8, &so[2571]},
{"id-cmc-confirmCertAcceptance", "id-cmc-confirmCertAcceptance", NID_id_cmc_confirmCertAcceptance, 8, &so[2579]},
{"id-on-personalData", "id-on-personalData", NID_id_on_personalData, 8, &so[2587]},
{"id-pda-dateOfBirth", "id-pda-dateOfBirth", NID_id_pda_dateOfBirth, 8, &so[2595]},
{"id-pda-placeOfBirth", "id-pda-placeOfBirth", NID_id_pda_placeOfBirth, 8, &so[2603]},
{ NULL, NULL, NID_undef },
{"id-pda-gender", "id-pda-gender", NID_id_pda_gender, 8, &so[2611]},
{"id-pda-countryOfCitizenship", "id-pda-countryOfCitizenship", NID_id_pda_countryOfCitizenship, 8, &so[2619]},
{"id-pda-countryOfResidence", "id-pda-countryOfResidence", NID_id_pda_countryOfResidence, 8, &so[2627]},
{"id-aca-authenticationInfo", "id-aca-authenticationInfo", NID_id_aca_authenticationInfo, 8, &so[2635]},
{"id-aca-accessIdentity", "id-aca-accessIdentity", NID_id_aca_accessIdentity, 8, &so[2643]},
{"id-aca-chargingIdentity", "id-aca-chargingIdentity", NID_id_aca_chargingIdentity, 8, &so[2651]},
{"id-aca-group", "id-aca-group", NID_id_aca_group, 8, &so[2659]},
{"id-aca-role", "id-aca-role", NID_id_aca_role, 8, &so[2667]},
{"id-qcs-pkixQCSyntax-v1", "id-qcs-pkixQCSyntax-v1", NID_id_qcs_pkixQCSyntax_v1, 8, &so[2675]},
{"id-cct-crs", "id-cct-crs", NID_id_cct_crs, 8, &so[2683]},
{"id-cct-PKIData", "id-cct-PKIData", NID_id_cct_PKIData, 8, &so[2691]},
{"id-cct-PKIResponse", "id-cct-PKIResponse", NID_id_cct_PKIResponse, 8, &so[2699]},
{"ad_timestamping", "AD Time Stamping", NID_ad_timeStamping, 8, &so[2707]},
{"AD_DVCS", "ad dvcs", NID_ad_dvcs, 8, &so[2715]},
{"basicOCSPResponse", "Basic OCSP Response", NID_id_pkix_OCSP_basic, 9, &so[2723]},
{"Nonce", "OCSP Nonce", NID_id_pkix_OCSP_Nonce, 9, &so[2732]},
{"CrlID", "OCSP CRL ID", NID_id_pkix_OCSP_CrlID, 9, &so[2741]},
{"acceptableResponses", "Acceptable OCSP Responses", NID_id_pkix_OCSP_acceptableResponses, 9, &so[2750]},
{"noCheck", "OCSP No Check", NID_id_pkix_OCSP_noCheck, 9, &so[2759]},
{"archiveCutoff", "OCSP Archive Cutoff", NID_id_pkix_OCSP_archiveCutoff, 9, &so[2768]},
{"serviceLocator", "OCSP Service Locator", NID_id_pkix_OCSP_serviceLocator, 9, &so[2777]},
{"extendedStatus", "Extended OCSP Status", NID_id_pkix_OCSP_extendedStatus, 9, &so[2786]},
{"valid", "valid", NID_id_pkix_OCSP_valid, 9, &so[2795]},
{"path", "path", NID_id_pkix_OCSP_path, 9, &so[2804]},
{"trustRoot", "Trust Root", NID_id_pkix_OCSP_trustRoot, 9, &so[2813]},
{"algorithm", "algorithm", NID_algorithm, 4, &so[2822]},
{"rsaSignature", "rsaSignature", NID_rsaSignature, 5, &so[2826]},
{"X500algorithms", "directory services - algorithms", NID_X500algorithms, 2, &so[2831]},
{"ORG", "org", NID_org, 1, &so[2833]},
{"DOD", "dod", NID_dod, 2, &so[2834]},
{"IANA", "iana", NID_iana, 3, &so[2836]},
{"directory", "Directory", NID_Directory, 4, &so[2839]},
{"mgmt", "Management", NID_Management, 4, &so[2843]},
{"experimental", "Experimental", NID_Experimental, 4, &so[2847]},
{"private", "Private", NID_Private, 4, &so[2851]},
{"security", "Security", NID_Security, 4, &so[2855]},
{"snmpv2", "SNMPv2", NID_SNMPv2, 4, &so[2859]},
{"Mail", "Mail", NID_Mail, 4, &so[2863]},
{"enterprises", "Enterprises", NID_Enterprises, 5, &so[2867]},
{"dcobject", "dcObject", NID_dcObject, 9, &so[2872]},
{"DC", "domainComponent", NID_domainComponent, 10, &so[2881]},
{"domain", "Domain", NID_Domain, 10, &so[2891]},
{"NULL", "NULL", NID_joint_iso_ccitt},
{"selected-attribute-types", "Selected Attribute Types", NID_selected_attribute_types, 3, &so[2901]},
{"clearance", "clearance", NID_clearance, 4, &so[2904]},
{"RSA-MD4", "md4WithRSAEncryption", NID_md4WithRSAEncryption, 9, &so[2908]},
{"ac-proxying", "ac-proxying", NID_ac_proxying, 8, &so[2917]},
{"subjectInfoAccess", "Subject Information Access", NID_sinfo_access, 8, &so[2925]},
{"id-aca-encAttrs", "id-aca-encAttrs", NID_id_aca_encAttrs, 8, &so[2933]},
{"role", "role", NID_role, 3, &so[2941]},
{"policyConstraints", "X509v3 Policy Constraints", NID_policy_constraints, 3, &so[2944]},
{"targetInformation", "X509v3 AC Targeting", NID_target_information, 3, &so[2947]},
{"noRevAvail", "X509v3 No Revocation Available", NID_no_rev_avail, 3, &so[2950]},
{"NULL", "NULL", NID_ccitt},
{"ansi-X9-62", "ANSI X9.62", NID_ansi_X9_62, 5, &so[2953]},
{"prime-field", "prime-field", NID_X9_62_prime_field, 7, &so[2958]},
{"characteristic-two-field", "characteristic-two-field", NID_X9_62_characteristic_two_field, 7, &so[2965]},
{"id-ecPublicKey", "id-ecPublicKey", NID_X9_62_id_ecPublicKey, 7, &so[2972]},
{"prime192v1", "prime192v1", NID_X9_62_prime192v1, 8, &so[2979]},
{"prime192v2", "prime192v2", NID_X9_62_prime192v2, 8, &so[2987]},
{"prime192v3", "prime192v3", NID_X9_62_prime192v3, 8, &so[2995]},
{"prime239v1", "prime239v1", NID_X9_62_prime239v1, 8, &so[3003]},
{"prime239v2", "prime239v2", NID_X9_62_prime239v2, 8, &so[3011]},
{"prime239v3", "prime239v3", NID_X9_62_prime239v3, 8, &so[3019]},
{"prime256v1", "prime256v1", NID_X9_62_prime256v1, 8, &so[3027]},
{"ecdsa-with-SHA1", "ecdsa-with-SHA1", NID_ecdsa_with_SHA1, 7, &so[3035]},
{"CSPName", "Microsoft CSP Name", NID_ms_csp_name, 9, &so[3042]},
{"AES-128-ECB", "aes-128-ecb", NID_aes_128_ecb, 9, &so[3051]},
{"AES-128-CBC", "aes-128-cbc", NID_aes_128_cbc, 9, &so[3060]},
{"AES-128-OFB", "aes-128-ofb", NID_aes_128_ofb128, 9, &so[3069]},
{"AES-128-CFB", "aes-128-cfb", NID_aes_128_cfb128, 9, &so[3078]},
{"AES-192-ECB", "aes-192-ecb", NID_aes_192_ecb, 9, &so[3087]},
{"AES-192-CBC", "aes-192-cbc", NID_aes_192_cbc, 9, &so[3096]},
{"AES-192-OFB", "aes-192-ofb", NID_aes_192_ofb128, 9, &so[3105]},
{"AES-192-CFB", "aes-192-cfb", NID_aes_192_cfb128, 9, &so[3114]},
{"AES-256-ECB", "aes-256-ecb", NID_aes_256_ecb, 9, &so[3123]},
{"AES-256-CBC", "aes-256-cbc", NID_aes_256_cbc, 9, &so[3132]},
{"AES-256-OFB", "aes-256-ofb", NID_aes_256_ofb128, 9, &so[3141]},
{"AES-256-CFB", "aes-256-cfb", NID_aes_256_cfb128, 9, &so[3150]},
{"holdInstructionCode", "Hold Instruction Code", NID_hold_instruction_code, 3, &so[3159]},
{"holdInstructionNone", "Hold Instruction None", NID_hold_instruction_none, 7, &so[3162]},
{"holdInstructionCallIssuer", "Hold Instruction Call Issuer", NID_hold_instruction_call_issuer, 7, &so[3169]},
{"holdInstructionReject", "Hold Instruction Reject", NID_hold_instruction_reject, 7, &so[3176]},
{"data", "data", NID_data, 1, &so[3183]},
{"pss", "pss", NID_pss, 3, &so[3184]},
{"ucl", "ucl", NID_ucl, 7, &so[3187]},
{"pilot", "pilot", NID_pilot, 8, &so[3194]},
{"pilotAttributeType", "pilotAttributeType", NID_pilotAttributeType, 9, &so[3202]},
{"pilotAttributeSyntax", "pilotAttributeSyntax", NID_pilotAttributeSyntax, 9, &so[3211]},
{"pilotObjectClass", "pilotObjectClass", NID_pilotObjectClass, 9, &so[3220]},
{"pilotGroups", "pilotGroups", NID_pilotGroups, 9, &so[3229]},
{"iA5StringSyntax", "iA5StringSyntax", NID_iA5StringSyntax, 10, &so[3238]},
{"caseIgnoreIA5StringSyntax", "caseIgnoreIA5StringSyntax", NID_caseIgnoreIA5StringSyntax, 10, &so[3248]},
{"pilotObject", "pilotObject", NID_pilotObject, 10, &so[3258]},
{"pilotPerson", "pilotPerson", NID_pilotPerson, 10, &so[3268]},
{"account", "account", NID_account, 10, &so[3278]},
{"document", "document", NID_document, 10, &so[3288]},
{"room", "room", NID_room, 10, &so[3298]},
{"documentSeries", "documentSeries", NID_documentSeries, 10, &so[3308]},
{"rFC822localPart", "rFC822localPart", NID_rFC822localPart, 10, &so[3318]},
{"dNSDomain", "dNSDomain", NID_dNSDomain, 10, &so[3328]},
{"domainRelatedObject", "domainRelatedObject", NID_domainRelatedObject, 10, &so[3338]},
{"friendlyCountry", "friendlyCountry", NID_friendlyCountry, 10, &so[3348]},
{"simpleSecurityObject", "simpleSecurityObject", NID_simpleSecurityObject, 10, &so[3358]},
{"pilotOrganization", "pilotOrganization", NID_pilotOrganization, 10, &so[3368]},
{"pilotDSA", "pilotDSA", NID_pilotDSA, 10, &so[3378]},
{"qualityLabelledData", "qualityLabelledData", NID_qualityLabelledData, 10, &so[3388]},
{"UID", "userId", NID_userId, 10, &so[3398]},
{"textEncodedORAddress", "textEncodedORAddress", NID_textEncodedORAddress, 10, &so[3408]},
{"mail", "rfc822Mailbox", NID_rfc822Mailbox, 10, &so[3418]},
{"info", "info", NID_info, 10, &so[3428]},
{"favouriteDrink", "favouriteDrink", NID_favouriteDrink, 10, &so[3438]},
{"roomNumber", "roomNumber", NID_roomNumber, 10, &so[3448]},
{"photo", "photo", NID_photo, 10, &so[3458]},
{"userClass", "userClass", NID_userClass, 10, &so[3468]},
{"host", "host", NID_host, 10, &so[3478]},
{"manager", "manager", NID_manager, 10, &so[3488]},
{"documentIdentifier", "documentIdentifier", NID_documentIdentifier, 10, &so[3498]},
{"documentTitle", "documentTitle", NID_documentTitle, 10, &so[3508]},
{"documentVersion", "documentVersion", NID_documentVersion, 10, &so[3518]},
{"documentAuthor", "documentAuthor", NID_documentAuthor, 10, &so[3528]},
{"documentLocation", "documentLocation", NID_documentLocation, 10, &so[3538]},
{"homeTelephoneNumber", "homeTelephoneNumber", NID_homeTelephoneNumber, 10, &so[3548]},
{"secretary", "secretary", NID_secretary, 10, &so[3558]},
{"otherMailbox", "otherMailbox", NID_otherMailbox, 10, &so[3568]},
{"lastModifiedTime", "lastModifiedTime", NID_lastModifiedTime, 10, &so[3578]},
{"lastModifiedBy", "lastModifiedBy", NID_lastModifiedBy, 10, &so[3588]},
{"aRecord", "aRecord", NID_aRecord, 10, &so[3598]},
{"pilotAttributeType27", "pilotAttributeType27", NID_pilotAttributeType27, 10, &so[3608]},
{"mXRecord", "mXRecord", NID_mXRecord, 10, &so[3618]},
{"nSRecord", "nSRecord", NID_nSRecord, 10, &so[3628]},
{"sOARecord", "sOARecord", NID_sOARecord, 10, &so[3638]},
{"cNAMERecord", "cNAMERecord", NID_cNAMERecord, 10, &so[3648]},
{"associatedDomain", "associatedDomain", NID_associatedDomain, 10, &so[3658]},
{"associatedName", "associatedName", NID_associatedName, 10, &so[3668]},
{"homePostalAddress", "homePostalAddress", NID_homePostalAddress, 10, &so[3678]},
{"personalTitle", "personalTitle", NID_personalTitle, 10, &so[3688]},
{"mobileTelephoneNumber", "mobileTelephoneNumber", NID_mobileTelephoneNumber, 10, &so[3698]},
{"pagerTelephoneNumber", "pagerTelephoneNumber", NID_pagerTelephoneNumber, 10, &so[3708]},
{"friendlyCountryName", "friendlyCountryName", NID_friendlyCountryName, 10, &so[3718]},
{"organizationalStatus", "organizationalStatus", NID_organizationalStatus, 10, &so[3728]},
{"janetMailbox", "janetMailbox", NID_janetMailbox, 10, &so[3738]},
{"mailPreferenceOption", "mailPreferenceOption", NID_mailPreferenceOption, 10, &so[3748]},
{"buildingName", "buildingName", NID_buildingName, 10, &so[3758]},
{"dSAQuality", "dSAQuality", NID_dSAQuality, 10, &so[3768]},
{"singleLevelQuality", "singleLevelQuality", NID_singleLevelQuality, 10, &so[3778]},
{"subtreeMinimumQuality", "subtreeMinimumQuality", NID_subtreeMinimumQuality, 10, &so[3788]},
{"subtreeMaximumQuality", "subtreeMaximumQuality", NID_subtreeMaximumQuality, 10, &so[3798]},
{"personalSignature", "personalSignature", NID_personalSignature, 10, &so[3808]},
{"dITRedirect", "dITRedirect", NID_dITRedirect, 10, &so[3818]},
{"audio", "audio", NID_audio, 10, &so[3828]},
{"documentPublisher", "documentPublisher", NID_documentPublisher, 10, &so[3838]},
{"x500UniqueIdentifier", "x500UniqueIdentifier", NID_x500UniqueIdentifier, 3, &so[3848]},
{"mime-mhs", "MIME MHS", NID_mime_mhs, 5, &so[3851]},
{"mime-mhs-headings", "mime-mhs-headings", NID_mime_mhs_headings, 6, &so[3856]},
{"mime-mhs-bodies", "mime-mhs-bodies", NID_mime_mhs_bodies, 6, &so[3862]},
{"id-hex-partial-message", "id-hex-partial-message", NID_id_hex_partial_message, 7, &so[3868]},
{"id-hex-multipart-message", "id-hex-multipart-message", NID_id_hex_multipart_message, 7, &so[3875]},
{"generationQualifier", "generationQualifier", NID_generationQualifier, 3, &so[3882]},
{"pseudonym", "pseudonym", NID_pseudonym, 3, &so[3885]},
{ NULL, NULL, NID_undef },
{"id-set", "Secure Electronic Transactions", NID_id_set, 2, &so[3888]},
{"set-ctype", "content types", NID_set_ctype, 3, &so[3890]},
{"set-msgExt", "message extensions", NID_set_msgExt, 3, &so[3893]},
{"set-attr", "set-attr", NID_set_attr, 3, &so[3896]},
{"set-policy", "set-policy", NID_set_policy, 3, &so[3899]},
{"set-certExt", "certificate extensions", NID_set_certExt, 3, &so[3902]},
{"set-brand", "set-brand", NID_set_brand, 3, &so[3905]},
{"setct-PANData", "setct-PANData", NID_setct_PANData, 4, &so[3908]},
{"setct-PANToken", "setct-PANToken", NID_setct_PANToken, 4, &so[3912]},
{"setct-PANOnly", "setct-PANOnly", NID_setct_PANOnly, 4, &so[3916]},
{"setct-OIData", "setct-OIData", NID_setct_OIData, 4, &so[3920]},
{"setct-PI", "setct-PI", NID_setct_PI, 4, &so[3924]},
{"setct-PIData", "setct-PIData", NID_setct_PIData, 4, &so[3928]},
{"setct-PIDataUnsigned", "setct-PIDataUnsigned", NID_setct_PIDataUnsigned, 4, &so[3932]},
{"setct-HODInput", "setct-HODInput", NID_setct_HODInput, 4, &so[3936]},
{"setct-AuthResBaggage", "setct-AuthResBaggage", NID_setct_AuthResBaggage, 4, &so[3940]},
{"setct-AuthRevReqBaggage", "setct-AuthRevReqBaggage", NID_setct_AuthRevReqBaggage, 4, &so[3944]},
{"setct-AuthRevResBaggage", "setct-AuthRevResBaggage", NID_setct_AuthRevResBaggage, 4, &so[3948]},
{"setct-CapTokenSeq", "setct-CapTokenSeq", NID_setct_CapTokenSeq, 4, &so[3952]},
{"setct-PInitResData", "setct-PInitResData", NID_setct_PInitResData, 4, &so[3956]},
{"setct-PI-TBS", "setct-PI-TBS", NID_setct_PI_TBS, 4, &so[3960]},
{"setct-PResData", "setct-PResData", NID_setct_PResData, 4, &so[3964]},
{"setct-AuthReqTBS", "setct-AuthReqTBS", NID_setct_AuthReqTBS, 4, &so[3968]},
{"setct-AuthResTBS", "setct-AuthResTBS", NID_setct_AuthResTBS, 4, &so[3972]},
{"setct-AuthResTBSX", "setct-AuthResTBSX", NID_setct_AuthResTBSX, 4, &so[3976]},
{"setct-AuthTokenTBS", "setct-AuthTokenTBS", NID_setct_AuthTokenTBS, 4, &so[3980]},
{"setct-CapTokenData", "setct-CapTokenData", NID_setct_CapTokenData, 4, &so[3984]},
{"setct-CapTokenTBS", "setct-CapTokenTBS", NID_setct_CapTokenTBS, 4, &so[3988]},
{"setct-AcqCardCodeMsg", "setct-AcqCardCodeMsg", NID_setct_AcqCardCodeMsg, 4, &so[3992]},
{"setct-AuthRevReqTBS", "setct-AuthRevReqTBS", NID_setct_AuthRevReqTBS, 4, &so[3996]},
{"setct-AuthRevResData", "setct-AuthRevResData", NID_setct_AuthRevResData, 4, &so[4000]},
{"setct-AuthRevResTBS", "setct-AuthRevResTBS", NID_setct_AuthRevResTBS, 4, &so[4004]},
{"setct-CapReqTBS", "setct-CapReqTBS", NID_setct_CapReqTBS, 4, &so[4008]},
{"setct-CapReqTBSX", "setct-CapReqTBSX", NID_setct_CapReqTBSX, 4, &so[4012]},
{"setct-CapResData", "setct-CapResData", NID_setct_CapResData, 4, &so[4016]},
{"setct-CapRevReqTBS", "setct-CapRevReqTBS", NID_setct_CapRevReqTBS, 4, &so[4020]},
{"setct-CapRevReqTBSX", "setct-CapRevReqTBSX", NID_setct_CapRevReqTBSX, 4, &so[4024]},
{"setct-CapRevResData", "setct-CapRevResData", NID_setct_CapRevResData, 4, &so[4028]},
{"setct-CredReqTBS", "setct-CredReqTBS", NID_setct_CredReqTBS, 4, &so[4032]},
{"setct-CredReqTBSX", "setct-CredReqTBSX", NID_setct_CredReqTBSX, 4, &so[4036]},
{"setct-CredResData", "setct-CredResData", NID_setct_CredResData, 4, &so[4040]},
{"setct-CredRevReqTBS", "setct-CredRevReqTBS", NID_setct_CredRevReqTBS, 4, &so[4044]},
{"setct-CredRevReqTBSX", "setct-CredRevReqTBSX", NID_setct_CredRevReqTBSX, 4, &so[4048]},
{"setct-CredRevResData", "setct-CredRevResData", NID_setct_CredRevResData, 4, &so[4052]},
{"setct-PCertReqData", "setct-PCertReqData", NID_setct_PCertReqData, 4, &so[4056]},
{"setct-PCertResTBS", "setct-PCertResTBS", NID_setct_PCertResTBS, 4, &so[4060]},
{"setct-BatchAdminReqData", "setct-BatchAdminReqData", NID_setct_BatchAdminReqData, 4, &so[4064]},
{"setct-BatchAdminResData", "setct-BatchAdminResData", NID_setct_BatchAdminResData, 4, &so[4068]},
{"setct-CardCInitResTBS", "setct-CardCInitResTBS", NID_setct_CardCInitResTBS, 4, &so[4072]},
{"setct-MeAqCInitResTBS", "setct-MeAqCInitResTBS", NID_setct_MeAqCInitResTBS, 4, &so[4076]},
{"setct-RegFormResTBS", "setct-RegFormResTBS", NID_setct_RegFormResTBS, 4, &so[4080]},
{"setct-CertReqData", "setct-CertReqData", NID_setct_CertReqData, 4, &so[4084]},
{"setct-CertReqTBS", "setct-CertReqTBS", NID_setct_CertReqTBS, 4, &so[4088]},
{"setct-CertResData", "setct-CertResData", NID_setct_CertResData, 4, &so[4092]},
{"setct-CertInqReqTBS", "setct-CertInqReqTBS", NID_setct_CertInqReqTBS, 4, &so[4096]},
{"setct-ErrorTBS", "setct-ErrorTBS", NID_setct_ErrorTBS, 4, &so[4100]},
{"setct-PIDualSignedTBE", "setct-PIDualSignedTBE", NID_setct_PIDualSignedTBE, 4, &so[4104]},
{"setct-PIUnsignedTBE", "setct-PIUnsignedTBE", NID_setct_PIUnsignedTBE, 4, &so[4108]},
{"setct-AuthReqTBE", "setct-AuthReqTBE", NID_setct_AuthReqTBE, 4, &so[4112]},
{"setct-AuthResTBE", "setct-AuthResTBE", NID_setct_AuthResTBE, 4, &so[4116]},
{"setct-AuthResTBEX", "setct-AuthResTBEX", NID_setct_AuthResTBEX, 4, &so[4120]},
{"setct-AuthTokenTBE", "setct-AuthTokenTBE", NID_setct_AuthTokenTBE, 4, &so[4124]},
{"setct-CapTokenTBE", "setct-CapTokenTBE", NID_setct_CapTokenTBE, 4, &so[4128]},
{"setct-CapTokenTBEX", "setct-CapTokenTBEX", NID_setct_CapTokenTBEX, 4, &so[4132]},
{"setct-AcqCardCodeMsgTBE", "setct-AcqCardCodeMsgTBE", NID_setct_AcqCardCodeMsgTBE, 4, &so[4136]},
{"setct-AuthRevReqTBE", "setct-AuthRevReqTBE", NID_setct_AuthRevReqTBE, 4, &so[4140]},
{"setct-AuthRevResTBE", "setct-AuthRevResTBE", NID_setct_AuthRevResTBE, 4, &so[4144]},
{"setct-AuthRevResTBEB", "setct-AuthRevResTBEB", NID_setct_AuthRevResTBEB, 4, &so[4148]},
{"setct-CapReqTBE", "setct-CapReqTBE", NID_setct_CapReqTBE, 4, &so[4152]},
{"setct-CapReqTBEX", "setct-CapReqTBEX", NID_setct_CapReqTBEX, 4, &so[4156]},
{"setct-CapResTBE", "setct-CapResTBE", NID_setct_CapResTBE, 4, &so[4160]},
{"setct-CapRevReqTBE", "setct-CapRevReqTBE", NID_setct_CapRevReqTBE, 4, &so[4164]},
{"setct-CapRevReqTBEX", "setct-CapRevReqTBEX", NID_setct_CapRevReqTBEX, 4, &so[4168]},
{"setct-CapRevResTBE", "setct-CapRevResTBE", NID_setct_CapRevResTBE, 4, &so[4172]},
{"setct-CredReqTBE", "setct-CredReqTBE", NID_setct_CredReqTBE, 4, &so[4176]},
{"setct-CredReqTBEX", "setct-CredReqTBEX", NID_setct_CredReqTBEX, 4, &so[4180]},
{"setct-CredResTBE", "setct-CredResTBE", NID_setct_CredResTBE, 4, &so[4184]},
{"setct-CredRevReqTBE", "setct-CredRevReqTBE", NID_setct_CredRevReqTBE, 4, &so[4188]},
{"setct-CredRevReqTBEX", "setct-CredRevReqTBEX", NID_setct_CredRevReqTBEX, 4, &so[4192]},
{"setct-CredRevResTBE", "setct-CredRevResTBE", NID_setct_CredRevResTBE, 4, &so[4196]},
{"setct-BatchAdminReqTBE", "setct-BatchAdminReqTBE", NID_setct_BatchAdminReqTBE, 4, &so[4200]},
{"setct-BatchAdminResTBE", "setct-BatchAdminResTBE", NID_setct_BatchAdminResTBE, 4, &so[4204]},
{"setct-RegFormReqTBE", "setct-RegFormReqTBE", NID_setct_RegFormReqTBE, 4, &so[4208]},
{"setct-CertReqTBE", "setct-CertReqTBE", NID_setct_CertReqTBE, 4, &so[4212]},
{"setct-CertReqTBEX", "setct-CertReqTBEX", NID_setct_CertReqTBEX, 4, &so[4216]},
{"setct-CertResTBE", "setct-CertResTBE", NID_setct_CertResTBE, 4, &so[4220]},
{"setct-CRLNotificationTBS", "setct-CRLNotificationTBS", NID_setct_CRLNotificationTBS, 4, &so[4224]},
{"setct-CRLNotificationResTBS", "setct-CRLNotificationResTBS", NID_setct_CRLNotificationResTBS, 4, &so[4228]},
{"setct-BCIDistributionTBS", "setct-BCIDistributionTBS", NID_setct_BCIDistributionTBS, 4, &so[4232]},
{"setext-genCrypt", "generic cryptogram", NID_setext_genCrypt, 4, &so[4236]},
{"setext-miAuth", "merchant initiated auth", NID_setext_miAuth, 4, &so[4240]},
{"setext-pinSecure", "setext-pinSecure", NID_setext_pinSecure, 4, &so[4244]},
{"setext-pinAny", "setext-pinAny", NID_setext_pinAny, 4, &so[4248]},
{"setext-track2", "setext-track2", NID_setext_track2, 4, &so[4252]},
{"setext-cv", "additional verification", NID_setext_cv, 4, &so[4256]},
{"set-policy-root", "set-policy-root", NID_set_policy_root, 4, &so[4260]},
{"setCext-hashedRoot", "setCext-hashedRoot", NID_setCext_hashedRoot, 4, &so[4264]},
{"setCext-certType", "setCext-certType", NID_setCext_certType, 4, &so[4268]},
{"setCext-merchData", "setCext-merchData", NID_setCext_merchData, 4, &so[4272]},
{"setCext-cCertRequired", "setCext-cCertRequired", NID_setCext_cCertRequired, 4, &so[4276]},
{"setCext-tunneling", "setCext-tunneling", NID_setCext_tunneling, 4, &so[4280]},
{"setCext-setExt", "setCext-setExt", NID_setCext_setExt, 4, &so[4284]},
{"setCext-setQualf", "setCext-setQualf", NID_setCext_setQualf, 4, &so[4288]},
{"setCext-PGWYcapabilities", "setCext-PGWYcapabilities", NID_setCext_PGWYcapabilities, 4, &so[4292]},
{"setCext-TokenIdentifier", "setCext-TokenIdentifier", NID_setCext_TokenIdentifier, 4, &so[4296]},
{"setCext-Track2Data", "setCext-Track2Data", NID_setCext_Track2Data, 4, &so[4300]},
{"setCext-TokenType", "setCext-TokenType", NID_setCext_TokenType, 4, &so[4304]},
{"setCext-IssuerCapabilities", "setCext-IssuerCapabilities", NID_setCext_IssuerCapabilities, 4, &so[4308]},
{"setAttr-Cert", "setAttr-Cert", NID_setAttr_Cert, 4, &so[4312]},
{"setAttr-PGWYcap", "payment gateway capabilities", NID_setAttr_PGWYcap, 4, &so[4316]},
{"setAttr-TokenType", "setAttr-TokenType", NID_setAttr_TokenType, 4, &so[4320]},
{"setAttr-IssCap", "issuer capabilities", NID_setAttr_IssCap, 4, &so[4324]},
{"set-rootKeyThumb", "set-rootKeyThumb", NID_set_rootKeyThumb, 5, &so[4328]},
{"set-addPolicy", "set-addPolicy", NID_set_addPolicy, 5, &so[4333]},
{"setAttr-Token-EMV", "setAttr-Token-EMV", NID_setAttr_Token_EMV, 5, &so[4338]},
{"setAttr-Token-B0Prime", "setAttr-Token-B0Prime", NID_setAttr_Token_B0Prime, 5, &so[4343]},
{"setAttr-IssCap-CVM", "setAttr-IssCap-CVM", NID_setAttr_IssCap_CVM, 5, &so[4348]},
{"setAttr-IssCap-T2", "setAttr-IssCap-T2", NID_setAttr_IssCap_T2, 5, &so[4353]},
{"setAttr-IssCap-Sig", "setAttr-IssCap-Sig", NID_setAttr_IssCap_Sig, 5, &so[4358]},
{"setAttr-GenCryptgrm", "generate cryptogram", NID_setAttr_GenCryptgrm, 6, &so[4363]},
{"setAttr-T2Enc", "encrypted track 2", NID_setAttr_T2Enc, 6, &so[4369]},
{"setAttr-T2cleartxt", "cleartext track 2", NID_setAttr_T2cleartxt, 6, &so[4375]},
{"setAttr-TokICCsig", "ICC or token signature", NID_setAttr_TokICCsig, 6, &so[4381]},
{"setAttr-SecDevSig", "secure device signature", NID_setAttr_SecDevSig, 6, &so[4387]},
{"set-brand-IATA-ATA", "set-brand-IATA-ATA", NID_set_brand_IATA_ATA, 4, &so[4393]},
{"set-brand-Diners", "set-brand-Diners", NID_set_brand_Diners, 4, &so[4397]},
{"set-brand-AmericanExpress", "set-brand-AmericanExpress", NID_set_brand_AmericanExpress, 4, &so[4401]},
{"set-brand-JCB", "set-brand-JCB", NID_set_brand_JCB, 4, &so[4405]},
{"set-brand-Visa", "set-brand-Visa", NID_set_brand_Visa, 4, &so[4409]},
{"set-brand-MasterCard", "set-brand-MasterCard", NID_set_brand_MasterCard, 4, &so[4413]},
{"set-brand-Novus", "set-brand-Novus", NID_set_brand_Novus, 5, &so[4417]},
{"DES-CDMF", "des-cdmf", NID_des_cdmf, 8, &so[4422]},
{"rsaOAEPEncryptionSET", "rsaOAEPEncryptionSET", NID_rsaOAEPEncryptionSET, 9, &so[4430]},
{"ITU-T", "itu-t", NID_itu_t},
{"JOINT-ISO-ITU-T", "joint-iso-itu-t", NID_joint_iso_itu_t},
{"international-organizations", "International Organizations", NID_international_organizations, 1, &so[4439]},
{"msSmartcardLogin", "Microsoft Smartcardlogin", NID_ms_smartcard_login, 10, &so[4440]},
{"msUPN", "Microsoft Universal Principal Name", NID_ms_upn, 10, &so[4450]},
{"AES-128-CFB1", "aes-128-cfb1", NID_aes_128_cfb1},
{"AES-192-CFB1", "aes-192-cfb1", NID_aes_192_cfb1},
{"AES-256-CFB1", "aes-256-cfb1", NID_aes_256_cfb1},
{"AES-128-CFB8", "aes-128-cfb8", NID_aes_128_cfb8},
{"AES-192-CFB8", "aes-192-cfb8", NID_aes_192_cfb8},
{"AES-256-CFB8", "aes-256-cfb8", NID_aes_256_cfb8},
{"DES-CFB1", "des-cfb1", NID_des_cfb1},
{"DES-CFB8", "des-cfb8", NID_des_cfb8},
{"DES-EDE3-CFB1", "des-ede3-cfb1", NID_des_ede3_cfb1},
{"DES-EDE3-CFB8", "des-ede3-cfb8", NID_des_ede3_cfb8},
{"street", "streetAddress", NID_streetAddress, 3, &so[4460]},
{"postalCode", "postalCode", NID_postalCode, 3, &so[4463]},
{"id-ppl", "id-ppl", NID_id_ppl, 7, &so[4466]},
{"proxyCertInfo", "Proxy Certificate Information", NID_proxyCertInfo, 8, &so[4473]},
{"id-ppl-anyLanguage", "Any language", NID_id_ppl_anyLanguage, 8, &so[4481]},
{"id-ppl-inheritAll", "Inherit all", NID_id_ppl_inheritAll, 8, &so[4489]},
{"nameConstraints", "X509v3 Name Constraints", NID_name_constraints, 3, &so[4497]},
{"id-ppl-independent", "Independent", NID_Independent, 8, &so[4500]},
{"RSA-SHA256", "sha256WithRSAEncryption", NID_sha256WithRSAEncryption, 9, &so[4508]},
{"RSA-SHA384", "sha384WithRSAEncryption", NID_sha384WithRSAEncryption, 9, &so[4517]},
{"RSA-SHA512", "sha512WithRSAEncryption", NID_sha512WithRSAEncryption, 9, &so[4526]},
{"RSA-SHA224", "sha224WithRSAEncryption", NID_sha224WithRSAEncryption, 9, &so[4535]},
{"SHA256", "sha256", NID_sha256, 9, &so[4544]},
{"SHA384", "sha384", NID_sha384, 9, &so[4553]},
{"SHA512", "sha512", NID_sha512, 9, &so[4562]},
{"SHA224", "sha224", NID_sha224, 9, &so[4571]},
{"identified-organization", "identified-organization", NID_identified_organization, 1, &so[4580]},
{"certicom-arc", "certicom-arc", NID_certicom_arc, 3, &so[4581]},
{"wap", "wap", NID_wap, 2, &so[4584]},
{"wap-wsg", "wap-wsg", NID_wap_wsg, 3, &so[4586]},
{"id-characteristic-two-basis", "id-characteristic-two-basis", NID_X9_62_id_characteristic_two_basis, 8, &so[4589]},
{"onBasis", "onBasis", NID_X9_62_onBasis, 9, &so[4597]},
{"tpBasis", "tpBasis", NID_X9_62_tpBasis, 9, &so[4606]},
{"ppBasis", "ppBasis", NID_X9_62_ppBasis, 9, &so[4615]},
{"c2pnb163v1", "c2pnb163v1", NID_X9_62_c2pnb163v1, 8, &so[4624]},
{"c2pnb163v2", "c2pnb163v2", NID_X9_62_c2pnb163v2, 8, &so[4632]},
{"c2pnb163v3", "c2pnb163v3", NID_X9_62_c2pnb163v3, 8, &so[4640]},
{"c2pnb176v1", "c2pnb176v1", NID_X9_62_c2pnb176v1, 8, &so[4648]},
{"c2tnb191v1", "c2tnb191v1", NID_X9_62_c2tnb191v1, 8, &so[4656]},
{"c2tnb191v2", "c2tnb191v2", NID_X9_62_c2tnb191v2, 8, &so[4664]},
{"c2tnb191v3", "c2tnb191v3", NID_X9_62_c2tnb191v3, 8, &so[4672]},
{"c2onb191v4", "c2onb191v4", NID_X9_62_c2onb191v4, 8, &so[4680]},
{"c2onb191v5", "c2onb191v5", NID_X9_62_c2onb191v5, 8, &so[4688]},
{"c2pnb208w1", "c2pnb208w1", NID_X9_62_c2pnb208w1, 8, &so[4696]},
{"c2tnb239v1", "c2tnb239v1", NID_X9_62_c2tnb239v1, 8, &so[4704]},
{"c2tnb239v2", "c2tnb239v2", NID_X9_62_c2tnb239v2, 8, &so[4712]},
{"c2tnb239v3", "c2tnb239v3", NID_X9_62_c2tnb239v3, 8, &so[4720]},
{"c2onb239v4", "c2onb239v4", NID_X9_62_c2onb239v4, 8, &so[4728]},
{"c2onb239v5", "c2onb239v5", NID_X9_62_c2onb239v5, 8, &so[4736]},
{"c2pnb272w1", "c2pnb272w1", NID_X9_62_c2pnb272w1, 8, &so[4744]},
{"c2pnb304w1", "c2pnb304w1", NID_X9_62_c2pnb304w1, 8, &so[4752]},
{"c2tnb359v1", "c2tnb359v1", NID_X9_62_c2tnb359v1, 8, &so[4760]},
{"c2pnb368w1", "c2pnb368w1", NID_X9_62_c2pnb368w1, 8, &so[4768]},
{"c2tnb431r1", "c2tnb431r1", NID_X9_62_c2tnb431r1, 8, &so[4776]},
{"secp112r1", "secp112r1", NID_secp112r1, 5, &so[4784]},
{"secp112r2", "secp112r2", NID_secp112r2, 5, &so[4789]},
{"secp128r1", "secp128r1", NID_secp128r1, 5, &so[4794]},
{"secp128r2", "secp128r2", NID_secp128r2, 5, &so[4799]},
{"secp160k1", "secp160k1", NID_secp160k1, 5, &so[4804]},
{"secp160r1", "secp160r1", NID_secp160r1, 5, &so[4809]},
{"secp160r2", "secp160r2", NID_secp160r2, 5, &so[4814]},
{"secp192k1", "secp192k1", NID_secp192k1, 5, &so[4819]},
{"secp224k1", "secp224k1", NID_secp224k1, 5, &so[4824]},
{"secp224r1", "secp224r1", NID_secp224r1, 5, &so[4829]},
{"secp256k1", "secp256k1", NID_secp256k1, 5, &so[4834]},
{"secp384r1", "secp384r1", NID_secp384r1, 5, &so[4839]},
{"secp521r1", "secp521r1", NID_secp521r1, 5, &so[4844]},
{"sect113r1", "sect113r1", NID_sect113r1, 5, &so[4849]},
{"sect113r2", "sect113r2", NID_sect113r2, 5, &so[4854]},
{"sect131r1", "sect131r1", NID_sect131r1, 5, &so[4859]},
{"sect131r2", "sect131r2", NID_sect131r2, 5, &so[4864]},
{"sect163k1", "sect163k1", NID_sect163k1, 5, &so[4869]},
{"sect163r1", "sect163r1", NID_sect163r1, 5, &so[4874]},
{"sect163r2", "sect163r2", NID_sect163r2, 5, &so[4879]},
{"sect193r1", "sect193r1", NID_sect193r1, 5, &so[4884]},
{"sect193r2", "sect193r2", NID_sect193r2, 5, &so[4889]},
{"sect233k1", "sect233k1", NID_sect233k1, 5, &so[4894]},
{"sect233r1", "sect233r1", NID_sect233r1, 5, &so[4899]},
{"sect239k1", "sect239k1", NID_sect239k1, 5, &so[4904]},
{"sect283k1", "sect283k1", NID_sect283k1, 5, &so[4909]},
{"sect283r1", "sect283r1", NID_sect283r1, 5, &so[4914]},
{"sect409k1", "sect409k1", NID_sect409k1, 5, &so[4919]},
{"sect409r1", "sect409r1", NID_sect409r1, 5, &so[4924]},
{"sect571k1", "sect571k1", NID_sect571k1, 5, &so[4929]},
{"sect571r1", "sect571r1", NID_sect571r1, 5, &so[4934]},
{"wap-wsg-idm-ecid-wtls1", "wap-wsg-idm-ecid-wtls1", NID_wap_wsg_idm_ecid_wtls1, 5, &so[4939]},
{"wap-wsg-idm-ecid-wtls3", "wap-wsg-idm-ecid-wtls3", NID_wap_wsg_idm_ecid_wtls3, 5, &so[4944]},
{"wap-wsg-idm-ecid-wtls4", "wap-wsg-idm-ecid-wtls4", NID_wap_wsg_idm_ecid_wtls4, 5, &so[4949]},
{"wap-wsg-idm-ecid-wtls5", "wap-wsg-idm-ecid-wtls5", NID_wap_wsg_idm_ecid_wtls5, 5, &so[4954]},
{"wap-wsg-idm-ecid-wtls6", "wap-wsg-idm-ecid-wtls6", NID_wap_wsg_idm_ecid_wtls6, 5, &so[4959]},
{"wap-wsg-idm-ecid-wtls7", "wap-wsg-idm-ecid-wtls7", NID_wap_wsg_idm_ecid_wtls7, 5, &so[4964]},
{"wap-wsg-idm-ecid-wtls8", "wap-wsg-idm-ecid-wtls8", NID_wap_wsg_idm_ecid_wtls8, 5, &so[4969]},
{"wap-wsg-idm-ecid-wtls9", "wap-wsg-idm-ecid-wtls9", NID_wap_wsg_idm_ecid_wtls9, 5, &so[4974]},
{"wap-wsg-idm-ecid-wtls10", "wap-wsg-idm-ecid-wtls10", NID_wap_wsg_idm_ecid_wtls10, 5, &so[4979]},
{"wap-wsg-idm-ecid-wtls11", "wap-wsg-idm-ecid-wtls11", NID_wap_wsg_idm_ecid_wtls11, 5, &so[4984]},
{"wap-wsg-idm-ecid-wtls12", "wap-wsg-idm-ecid-wtls12", NID_wap_wsg_idm_ecid_wtls12, 5, &so[4989]},
{"anyPolicy", "X509v3 Any Policy", NID_any_policy, 4, &so[4994]},
{"policyMappings", "X509v3 Policy Mappings", NID_policy_mappings, 3, &so[4998]},
{"inhibitAnyPolicy", "X509v3 Inhibit Any Policy", NID_inhibit_any_policy, 3, &so[5001]},
{"Oakley-EC2N-3", "ipsec3", NID_ipsec3},
{"Oakley-EC2N-4", "ipsec4", NID_ipsec4},
{"CAMELLIA-128-CBC", "camellia-128-cbc", NID_camellia_128_cbc, 11, &so[5004]},
{"CAMELLIA-192-CBC", "camellia-192-cbc", NID_camellia_192_cbc, 11, &so[5015]},
{"CAMELLIA-256-CBC", "camellia-256-cbc", NID_camellia_256_cbc, 11, &so[5026]},
{"CAMELLIA-128-ECB", "camellia-128-ecb", NID_camellia_128_ecb, 8, &so[5037]},
{"CAMELLIA-192-ECB", "camellia-192-ecb", NID_camellia_192_ecb, 8, &so[5045]},
{"CAMELLIA-256-ECB", "camellia-256-ecb", NID_camellia_256_ecb, 8, &so[5053]},
{"CAMELLIA-128-CFB", "camellia-128-cfb", NID_camellia_128_cfb128, 8, &so[5061]},
{"CAMELLIA-192-CFB", "camellia-192-cfb", NID_camellia_192_cfb128, 8, &so[5069]},
{"CAMELLIA-256-CFB", "camellia-256-cfb", NID_camellia_256_cfb128, 8, &so[5077]},
{"CAMELLIA-128-CFB1", "camellia-128-cfb1", NID_camellia_128_cfb1},
{"CAMELLIA-192-CFB1", "camellia-192-cfb1", NID_camellia_192_cfb1},
{"CAMELLIA-256-CFB1", "camellia-256-cfb1", NID_camellia_256_cfb1},
{"CAMELLIA-128-CFB8", "camellia-128-cfb8", NID_camellia_128_cfb8},
{"CAMELLIA-192-CFB8", "camellia-192-cfb8", NID_camellia_192_cfb8},
{"CAMELLIA-256-CFB8", "camellia-256-cfb8", NID_camellia_256_cfb8},
{"CAMELLIA-128-OFB", "camellia-128-ofb", NID_camellia_128_ofb128, 8, &so[5085]},
{"CAMELLIA-192-OFB", "camellia-192-ofb", NID_camellia_192_ofb128, 8, &so[5093]},
{"CAMELLIA-256-OFB", "camellia-256-ofb", NID_camellia_256_ofb128, 8, &so[5101]},
{"subjectDirectoryAttributes", "X509v3 Subject Directory Attributes", NID_subject_directory_attributes, 3, &so[5109]},
{"issuingDistributionPoint", "X509v3 Issuing Distribution Point", NID_issuing_distribution_point, 3, &so[5112]},
{"certificateIssuer", "X509v3 Certificate Issuer", NID_certificate_issuer, 3, &so[5115]},
{ NULL, NULL, NID_undef },
{"KISA", "kisa", NID_kisa, 6, &so[5118]},
{ NULL, NULL, NID_undef },
{ NULL, NULL, NID_undef },
{"SEED-ECB", "seed-ecb", NID_seed_ecb, 8, &so[5124]},
{"SEED-CBC", "seed-cbc", NID_seed_cbc, 8, &so[5132]},
{"SEED-OFB", "seed-ofb", NID_seed_ofb128, 8, &so[5140]},
{"SEED-CFB", "seed-cfb", NID_seed_cfb128, 8, &so[5148]},
{"HMAC-MD5", "hmac-md5", NID_hmac_md5, 8, &so[5156]},
{"HMAC-SHA1", "hmac-sha1", NID_hmac_sha1, 8, &so[5164]},
{"id-PasswordBasedMAC", "password based MAC", NID_id_PasswordBasedMAC, 9, &so[5172]},
{"id-DHBasedMac", "Diffie-Hellman based MAC", NID_id_DHBasedMac, 9, &so[5181]},
{"id-it-suppLangTags", "id-it-suppLangTags", NID_id_it_suppLangTags, 8, &so[5190]},
{"caRepository", "CA Repository", NID_caRepository, 8, &so[5198]},
{"id-smime-ct-compressedData", "id-smime-ct-compressedData", NID_id_smime_ct_compressedData, 11, &so[5206]},
{"id-ct-asciiTextWithCRLF", "id-ct-asciiTextWithCRLF", NID_id_ct_asciiTextWithCRLF, 11, &so[5217]},
{"id-aes128-wrap", "id-aes128-wrap", NID_id_aes128_wrap, 9, &so[5228]},
{"id-aes192-wrap", "id-aes192-wrap", NID_id_aes192_wrap, 9, &so[5237]},
{"id-aes256-wrap", "id-aes256-wrap", NID_id_aes256_wrap, 9, &so[5246]},
{"ecdsa-with-Recommended", "ecdsa-with-Recommended", NID_ecdsa_with_Recommended, 7, &so[5255]},
{"ecdsa-with-Specified", "ecdsa-with-Specified", NID_ecdsa_with_Specified, 7, &so[5262]},
{"ecdsa-with-SHA224", "ecdsa-with-SHA224", NID_ecdsa_with_SHA224, 8, &so[5269]},
{"ecdsa-with-SHA256", "ecdsa-with-SHA256", NID_ecdsa_with_SHA256, 8, &so[5277]},
{"ecdsa-with-SHA384", "ecdsa-with-SHA384", NID_ecdsa_with_SHA384, 8, &so[5285]},
{"ecdsa-with-SHA512", "ecdsa-with-SHA512", NID_ecdsa_with_SHA512, 8, &so[5293]},
{"hmacWithMD5", "hmacWithMD5", NID_hmacWithMD5, 8, &so[5301]},
{"hmacWithSHA224", "hmacWithSHA224", NID_hmacWithSHA224, 8, &so[5309]},
{"hmacWithSHA256", "hmacWithSHA256", NID_hmacWithSHA256, 8, &so[5317]},
{"hmacWithSHA384", "hmacWithSHA384", NID_hmacWithSHA384, 8, &so[5325]},
{"hmacWithSHA512", "hmacWithSHA512", NID_hmacWithSHA512, 8, &so[5333]},
{"dsa_with_SHA224", "dsa_with_SHA224", NID_dsa_with_SHA224, 9, &so[5341]},
{"dsa_with_SHA256", "dsa_with_SHA256", NID_dsa_with_SHA256, 9, &so[5350]},
{"whirlpool", "whirlpool", NID_whirlpool, 6, &so[5359]},
{"cryptopro", "cryptopro", NID_cryptopro, 5, &so[5365]},
{"cryptocom", "cryptocom", NID_cryptocom, 5, &so[5370]},
{"id-GostR3411-94-with-GostR3410-2001", "GOST R 34.11-94 with GOST R 34.10-2001", NID_id_GostR3411_94_with_GostR3410_2001, 6, &so[5375]},
{"id-GostR3411-94-with-GostR3410-94", "GOST R 34.11-94 with GOST R 34.10-94", NID_id_GostR3411_94_with_GostR3410_94, 6, &so[5381]},
{"md_gost94", "GOST R 34.11-94", NID_id_GostR3411_94, 6, &so[5387]},
{"id-HMACGostR3411-94", "HMAC GOST 34.11-94", NID_id_HMACGostR3411_94, 6, &so[5393]},
{"gost2001", "GOST R 34.10-2001", NID_id_GostR3410_2001, 6, &so[5399]},
{"gost94", "GOST R 34.10-94", NID_id_GostR3410_94, 6, &so[5405]},
{"gost89", "GOST 28147-89", NID_id_Gost28147_89, 6, &so[5411]},
{"gost89-cnt", "gost89-cnt", NID_gost89_cnt},
{"gost-mac", "GOST 28147-89 MAC", NID_id_Gost28147_89_MAC, 6, &so[5417]},
{"prf-gostr3411-94", "GOST R 34.11-94 PRF", NID_id_GostR3411_94_prf, 6, &so[5423]},
{"id-GostR3410-2001DH", "GOST R 34.10-2001 DH", NID_id_GostR3410_2001DH, 6, &so[5429]},
{"id-GostR3410-94DH", "GOST R 34.10-94 DH", NID_id_GostR3410_94DH, 6, &so[5435]},
{"id-Gost28147-89-CryptoPro-KeyMeshing", "id-Gost28147-89-CryptoPro-KeyMeshing", NID_id_Gost28147_89_CryptoPro_KeyMeshing, 7, &so[5441]},
{"id-Gost28147-89-None-KeyMeshing", "id-Gost28147-89-None-KeyMeshing", NID_id_Gost28147_89_None_KeyMeshing, 7, &so[5448]},
{"id-GostR3411-94-TestParamSet", "id-GostR3411-94-TestParamSet", NID_id_GostR3411_94_TestParamSet, 7, &so[5455]},
{"id-GostR3411-94-CryptoProParamSet", "id-GostR3411-94-CryptoProParamSet", NID_id_GostR3411_94_CryptoProParamSet, 7, &so[5462]},
{"id-Gost28147-89-TestParamSet", "id-Gost28147-89-TestParamSet", NID_id_Gost28147_89_TestParamSet, 7, &so[5469]},
{"id-Gost28147-89-CryptoPro-A-ParamSet", "id-Gost28147-89-CryptoPro-A-ParamSet", NID_id_Gost28147_89_CryptoPro_A_ParamSet, 7, &so[5476]},
{"id-Gost28147-89-CryptoPro-B-ParamSet", "id-Gost28147-89-CryptoPro-B-ParamSet", NID_id_Gost28147_89_CryptoPro_B_ParamSet, 7, &so[5483]},
{"id-Gost28147-89-CryptoPro-C-ParamSet", "id-Gost28147-89-CryptoPro-C-ParamSet", NID_id_Gost28147_89_CryptoPro_C_ParamSet, 7, &so[5490]},
{"id-Gost28147-89-CryptoPro-D-ParamSet", "id-Gost28147-89-CryptoPro-D-ParamSet", NID_id_Gost28147_89_CryptoPro_D_ParamSet, 7, &so[5497]},
{"id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet", "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet", NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet, 7, &so[5504]},
{"id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet", "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet", NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet, 7, &so[5511]},
{"id-Gost28147-89-CryptoPro-RIC-1-ParamSet", "id-Gost28147-89-CryptoPro-RIC-1-ParamSet", NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet, 7, &so[5518]},
{"id-GostR3410-94-TestParamSet", "id-GostR3410-94-TestParamSet", NID_id_GostR3410_94_TestParamSet, 7, &so[5525]},
{"id-GostR3410-94-CryptoPro-A-ParamSet", "id-GostR3410-94-CryptoPro-A-ParamSet", NID_id_GostR3410_94_CryptoPro_A_ParamSet, 7, &so[5532]},
{"id-GostR3410-94-CryptoPro-B-ParamSet", "id-GostR3410-94-CryptoPro-B-ParamSet", NID_id_GostR3410_94_CryptoPro_B_ParamSet, 7, &so[5539]},
{"id-GostR3410-94-CryptoPro-C-ParamSet", "id-GostR3410-94-CryptoPro-C-ParamSet", NID_id_GostR3410_94_CryptoPro_C_ParamSet, 7, &so[5546]},
{"id-GostR3410-94-CryptoPro-D-ParamSet", "id-GostR3410-94-CryptoPro-D-ParamSet", NID_id_GostR3410_94_CryptoPro_D_ParamSet, 7, &so[5553]},
{"id-GostR3410-94-CryptoPro-XchA-ParamSet", "id-GostR3410-94-CryptoPro-XchA-ParamSet", NID_id_GostR3410_94_CryptoPro_XchA_ParamSet, 7, &so[5560]},
{"id-GostR3410-94-CryptoPro-XchB-ParamSet", "id-GostR3410-94-CryptoPro-XchB-ParamSet", NID_id_GostR3410_94_CryptoPro_XchB_ParamSet, 7, &so[5567]},
{"id-GostR3410-94-CryptoPro-XchC-ParamSet", "id-GostR3410-94-CryptoPro-XchC-ParamSet", NID_id_GostR3410_94_CryptoPro_XchC_ParamSet, 7, &so[5574]},
{"id-GostR3410-2001-TestParamSet", "id-GostR3410-2001-TestParamSet", NID_id_GostR3410_2001_TestParamSet, 7, &so[5581]},
{"id-GostR3410-2001-CryptoPro-A-ParamSet", "id-GostR3410-2001-CryptoPro-A-ParamSet", NID_id_GostR3410_2001_CryptoPro_A_ParamSet, 7, &so[5588]},
{"id-GostR3410-2001-CryptoPro-B-ParamSet", "id-GostR3410-2001-CryptoPro-B-ParamSet", NID_id_GostR3410_2001_CryptoPro_B_ParamSet, 7, &so[5595]},
{"id-GostR3410-2001-CryptoPro-C-ParamSet", "id-GostR3410-2001-CryptoPro-C-ParamSet", NID_id_GostR3410_2001_CryptoPro_C_ParamSet, 7, &so[5602]},
{"id-GostR3410-2001-CryptoPro-XchA-ParamSet", "id-GostR3410-2001-CryptoPro-XchA-ParamSet", NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet, 7, &so[5609]},
{"id-GostR3410-2001-CryptoPro-XchB-ParamSet", "id-GostR3410-2001-CryptoPro-XchB-ParamSet", NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet, 7, &so[5616]},
{"id-GostR3410-94-a", "id-GostR3410-94-a", NID_id_GostR3410_94_a, 7, &so[5623]},
{"id-GostR3410-94-aBis", "id-GostR3410-94-aBis", NID_id_GostR3410_94_aBis, 7, &so[5630]},
{"id-GostR3410-94-b", "id-GostR3410-94-b", NID_id_GostR3410_94_b, 7, &so[5637]},
{"id-GostR3410-94-bBis", "id-GostR3410-94-bBis", NID_id_GostR3410_94_bBis, 7, &so[5644]},
{"id-Gost28147-89-cc", "GOST 28147-89 Cryptocom ParamSet", NID_id_Gost28147_89_cc, 8, &so[5651]},
{"gost94cc", "GOST 34.10-94 Cryptocom", NID_id_GostR3410_94_cc, 8, &so[5659]},
{"gost2001cc", "GOST 34.10-2001 Cryptocom", NID_id_GostR3410_2001_cc, 8, &so[5667]},
{"id-GostR3411-94-with-GostR3410-94-cc", "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom", NID_id_GostR3411_94_with_GostR3410_94_cc, 8, &so[5675]},
{"id-GostR3411-94-with-GostR3410-2001-cc", "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom", NID_id_GostR3411_94_with_GostR3410_2001_cc, 8, &so[5683]},
{"id-GostR3410-2001-ParamSet-cc", "GOST R 3410-2001 Parameter Set Cryptocom", NID_id_GostR3410_2001_ParamSet_cc, 8, &so[5691]},
{"HMAC", "hmac", NID_hmac},
{"LocalKeySet", "Microsoft Local Key set", NID_LocalKeySet, 9, &so[5699]},
{"freshestCRL", "X509v3 Freshest CRL", NID_freshest_crl, 3, &so[5708]},
{"id-on-permanentIdentifier", "Permanent Identifier", NID_id_on_permanentIdentifier, 8, &so[5711]},
{"searchGuide", "searchGuide", NID_searchGuide, 3, &so[5719]},
{"businessCategory", "businessCategory", NID_businessCategory, 3, &so[5722]},
{"postalAddress", "postalAddress", NID_postalAddress, 3, &so[5725]},
{"postOfficeBox", "postOfficeBox", NID_postOfficeBox, 3, &so[5728]},
{"physicalDeliveryOfficeName", "physicalDeliveryOfficeName", NID_physicalDeliveryOfficeName, 3, &so[5731]},
{"telephoneNumber", "telephoneNumber", NID_telephoneNumber, 3, &so[5734]},
{"telexNumber", "telexNumber", NID_telexNumber, 3, &so[5737]},
{"teletexTerminalIdentifier", "teletexTerminalIdentifier", NID_teletexTerminalIdentifier, 3, &so[5740]},
{"facsimileTelephoneNumber", "facsimileTelephoneNumber", NID_facsimileTelephoneNumber, 3, &so[5743]},
{"x121Address", "x121Address", NID_x121Address, 3, &so[5746]},
{"internationaliSDNNumber", "internationaliSDNNumber", NID_internationaliSDNNumber, 3, &so[5749]},
{"registeredAddress", "registeredAddress", NID_registeredAddress, 3, &so[5752]},
{"destinationIndicator", "destinationIndicator", NID_destinationIndicator, 3, &so[5755]},
{"preferredDeliveryMethod", "preferredDeliveryMethod", NID_preferredDeliveryMethod, 3, &so[5758]},
{"presentationAddress", "presentationAddress", NID_presentationAddress, 3, &so[5761]},
{"supportedApplicationContext", "supportedApplicationContext", NID_supportedApplicationContext, 3, &so[5764]},
{"member", "member", NID_member, 3, &so[5767]},
{"owner", "owner", NID_owner, 3, &so[5770]},
{"roleOccupant", "roleOccupant", NID_roleOccupant, 3, &so[5773]},
{"seeAlso", "seeAlso", NID_seeAlso, 3, &so[5776]},
{"userPassword", "userPassword", NID_userPassword, 3, &so[5779]},
{"userCertificate", "userCertificate", NID_userCertificate, 3, &so[5782]},
{"cACertificate", "cACertificate", NID_cACertificate, 3, &so[5785]},
{"authorityRevocationList", "authorityRevocationList", NID_authorityRevocationList, 3, &so[5788]},
{"certificateRevocationList", "certificateRevocationList", NID_certificateRevocationList, 3, &so[5791]},
{"crossCertificatePair", "crossCertificatePair", NID_crossCertificatePair, 3, &so[5794]},
{"enhancedSearchGuide", "enhancedSearchGuide", NID_enhancedSearchGuide, 3, &so[5797]},
{"protocolInformation", "protocolInformation", NID_protocolInformation, 3, &so[5800]},
{"distinguishedName", "distinguishedName", NID_distinguishedName, 3, &so[5803]},
{"uniqueMember", "uniqueMember", NID_uniqueMember, 3, &so[5806]},
{"houseIdentifier", "houseIdentifier", NID_houseIdentifier, 3, &so[5809]},
{"supportedAlgorithms", "supportedAlgorithms", NID_supportedAlgorithms, 3, &so[5812]},
{"deltaRevocationList", "deltaRevocationList", NID_deltaRevocationList, 3, &so[5815]},
{"dmdName", "dmdName", NID_dmdName, 3, &so[5818]},
{"id-alg-PWRI-KEK", "id-alg-PWRI-KEK", NID_id_alg_PWRI_KEK, 11, &so[5821]},
{"CMAC", "cmac", NID_cmac},
{"id-aes128-GCM", "aes-128-gcm", NID_aes_128_gcm, 9, &so[5832]},
{"id-aes128-CCM", "aes-128-ccm", NID_aes_128_ccm, 9, &so[5841]},
{"id-aes128-wrap-pad", "id-aes128-wrap-pad", NID_id_aes128_wrap_pad, 9, &so[5850]},
{"id-aes192-GCM", "aes-192-gcm", NID_aes_192_gcm, 9, &so[5859]},
{"id-aes192-CCM", "aes-192-ccm", NID_aes_192_ccm, 9, &so[5868]},
{"id-aes192-wrap-pad", "id-aes192-wrap-pad", NID_id_aes192_wrap_pad, 9, &so[5877]},
{"id-aes256-GCM", "aes-256-gcm", NID_aes_256_gcm, 9, &so[5886]},
{"id-aes256-CCM", "aes-256-ccm", NID_aes_256_ccm, 9, &so[5895]},
{"id-aes256-wrap-pad", "id-aes256-wrap-pad", NID_id_aes256_wrap_pad, 9, &so[5904]},
{"AES-128-CTR", "aes-128-ctr", NID_aes_128_ctr},
{"AES-192-CTR", "aes-192-ctr", NID_aes_192_ctr},
{"AES-256-CTR", "aes-256-ctr", NID_aes_256_ctr},
{"id-camellia128-wrap", "id-camellia128-wrap", NID_id_camellia128_wrap, 11, &so[5913]},
{"id-camellia192-wrap", "id-camellia192-wrap", NID_id_camellia192_wrap, 11, &so[5924]},
{"id-camellia256-wrap", "id-camellia256-wrap", NID_id_camellia256_wrap, 11, &so[5935]},
{"anyExtendedKeyUsage", "Any Extended Key Usage", NID_anyExtendedKeyUsage, 4, &so[5946]},
{"MGF1", "mgf1", NID_mgf1, 9, &so[5950]},
{"RSASSA-PSS", "rsassaPss", NID_rsassaPss, 9, &so[5959]},
{"AES-128-XTS", "aes-128-xts", NID_aes_128_xts, 8, &so[5968]},
{"AES-256-XTS", "aes-256-xts", NID_aes_256_xts, 8, &so[5976]},
{"RC4-HMAC-MD5", "rc4-hmac-md5", NID_rc4_hmac_md5},
{"AES-128-CBC-HMAC-SHA1", "aes-128-cbc-hmac-sha1", NID_aes_128_cbc_hmac_sha1},
{"AES-192-CBC-HMAC-SHA1", "aes-192-cbc-hmac-sha1", NID_aes_192_cbc_hmac_sha1},
{"AES-256-CBC-HMAC-SHA1", "aes-256-cbc-hmac-sha1", NID_aes_256_cbc_hmac_sha1},
{"RSAES-OAEP", "rsaesOaep", NID_rsaesOaep, 9, &so[5984]},
{"dhpublicnumber", "X9.42 DH", NID_dhpublicnumber, 7, &so[5993]},
{"brainpoolP160r1", "brainpoolP160r1", NID_brainpoolP160r1, 9, &so[6000]},
{"brainpoolP160t1", "brainpoolP160t1", NID_brainpoolP160t1, 9, &so[6009]},
{"brainpoolP192r1", "brainpoolP192r1", NID_brainpoolP192r1, 9, &so[6018]},
{"brainpoolP192t1", "brainpoolP192t1", NID_brainpoolP192t1, 9, &so[6027]},
{"brainpoolP224r1", "brainpoolP224r1", NID_brainpoolP224r1, 9, &so[6036]},
{"brainpoolP224t1", "brainpoolP224t1", NID_brainpoolP224t1, 9, &so[6045]},
{"brainpoolP256r1", "brainpoolP256r1", NID_brainpoolP256r1, 9, &so[6054]},
{"brainpoolP256t1", "brainpoolP256t1", NID_brainpoolP256t1, 9, &so[6063]},
{"brainpoolP320r1", "brainpoolP320r1", NID_brainpoolP320r1, 9, &so[6072]},
{"brainpoolP320t1", "brainpoolP320t1", NID_brainpoolP320t1, 9, &so[6081]},
{"brainpoolP384r1", "brainpoolP384r1", NID_brainpoolP384r1, 9, &so[6090]},
{"brainpoolP384t1", "brainpoolP384t1", NID_brainpoolP384t1, 9, &so[6099]},
{"brainpoolP512r1", "brainpoolP512r1", NID_brainpoolP512r1, 9, &so[6108]},
{"brainpoolP512t1", "brainpoolP512t1", NID_brainpoolP512t1, 9, &so[6117]},
{"PSPECIFIED", "pSpecified", NID_pSpecified, 9, &so[6126]},
{"dhSinglePass-stdDH-sha1kdf-scheme", "dhSinglePass-stdDH-sha1kdf-scheme", NID_dhSinglePass_stdDH_sha1kdf_scheme, 9, &so[6135]},
{"dhSinglePass-stdDH-sha224kdf-scheme", "dhSinglePass-stdDH-sha224kdf-scheme", NID_dhSinglePass_stdDH_sha224kdf_scheme, 6, &so[6144]},
{"dhSinglePass-stdDH-sha256kdf-scheme", "dhSinglePass-stdDH-sha256kdf-scheme", NID_dhSinglePass_stdDH_sha256kdf_scheme, 6, &so[6150]},
{"dhSinglePass-stdDH-sha384kdf-scheme", "dhSinglePass-stdDH-sha384kdf-scheme", NID_dhSinglePass_stdDH_sha384kdf_scheme, 6, &so[6156]},
{"dhSinglePass-stdDH-sha512kdf-scheme", "dhSinglePass-stdDH-sha512kdf-scheme", NID_dhSinglePass_stdDH_sha512kdf_scheme, 6, &so[6162]},
{"dhSinglePass-cofactorDH-sha1kdf-scheme", "dhSinglePass-cofactorDH-sha1kdf-scheme", NID_dhSinglePass_cofactorDH_sha1kdf_scheme, 9, &so[6168]},
{"dhSinglePass-cofactorDH-sha224kdf-scheme", "dhSinglePass-cofactorDH-sha224kdf-scheme", NID_dhSinglePass_cofactorDH_sha224kdf_scheme, 6, &so[6177]},
{"dhSinglePass-cofactorDH-sha256kdf-scheme", "dhSinglePass-cofactorDH-sha256kdf-scheme", NID_dhSinglePass_cofactorDH_sha256kdf_scheme, 6, &so[6183]},
{"dhSinglePass-cofactorDH-sha384kdf-scheme", "dhSinglePass-cofactorDH-sha384kdf-scheme", NID_dhSinglePass_cofactorDH_sha384kdf_scheme, 6, &so[6189]},
{"dhSinglePass-cofactorDH-sha512kdf-scheme", "dhSinglePass-cofactorDH-sha512kdf-scheme", NID_dhSinglePass_cofactorDH_sha512kdf_scheme, 6, &so[6195]},
{"dh-std-kdf", "dh-std-kdf", NID_dh_std_kdf},
{"dh-cofactor-kdf", "dh-cofactor-kdf", NID_dh_cofactor_kdf},
{"AES-128-CBC-HMAC-SHA256", "aes-128-cbc-hmac-sha256", NID_aes_128_cbc_hmac_sha256},
{"AES-192-CBC-HMAC-SHA256", "aes-192-cbc-hmac-sha256", NID_aes_192_cbc_hmac_sha256},
{"AES-256-CBC-HMAC-SHA256", "aes-256-cbc-hmac-sha256", NID_aes_256_cbc_hmac_sha256},
{"ct_precert_scts", "CT Precertificate SCTs", NID_ct_precert_scts, 10, &so[6201]},
{"ct_precert_poison", "CT Precertificate Poison", NID_ct_precert_poison, 10, &so[6211]},
{"ct_precert_signer", "CT Precertificate Signer", NID_ct_precert_signer, 10, &so[6221]},
{"ct_cert_scts", "CT Certificate SCTs", NID_ct_cert_scts, 10, &so[6231]},
{"jurisdictionL", "jurisdictionLocalityName", NID_jurisdictionLocalityName, 11, &so[6241]},
{"jurisdictionST", "jurisdictionStateOrProvinceName", NID_jurisdictionStateOrProvinceName, 11, &so[6252]},
{"jurisdictionC", "jurisdictionCountryName", NID_jurisdictionCountryName, 11, &so[6263]},
{"AES-128-OCB", "aes-128-ocb", NID_aes_128_ocb},
{"AES-192-OCB", "aes-192-ocb", NID_aes_192_ocb},
{"AES-256-OCB", "aes-256-ocb", NID_aes_256_ocb},
{"CAMELLIA-128-GCM", "camellia-128-gcm", NID_camellia_128_gcm, 8, &so[6274]},
{"CAMELLIA-128-CCM", "camellia-128-ccm", NID_camellia_128_ccm, 8, &so[6282]},
{"CAMELLIA-128-CTR", "camellia-128-ctr", NID_camellia_128_ctr, 8, &so[6290]},
{"CAMELLIA-128-CMAC", "camellia-128-cmac", NID_camellia_128_cmac, 8, &so[6298]},
{"CAMELLIA-192-GCM", "camellia-192-gcm", NID_camellia_192_gcm, 8, &so[6306]},
{"CAMELLIA-192-CCM", "camellia-192-ccm", NID_camellia_192_ccm, 8, &so[6314]},
{"CAMELLIA-192-CTR", "camellia-192-ctr", NID_camellia_192_ctr, 8, &so[6322]},
{"CAMELLIA-192-CMAC", "camellia-192-cmac", NID_camellia_192_cmac, 8, &so[6330]},
{"CAMELLIA-256-GCM", "camellia-256-gcm", NID_camellia_256_gcm, 8, &so[6338]},
{"CAMELLIA-256-CCM", "camellia-256-ccm", NID_camellia_256_ccm, 8, &so[6346]},
{"CAMELLIA-256-CTR", "camellia-256-ctr", NID_camellia_256_ctr, 8, &so[6354]},
{"CAMELLIA-256-CMAC", "camellia-256-cmac", NID_camellia_256_cmac, 8, &so[6362]},
{"id-scrypt", "scrypt", NID_id_scrypt, 9, &so[6370]},
{"id-tc26", "id-tc26", NID_id_tc26, 5, &so[6379]},
{"gost89-cnt-12", "gost89-cnt-12", NID_gost89_cnt_12},
{"gost-mac-12", "gost-mac-12", NID_gost_mac_12},
{"id-tc26-algorithms", "id-tc26-algorithms", NID_id_tc26_algorithms, 6, &so[6384]},
{"id-tc26-sign", "id-tc26-sign", NID_id_tc26_sign, 7, &so[6390]},
{"gost2012_256", "GOST R 34.10-2012 with 256 bit modulus", NID_id_GostR3410_2012_256, 8, &so[6397]},
{"gost2012_512", "GOST R 34.10-2012 with 512 bit modulus", NID_id_GostR3410_2012_512, 8, &so[6405]},
{"id-tc26-digest", "id-tc26-digest", NID_id_tc26_digest, 7, &so[6413]},
{"md_gost12_256", "GOST R 34.11-2012 with 256 bit hash", NID_id_GostR3411_2012_256, 8, &so[6420]},
{"md_gost12_512", "GOST R 34.11-2012 with 512 bit hash", NID_id_GostR3411_2012_512, 8, &so[6428]},
{"id-tc26-signwithdigest", "id-tc26-signwithdigest", NID_id_tc26_signwithdigest, 7, &so[6436]},
{"id-tc26-signwithdigest-gost3410-2012-256", "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)", NID_id_tc26_signwithdigest_gost3410_2012_256, 8, &so[6443]},
{"id-tc26-signwithdigest-gost3410-2012-512", "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)", NID_id_tc26_signwithdigest_gost3410_2012_512, 8, &so[6451]},
{"id-tc26-mac", "id-tc26-mac", NID_id_tc26_mac, 7, &so[6459]},
{"id-tc26-hmac-gost-3411-2012-256", "HMAC GOST 34.11-2012 256 bit", NID_id_tc26_hmac_gost_3411_2012_256, 8, &so[6466]},
{"id-tc26-hmac-gost-3411-2012-512", "HMAC GOST 34.11-2012 512 bit", NID_id_tc26_hmac_gost_3411_2012_512, 8, &so[6474]},
{"id-tc26-cipher", "id-tc26-cipher", NID_id_tc26_cipher, 7, &so[6482]},
{"id-tc26-agreement", "id-tc26-agreement", NID_id_tc26_agreement, 7, &so[6489]},
{"id-tc26-agreement-gost-3410-2012-256", "id-tc26-agreement-gost-3410-2012-256", NID_id_tc26_agreement_gost_3410_2012_256, 8, &so[6496]},
{"id-tc26-agreement-gost-3410-2012-512", "id-tc26-agreement-gost-3410-2012-512", NID_id_tc26_agreement_gost_3410_2012_512, 8, &so[6504]},
{"id-tc26-constants", "id-tc26-constants", NID_id_tc26_constants, 6, &so[6512]},
{"id-tc26-sign-constants", "id-tc26-sign-constants", NID_id_tc26_sign_constants, 7, &so[6518]},
{"id-tc26-gost-3410-2012-512-constants", "id-tc26-gost-3410-2012-512-constants", NID_id_tc26_gost_3410_2012_512_constants, 8, &so[6525]},
{"id-tc26-gost-3410-2012-512-paramSetTest", "GOST R 34.10-2012 (512 bit) testing parameter set", NID_id_tc26_gost_3410_2012_512_paramSetTest, 9, &so[6533]},
{"id-tc26-gost-3410-2012-512-paramSetA", "GOST R 34.10-2012 (512 bit) ParamSet A", NID_id_tc26_gost_3410_2012_512_paramSetA, 9, &so[6542]},
{"id-tc26-gost-3410-2012-512-paramSetB", "GOST R 34.10-2012 (512 bit) ParamSet B", NID_id_tc26_gost_3410_2012_512_paramSetB, 9, &so[6551]},
{"id-tc26-digest-constants", "id-tc26-digest-constants", NID_id_tc26_digest_constants, 7, &so[6560]},
{"id-tc26-cipher-constants", "id-tc26-cipher-constants", NID_id_tc26_cipher_constants, 7, &so[6567]},
{"id-tc26-gost-28147-constants", "id-tc26-gost-28147-constants", NID_id_tc26_gost_28147_constants, 8, &so[6574]},
{"id-tc26-gost-28147-param-Z", "GOST 28147-89 TC26 parameter set", NID_id_tc26_gost_28147_param_Z, 9, &so[6582]},
{"INN", "INN", NID_INN, 8, &so[6591]},
{"OGRN", "OGRN", NID_OGRN, 5, &so[6599]},
{"SNILS", "SNILS", NID_SNILS, 5, &so[6604]},
{"subjectSignTool", "Signing Tool of Subject", NID_subjectSignTool, 5, &so[6609]},
{"issuerSignTool", "Signing Tool of Issuer", NID_issuerSignTool, 5, &so[6614]},
{"gost89-cbc", "gost89-cbc", NID_gost89_cbc},
{"gost89-ecb", "gost89-ecb", NID_gost89_ecb},
{"gost89-ctr", "gost89-ctr", NID_gost89_ctr},
{"grasshopper-ecb", "grasshopper-ecb", NID_grasshopper_ecb},
{"grasshopper-ctr", "grasshopper-ctr", NID_grasshopper_ctr},
{"grasshopper-ofb", "grasshopper-ofb", NID_grasshopper_ofb},
{"grasshopper-cbc", "grasshopper-cbc", NID_grasshopper_cbc},
{"grasshopper-cfb", "grasshopper-cfb", NID_grasshopper_cfb},
{"grasshopper-mac", "grasshopper-mac", NID_grasshopper_mac},
{"ChaCha20-Poly1305", "chacha20-poly1305", NID_chacha20_poly1305},
{"ChaCha20", "chacha20", NID_chacha20},
{"tlsfeature", "TLS Feature", NID_tlsfeature, 8, &so[6619]},
{"TLS1-PRF", "tls1-prf", NID_tls1_prf},
{"ipsecIKE", "ipsec Internet Key Exchange", NID_ipsec_IKE, 8, &so[6627]},
{"capwapAC", "Ctrl/provision WAP Access", NID_capwapAC, 8, &so[6635]},
{"capwapWTP", "Ctrl/Provision WAP Termination", NID_capwapWTP, 8, &so[6643]},
{"secureShellClient", "SSH Client", NID_sshClient, 8, &so[6651]},
{"secureShellServer", "SSH Server", NID_sshServer, 8, &so[6659]},
{"sendRouter", "Send Router", NID_sendRouter, 8, &so[6667]},
{"sendProxiedRouter", "Send Proxied Router", NID_sendProxiedRouter, 8, &so[6675]},
{"sendOwner", "Send Owner", NID_sendOwner, 8, &so[6683]},
{"sendProxiedOwner", "Send Proxied Owner", NID_sendProxiedOwner, 8, &so[6691]},
{"id-pkinit", "id-pkinit", NID_id_pkinit, 6, &so[6699]},
{"pkInitClientAuth", "PKINIT Client Auth", NID_pkInitClientAuth, 7, &so[6705]},
{"pkInitKDC", "Signing KDC Response", NID_pkInitKDC, 7, &so[6712]},
{"X25519", "X25519", NID_X25519, 3, &so[6719]},
{"X448", "X448", NID_X448, 3, &so[6722]},
{"HKDF", "hkdf", NID_hkdf},
{"KxRSA", "kx-rsa", NID_kx_rsa},
{"KxECDHE", "kx-ecdhe", NID_kx_ecdhe},
{"KxDHE", "kx-dhe", NID_kx_dhe},
{"KxECDHE-PSK", "kx-ecdhe-psk", NID_kx_ecdhe_psk},
{"KxDHE-PSK", "kx-dhe-psk", NID_kx_dhe_psk},
{"KxRSA_PSK", "kx-rsa-psk", NID_kx_rsa_psk},
{"KxPSK", "kx-psk", NID_kx_psk},
{"KxSRP", "kx-srp", NID_kx_srp},
{"KxGOST", "kx-gost", NID_kx_gost},
{"AuthRSA", "auth-rsa", NID_auth_rsa},
{"AuthECDSA", "auth-ecdsa", NID_auth_ecdsa},
{"AuthPSK", "auth-psk", NID_auth_psk},
{"AuthDSS", "auth-dss", NID_auth_dss},
{"AuthGOST01", "auth-gost01", NID_auth_gost01},
{"AuthGOST12", "auth-gost12", NID_auth_gost12},
{"AuthSRP", "auth-srp", NID_auth_srp},
{"AuthNULL", "auth-null", NID_auth_null},
{ NULL, NULL, NID_undef },
{ NULL, NULL, NID_undef },
{"BLAKE2b512", "blake2b512", NID_blake2b512, 11, &so[6725]},
{"BLAKE2s256", "blake2s256", NID_blake2s256, 11, &so[6736]},
{"id-smime-ct-contentCollection", "id-smime-ct-contentCollection", NID_id_smime_ct_contentCollection, 11, &so[6747]},
{"id-smime-ct-authEnvelopedData", "id-smime-ct-authEnvelopedData", NID_id_smime_ct_authEnvelopedData, 11, &so[6758]},
{"id-ct-xml", "id-ct-xml", NID_id_ct_xml, 11, &so[6769]},
{"Poly1305", "poly1305", NID_poly1305},
{"SipHash", "siphash", NID_siphash},
{"KxANY", "kx-any", NID_kx_any},
{"AuthANY", "auth-any", NID_auth_any},
{"ARIA-128-ECB", "aria-128-ecb", NID_aria_128_ecb, 9, &so[6780]},
{"ARIA-128-CBC", "aria-128-cbc", NID_aria_128_cbc, 9, &so[6789]},
{"ARIA-128-CFB", "aria-128-cfb", NID_aria_128_cfb128, 9, &so[6798]},
{"ARIA-128-OFB", "aria-128-ofb", NID_aria_128_ofb128, 9, &so[6807]},
{"ARIA-128-CTR", "aria-128-ctr", NID_aria_128_ctr, 9, &so[6816]},
{"ARIA-192-ECB", "aria-192-ecb", NID_aria_192_ecb, 9, &so[6825]},
{"ARIA-192-CBC", "aria-192-cbc", NID_aria_192_cbc, 9, &so[6834]},
{"ARIA-192-CFB", "aria-192-cfb", NID_aria_192_cfb128, 9, &so[6843]},
{"ARIA-192-OFB", "aria-192-ofb", NID_aria_192_ofb128, 9, &so[6852]},
{"ARIA-192-CTR", "aria-192-ctr", NID_aria_192_ctr, 9, &so[6861]},
{"ARIA-256-ECB", "aria-256-ecb", NID_aria_256_ecb, 9, &so[6870]},
{"ARIA-256-CBC", "aria-256-cbc", NID_aria_256_cbc, 9, &so[6879]},
{"ARIA-256-CFB", "aria-256-cfb", NID_aria_256_cfb128, 9, &so[6888]},
{"ARIA-256-OFB", "aria-256-ofb", NID_aria_256_ofb128, 9, &so[6897]},
{"ARIA-256-CTR", "aria-256-ctr", NID_aria_256_ctr, 9, &so[6906]},
{"ARIA-128-CFB1", "aria-128-cfb1", NID_aria_128_cfb1},
{"ARIA-192-CFB1", "aria-192-cfb1", NID_aria_192_cfb1},
{"ARIA-256-CFB1", "aria-256-cfb1", NID_aria_256_cfb1},
{"ARIA-128-CFB8", "aria-128-cfb8", NID_aria_128_cfb8},
{"ARIA-192-CFB8", "aria-192-cfb8", NID_aria_192_cfb8},
{"ARIA-256-CFB8", "aria-256-cfb8", NID_aria_256_cfb8},
{"id-smime-aa-signingCertificateV2", "id-smime-aa-signingCertificateV2", NID_id_smime_aa_signingCertificateV2, 11, &so[6915]},
{"ED25519", "ED25519", NID_ED25519, 3, &so[6926]},
{"ED448", "ED448", NID_ED448, 3, &so[6929]},
{"organizationIdentifier", "organizationIdentifier", NID_organizationIdentifier, 3, &so[6932]},
{"c3", "countryCode3c", NID_countryCode3c, 3, &so[6935]},
{"n3", "countryCode3n", NID_countryCode3n, 3, &so[6938]},
{"dnsName", "dnsName", NID_dnsName, 3, &so[6941]},
{"x509ExtAdmission", "Professional Information or basis for Admission", NID_x509ExtAdmission, 5, &so[6944]},
{"SHA512-224", "sha512-224", NID_sha512_224, 9, &so[6949]},
{"SHA512-256", "sha512-256", NID_sha512_256, 9, &so[6958]},
{"SHA3-224", "sha3-224", NID_sha3_224, 9, &so[6967]},
{"SHA3-256", "sha3-256", NID_sha3_256, 9, &so[6976]},
{"SHA3-384", "sha3-384", NID_sha3_384, 9, &so[6985]},
{"SHA3-512", "sha3-512", NID_sha3_512, 9, &so[6994]},
{"SHAKE128", "shake128", NID_shake128, 9, &so[7003]},
{"SHAKE256", "shake256", NID_shake256, 9, &so[7012]},
{"id-hmacWithSHA3-224", "hmac-sha3-224", NID_hmac_sha3_224, 9, &so[7021]},
{"id-hmacWithSHA3-256", "hmac-sha3-256", NID_hmac_sha3_256, 9, &so[7030]},
{"id-hmacWithSHA3-384", "hmac-sha3-384", NID_hmac_sha3_384, 9, &so[7039]},
{"id-hmacWithSHA3-512", "hmac-sha3-512", NID_hmac_sha3_512, 9, &so[7048]},
{"id-dsa-with-sha384", "dsa_with_SHA384", NID_dsa_with_SHA384, 9, &so[7057]},
{"id-dsa-with-sha512", "dsa_with_SHA512", NID_dsa_with_SHA512, 9, &so[7066]},
{"id-dsa-with-sha3-224", "dsa_with_SHA3-224", NID_dsa_with_SHA3_224, 9, &so[7075]},
{"id-dsa-with-sha3-256", "dsa_with_SHA3-256", NID_dsa_with_SHA3_256, 9, &so[7084]},
{"id-dsa-with-sha3-384", "dsa_with_SHA3-384", NID_dsa_with_SHA3_384, 9, &so[7093]},
{"id-dsa-with-sha3-512", "dsa_with_SHA3-512", NID_dsa_with_SHA3_512, 9, &so[7102]},
{"id-ecdsa-with-sha3-224", "ecdsa_with_SHA3-224", NID_ecdsa_with_SHA3_224, 9, &so[7111]},
{"id-ecdsa-with-sha3-256", "ecdsa_with_SHA3-256", NID_ecdsa_with_SHA3_256, 9, &so[7120]},
{"id-ecdsa-with-sha3-384", "ecdsa_with_SHA3-384", NID_ecdsa_with_SHA3_384, 9, &so[7129]},
{"id-ecdsa-with-sha3-512", "ecdsa_with_SHA3-512", NID_ecdsa_with_SHA3_512, 9, &so[7138]},
{"id-rsassa-pkcs1-v1_5-with-sha3-224", "RSA-SHA3-224", NID_RSA_SHA3_224, 9, &so[7147]},
{"id-rsassa-pkcs1-v1_5-with-sha3-256", "RSA-SHA3-256", NID_RSA_SHA3_256, 9, &so[7156]},
{"id-rsassa-pkcs1-v1_5-with-sha3-384", "RSA-SHA3-384", NID_RSA_SHA3_384, 9, &so[7165]},
{"id-rsassa-pkcs1-v1_5-with-sha3-512", "RSA-SHA3-512", NID_RSA_SHA3_512, 9, &so[7174]},
{"ARIA-128-CCM", "aria-128-ccm", NID_aria_128_ccm, 9, &so[7183]},
{"ARIA-192-CCM", "aria-192-ccm", NID_aria_192_ccm, 9, &so[7192]},
{"ARIA-256-CCM", "aria-256-ccm", NID_aria_256_ccm, 9, &so[7201]},
{"ARIA-128-GCM", "aria-128-gcm", NID_aria_128_gcm, 9, &so[7210]},
{"ARIA-192-GCM", "aria-192-gcm", NID_aria_192_gcm, 9, &so[7219]},
{"ARIA-256-GCM", "aria-256-gcm", NID_aria_256_gcm, 9, &so[7228]},
{"ffdhe2048", "ffdhe2048", NID_ffdhe2048},
{"ffdhe3072", "ffdhe3072", NID_ffdhe3072},
{"ffdhe4096", "ffdhe4096", NID_ffdhe4096},
{"ffdhe6144", "ffdhe6144", NID_ffdhe6144},
{"ffdhe8192", "ffdhe8192", NID_ffdhe8192},
{"cmcCA", "CMC Certificate Authority", NID_cmcCA, 8, &so[7237]},
{"cmcRA", "CMC Registration Authority", NID_cmcRA, 8, &so[7245]},
{"SM4-ECB", "sm4-ecb", NID_sm4_ecb, 8, &so[7253]},
{"SM4-CBC", "sm4-cbc", NID_sm4_cbc, 8, &so[7261]},
{"SM4-OFB", "sm4-ofb", NID_sm4_ofb128, 8, &so[7269]},
{"SM4-CFB1", "sm4-cfb1", NID_sm4_cfb1, 8, &so[7277]},
{"SM4-CFB", "sm4-cfb", NID_sm4_cfb128, 8, &so[7285]},
{"SM4-CFB8", "sm4-cfb8", NID_sm4_cfb8, 8, &so[7293]},
{"SM4-CTR", "sm4-ctr", NID_sm4_ctr, 8, &so[7301]},
{"ISO-CN", "ISO CN Member Body", NID_ISO_CN, 3, &so[7309]},
{"oscca", "oscca", NID_oscca, 5, &so[7312]},
{"sm-scheme", "sm-scheme", NID_sm_scheme, 6, &so[7317]},
{"SM3", "sm3", NID_sm3, 8, &so[7323]},
{"RSA-SM3", "sm3WithRSAEncryption", NID_sm3WithRSAEncryption, 8, &so[7331]},
{"RSA-SHA512/224", "sha512-224WithRSAEncryption", NID_sha512_224WithRSAEncryption, 9, &so[7339]},
{"RSA-SHA512/256", "sha512-256WithRSAEncryption", NID_sha512_256WithRSAEncryption, 9, &so[7348]},
{"id-tc26-gost-3410-2012-256-constants", "id-tc26-gost-3410-2012-256-constants", NID_id_tc26_gost_3410_2012_256_constants, 8, &so[7357]},
{"id-tc26-gost-3410-2012-256-paramSetA", "GOST R 34.10-2012 (256 bit) ParamSet A", NID_id_tc26_gost_3410_2012_256_paramSetA, 9, &so[7365]},
{"id-tc26-gost-3410-2012-512-paramSetC", "GOST R 34.10-2012 (512 bit) ParamSet C", NID_id_tc26_gost_3410_2012_512_paramSetC, 9, &so[7374]},
{"ISO-UA", "ISO-UA", NID_ISO_UA, 3, &so[7383]},
{"ua-pki", "ua-pki", NID_ua_pki, 7, &so[7386]},
{"dstu28147", "DSTU Gost 28147-2009", NID_dstu28147, 10, &so[7393]},
{"dstu28147-ofb", "DSTU Gost 28147-2009 OFB mode", NID_dstu28147_ofb, 11, &so[7403]},
{"dstu28147-cfb", "DSTU Gost 28147-2009 CFB mode", NID_dstu28147_cfb, 11, &so[7414]},
{"dstu28147-wrap", "DSTU Gost 28147-2009 key wrap", NID_dstu28147_wrap, 11, &so[7425]},
{"hmacWithDstu34311", "HMAC DSTU Gost 34311-95", NID_hmacWithDstu34311, 10, &so[7436]},
{"dstu34311", "DSTU Gost 34311-95", NID_dstu34311, 10, &so[7446]},
{"dstu4145le", "DSTU 4145-2002 little endian", NID_dstu4145le, 11, &so[7456]},
{"dstu4145be", "DSTU 4145-2002 big endian", NID_dstu4145be, 13, &so[7467]},
{"uacurve0", "DSTU curve 0", NID_uacurve0, 13, &so[7480]},
{"uacurve1", "DSTU curve 1", NID_uacurve1, 13, &so[7493]},
{"uacurve2", "DSTU curve 2", NID_uacurve2, 13, &so[7506]},
{"uacurve3", "DSTU curve 3", NID_uacurve3, 13, &so[7519]},
{"uacurve4", "DSTU curve 4", NID_uacurve4, 13, &so[7532]},
{"uacurve5", "DSTU curve 5", NID_uacurve5, 13, &so[7545]},
{"uacurve6", "DSTU curve 6", NID_uacurve6, 13, &so[7558]},
{"uacurve7", "DSTU curve 7", NID_uacurve7, 13, &so[7571]},
{"uacurve8", "DSTU curve 8", NID_uacurve8, 13, &so[7584]},
{"uacurve9", "DSTU curve 9", NID_uacurve9, 13, &so[7597]},
{"ieee", "ieee", NID_ieee, 2, &so[7610]},
{"ieee-siswg", "IEEE Security in Storage Working Group", NID_ieee_siswg, 5, &so[7612]},
{"SM2", "sm2", NID_sm2, 8, &so[7617]},
{"id-tc26-cipher-gostr3412-2015-magma", "id-tc26-cipher-gostr3412-2015-magma", NID_id_tc26_cipher_gostr3412_2015_magma, 8, &so[7625]},
{"id-tc26-cipher-gostr3412-2015-magma-ctracpkm", "id-tc26-cipher-gostr3412-2015-magma-ctracpkm", NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm, 9, &so[7633]},
{"id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac", "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac", NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac, 9, &so[7642]},
{"id-tc26-cipher-gostr3412-2015-kuznyechik", "id-tc26-cipher-gostr3412-2015-kuznyechik", NID_id_tc26_cipher_gostr3412_2015_kuznyechik, 8, &so[7651]},
{"id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm", "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm", NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm, 9, &so[7659]},
{"id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac", "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac", NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac, 9, &so[7668]},
{"id-tc26-wrap", "id-tc26-wrap", NID_id_tc26_wrap, 7, &so[7677]},
{"id-tc26-wrap-gostr3412-2015-magma", "id-tc26-wrap-gostr3412-2015-magma", NID_id_tc26_wrap_gostr3412_2015_magma, 8, &so[7684]},
{"id-tc26-wrap-gostr3412-2015-magma-kexp15", "id-tc26-wrap-gostr3412-2015-magma-kexp15", NID_id_tc26_wrap_gostr3412_2015_magma_kexp15, 9, &so[7692]},
{"id-tc26-wrap-gostr3412-2015-kuznyechik", "id-tc26-wrap-gostr3412-2015-kuznyechik", NID_id_tc26_wrap_gostr3412_2015_kuznyechik, 8, &so[7701]},
{"id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15", "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15", NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15, 9, &so[7709]},
{"id-tc26-gost-3410-2012-256-paramSetB", "GOST R 34.10-2012 (256 bit) ParamSet B", NID_id_tc26_gost_3410_2012_256_paramSetB, 9, &so[7718]},
{"id-tc26-gost-3410-2012-256-paramSetC", "GOST R 34.10-2012 (256 bit) ParamSet C", NID_id_tc26_gost_3410_2012_256_paramSetC, 9, &so[7727]},
{"id-tc26-gost-3410-2012-256-paramSetD", "GOST R 34.10-2012 (256 bit) ParamSet D", NID_id_tc26_gost_3410_2012_256_paramSetD, 9, &so[7736]},
{"magma-ecb", "magma-ecb", NID_magma_ecb},
{"magma-ctr", "magma-ctr", NID_magma_ctr},
{"magma-ofb", "magma-ofb", NID_magma_ofb},
{"magma-cbc", "magma-cbc", NID_magma_cbc},
{"magma-cfb", "magma-cfb", NID_magma_cfb},
{"magma-mac", "magma-mac", NID_magma_mac},
{"hmacWithSHA512-224", "hmacWithSHA512-224", NID_hmacWithSHA512_224, 8, &so[7745]},
{"hmacWithSHA512-256", "hmacWithSHA512-256", NID_hmacWithSHA512_256, 8, &so[7753]},
};
#define NUM_SN 1186
static const unsigned int sn_objs[NUM_SN] = {
364, /* "AD_DVCS" */
419, /* "AES-128-CBC" */
916, /* "AES-128-CBC-HMAC-SHA1" */
948, /* "AES-128-CBC-HMAC-SHA256" */
421, /* "AES-128-CFB" */
650, /* "AES-128-CFB1" */
653, /* "AES-128-CFB8" */
904, /* "AES-128-CTR" */
418, /* "AES-128-ECB" */
958, /* "AES-128-OCB" */
420, /* "AES-128-OFB" */
913, /* "AES-128-XTS" */
423, /* "AES-192-CBC" */
917, /* "AES-192-CBC-HMAC-SHA1" */
949, /* "AES-192-CBC-HMAC-SHA256" */
425, /* "AES-192-CFB" */
651, /* "AES-192-CFB1" */
654, /* "AES-192-CFB8" */
905, /* "AES-192-CTR" */
422, /* "AES-192-ECB" */
959, /* "AES-192-OCB" */
424, /* "AES-192-OFB" */
427, /* "AES-256-CBC" */
918, /* "AES-256-CBC-HMAC-SHA1" */
950, /* "AES-256-CBC-HMAC-SHA256" */
429, /* "AES-256-CFB" */
652, /* "AES-256-CFB1" */
655, /* "AES-256-CFB8" */
906, /* "AES-256-CTR" */
426, /* "AES-256-ECB" */
960, /* "AES-256-OCB" */
428, /* "AES-256-OFB" */
914, /* "AES-256-XTS" */
1066, /* "ARIA-128-CBC" */
1120, /* "ARIA-128-CCM" */
1067, /* "ARIA-128-CFB" */
1080, /* "ARIA-128-CFB1" */
1083, /* "ARIA-128-CFB8" */
1069, /* "ARIA-128-CTR" */
1065, /* "ARIA-128-ECB" */
1123, /* "ARIA-128-GCM" */
1068, /* "ARIA-128-OFB" */
1071, /* "ARIA-192-CBC" */
1121, /* "ARIA-192-CCM" */
1072, /* "ARIA-192-CFB" */
1081, /* "ARIA-192-CFB1" */
1084, /* "ARIA-192-CFB8" */
1074, /* "ARIA-192-CTR" */
1070, /* "ARIA-192-ECB" */
1124, /* "ARIA-192-GCM" */
1073, /* "ARIA-192-OFB" */
1076, /* "ARIA-256-CBC" */
1122, /* "ARIA-256-CCM" */
1077, /* "ARIA-256-CFB" */
1082, /* "ARIA-256-CFB1" */
1085, /* "ARIA-256-CFB8" */
1079, /* "ARIA-256-CTR" */
1075, /* "ARIA-256-ECB" */
1125, /* "ARIA-256-GCM" */
1078, /* "ARIA-256-OFB" */
1064, /* "AuthANY" */
1049, /* "AuthDSS" */
1047, /* "AuthECDSA" */
1050, /* "AuthGOST01" */
1051, /* "AuthGOST12" */
1053, /* "AuthNULL" */
1048, /* "AuthPSK" */
1046, /* "AuthRSA" */
1052, /* "AuthSRP" */
91, /* "BF-CBC" */
93, /* "BF-CFB" */
92, /* "BF-ECB" */
94, /* "BF-OFB" */
1056, /* "BLAKE2b512" */
1057, /* "BLAKE2s256" */
14, /* "C" */
751, /* "CAMELLIA-128-CBC" */
962, /* "CAMELLIA-128-CCM" */
757, /* "CAMELLIA-128-CFB" */
760, /* "CAMELLIA-128-CFB1" */
763, /* "CAMELLIA-128-CFB8" */
964, /* "CAMELLIA-128-CMAC" */
963, /* "CAMELLIA-128-CTR" */
754, /* "CAMELLIA-128-ECB" */
961, /* "CAMELLIA-128-GCM" */
766, /* "CAMELLIA-128-OFB" */
752, /* "CAMELLIA-192-CBC" */
966, /* "CAMELLIA-192-CCM" */
758, /* "CAMELLIA-192-CFB" */
761, /* "CAMELLIA-192-CFB1" */
764, /* "CAMELLIA-192-CFB8" */
968, /* "CAMELLIA-192-CMAC" */
967, /* "CAMELLIA-192-CTR" */
755, /* "CAMELLIA-192-ECB" */
965, /* "CAMELLIA-192-GCM" */
767, /* "CAMELLIA-192-OFB" */
753, /* "CAMELLIA-256-CBC" */
970, /* "CAMELLIA-256-CCM" */
759, /* "CAMELLIA-256-CFB" */
762, /* "CAMELLIA-256-CFB1" */
765, /* "CAMELLIA-256-CFB8" */
972, /* "CAMELLIA-256-CMAC" */
971, /* "CAMELLIA-256-CTR" */
756, /* "CAMELLIA-256-ECB" */
969, /* "CAMELLIA-256-GCM" */
768, /* "CAMELLIA-256-OFB" */
108, /* "CAST5-CBC" */
110, /* "CAST5-CFB" */
109, /* "CAST5-ECB" */
111, /* "CAST5-OFB" */
894, /* "CMAC" */
13, /* "CN" */
141, /* "CRLReason" */
417, /* "CSPName" */
1019, /* "ChaCha20" */
1018, /* "ChaCha20-Poly1305" */
367, /* "CrlID" */
391, /* "DC" */
31, /* "DES-CBC" */
643, /* "DES-CDMF" */
30, /* "DES-CFB" */
656, /* "DES-CFB1" */
657, /* "DES-CFB8" */
29, /* "DES-ECB" */
32, /* "DES-EDE" */
43, /* "DES-EDE-CBC" */
60, /* "DES-EDE-CFB" */
62, /* "DES-EDE-OFB" */
33, /* "DES-EDE3" */
44, /* "DES-EDE3-CBC" */
61, /* "DES-EDE3-CFB" */
658, /* "DES-EDE3-CFB1" */
659, /* "DES-EDE3-CFB8" */
63, /* "DES-EDE3-OFB" */
45, /* "DES-OFB" */
80, /* "DESX-CBC" */
380, /* "DOD" */
116, /* "DSA" */
66, /* "DSA-SHA" */
113, /* "DSA-SHA1" */
70, /* "DSA-SHA1-old" */
67, /* "DSA-old" */
297, /* "DVCS" */
1087, /* "ED25519" */
1088, /* "ED448" */
99, /* "GN" */
1036, /* "HKDF" */
855, /* "HMAC" */
780, /* "HMAC-MD5" */
781, /* "HMAC-SHA1" */
381, /* "IANA" */
34, /* "IDEA-CBC" */
35, /* "IDEA-CFB" */
36, /* "IDEA-ECB" */
46, /* "IDEA-OFB" */
1004, /* "INN" */
181, /* "ISO" */
1140, /* "ISO-CN" */
1150, /* "ISO-UA" */
183, /* "ISO-US" */
645, /* "ITU-T" */
646, /* "JOINT-ISO-ITU-T" */
773, /* "KISA" */
1063, /* "KxANY" */
1039, /* "KxDHE" */
1041, /* "KxDHE-PSK" */
1038, /* "KxECDHE" */
1040, /* "KxECDHE-PSK" */
1045, /* "KxGOST" */
1043, /* "KxPSK" */
1037, /* "KxRSA" */
1042, /* "KxRSA_PSK" */
1044, /* "KxSRP" */
15, /* "L" */
856, /* "LocalKeySet" */
3, /* "MD2" */
257, /* "MD4" */
4, /* "MD5" */
114, /* "MD5-SHA1" */
95, /* "MDC2" */
911, /* "MGF1" */
388, /* "Mail" */
393, /* "NULL" */
404, /* "NULL" */
57, /* "Netscape" */
366, /* "Nonce" */
17, /* "O" */
178, /* "OCSP" */
180, /* "OCSPSigning" */
1005, /* "OGRN" */
379, /* "ORG" */
18, /* "OU" */
749, /* "Oakley-EC2N-3" */
750, /* "Oakley-EC2N-4" */
9, /* "PBE-MD2-DES" */
168, /* "PBE-MD2-RC2-64" */
10, /* "PBE-MD5-DES" */
169, /* "PBE-MD5-RC2-64" */
147, /* "PBE-SHA1-2DES" */
146, /* "PBE-SHA1-3DES" */
170, /* "PBE-SHA1-DES" */
148, /* "PBE-SHA1-RC2-128" */
149, /* "PBE-SHA1-RC2-40" */
68, /* "PBE-SHA1-RC2-64" */
144, /* "PBE-SHA1-RC4-128" */
145, /* "PBE-SHA1-RC4-40" */
161, /* "PBES2" */
69, /* "PBKDF2" */
162, /* "PBMAC1" */
127, /* "PKIX" */
935, /* "PSPECIFIED" */
1061, /* "Poly1305" */
98, /* "RC2-40-CBC" */
166, /* "RC2-64-CBC" */
37, /* "RC2-CBC" */
39, /* "RC2-CFB" */
38, /* "RC2-ECB" */
40, /* "RC2-OFB" */
5, /* "RC4" */
97, /* "RC4-40" */
915, /* "RC4-HMAC-MD5" */
120, /* "RC5-CBC" */
122, /* "RC5-CFB" */
121, /* "RC5-ECB" */
123, /* "RC5-OFB" */
117, /* "RIPEMD160" */
19, /* "RSA" */
7, /* "RSA-MD2" */
396, /* "RSA-MD4" */
8, /* "RSA-MD5" */
96, /* "RSA-MDC2" */
104, /* "RSA-NP-MD5" */
119, /* "RSA-RIPEMD160" */
42, /* "RSA-SHA" */
65, /* "RSA-SHA1" */
115, /* "RSA-SHA1-2" */
671, /* "RSA-SHA224" */
668, /* "RSA-SHA256" */
669, /* "RSA-SHA384" */
670, /* "RSA-SHA512" */
1145, /* "RSA-SHA512/224" */
1146, /* "RSA-SHA512/256" */
1144, /* "RSA-SM3" */
919, /* "RSAES-OAEP" */
912, /* "RSASSA-PSS" */
777, /* "SEED-CBC" */
779, /* "SEED-CFB" */
776, /* "SEED-ECB" */
778, /* "SEED-OFB" */
41, /* "SHA" */
64, /* "SHA1" */
675, /* "SHA224" */
672, /* "SHA256" */
1096, /* "SHA3-224" */
1097, /* "SHA3-256" */
1098, /* "SHA3-384" */
1099, /* "SHA3-512" */
673, /* "SHA384" */
674, /* "SHA512" */
1094, /* "SHA512-224" */
1095, /* "SHA512-256" */
1100, /* "SHAKE128" */
1101, /* "SHAKE256" */
1172, /* "SM2" */
1143, /* "SM3" */
1134, /* "SM4-CBC" */
1137, /* "SM4-CFB" */
1136, /* "SM4-CFB1" */
1138, /* "SM4-CFB8" */
1139, /* "SM4-CTR" */
1133, /* "SM4-ECB" */
1135, /* "SM4-OFB" */
188, /* "SMIME" */
167, /* "SMIME-CAPS" */
100, /* "SN" */
1006, /* "SNILS" */
16, /* "ST" */
143, /* "SXNetID" */
1062, /* "SipHash" */
1021, /* "TLS1-PRF" */
458, /* "UID" */
0, /* "UNDEF" */
1034, /* "X25519" */
1035, /* "X448" */
11, /* "X500" */
378, /* "X500algorithms" */
12, /* "X509" */
184, /* "X9-57" */
185, /* "X9cm" */
125, /* "ZLIB" */
478, /* "aRecord" */
289, /* "aaControls" */
287, /* "ac-auditEntity" */
397, /* "ac-proxying" */
288, /* "ac-targeting" */
368, /* "acceptableResponses" */
446, /* "account" */
363, /* "ad_timestamping" */
376, /* "algorithm" */
405, /* "ansi-X9-62" */
910, /* "anyExtendedKeyUsage" */
746, /* "anyPolicy" */
370, /* "archiveCutoff" */
484, /* "associatedDomain" */
485, /* "associatedName" */
501, /* "audio" */
177, /* "authorityInfoAccess" */
90, /* "authorityKeyIdentifier" */
882, /* "authorityRevocationList" */
87, /* "basicConstraints" */
365, /* "basicOCSPResponse" */
285, /* "biometricInfo" */
921, /* "brainpoolP160r1" */
922, /* "brainpoolP160t1" */
923, /* "brainpoolP192r1" */
924, /* "brainpoolP192t1" */
925, /* "brainpoolP224r1" */
926, /* "brainpoolP224t1" */
927, /* "brainpoolP256r1" */
928, /* "brainpoolP256t1" */
929, /* "brainpoolP320r1" */
930, /* "brainpoolP320t1" */
931, /* "brainpoolP384r1" */
932, /* "brainpoolP384t1" */
933, /* "brainpoolP512r1" */
934, /* "brainpoolP512t1" */
494, /* "buildingName" */
860, /* "businessCategory" */
691, /* "c2onb191v4" */
692, /* "c2onb191v5" */
697, /* "c2onb239v4" */
698, /* "c2onb239v5" */
684, /* "c2pnb163v1" */
685, /* "c2pnb163v2" */
686, /* "c2pnb163v3" */
687, /* "c2pnb176v1" */
693, /* "c2pnb208w1" */
699, /* "c2pnb272w1" */
700, /* "c2pnb304w1" */
702, /* "c2pnb368w1" */
688, /* "c2tnb191v1" */
689, /* "c2tnb191v2" */
690, /* "c2tnb191v3" */
694, /* "c2tnb239v1" */
695, /* "c2tnb239v2" */
696, /* "c2tnb239v3" */
701, /* "c2tnb359v1" */
703, /* "c2tnb431r1" */
1090, /* "c3" */
881, /* "cACertificate" */
483, /* "cNAMERecord" */
179, /* "caIssuers" */
785, /* "caRepository" */
1023, /* "capwapAC" */
1024, /* "capwapWTP" */
443, /* "caseIgnoreIA5StringSyntax" */
152, /* "certBag" */
677, /* "certicom-arc" */
771, /* "certificateIssuer" */
89, /* "certificatePolicies" */
883, /* "certificateRevocationList" */
54, /* "challengePassword" */
407, /* "characteristic-two-field" */
395, /* "clearance" */
130, /* "clientAuth" */
1131, /* "cmcCA" */
1132, /* "cmcRA" */
131, /* "codeSigning" */
50, /* "contentType" */
53, /* "countersignature" */
153, /* "crlBag" */
103, /* "crlDistributionPoints" */
88, /* "crlNumber" */
884, /* "crossCertificatePair" */
806, /* "cryptocom" */
805, /* "cryptopro" */
954, /* "ct_cert_scts" */
952, /* "ct_precert_poison" */
951, /* "ct_precert_scts" */
953, /* "ct_precert_signer" */
500, /* "dITRedirect" */
451, /* "dNSDomain" */
495, /* "dSAQuality" */
434, /* "data" */
390, /* "dcobject" */
140, /* "deltaCRL" */
891, /* "deltaRevocationList" */
107, /* "description" */
871, /* "destinationIndicator" */
947, /* "dh-cofactor-kdf" */
946, /* "dh-std-kdf" */
28, /* "dhKeyAgreement" */
941, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
942, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
943, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
944, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
945, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
936, /* "dhSinglePass-stdDH-sha1kdf-scheme" */
937, /* "dhSinglePass-stdDH-sha224kdf-scheme" */
938, /* "dhSinglePass-stdDH-sha256kdf-scheme" */
939, /* "dhSinglePass-stdDH-sha384kdf-scheme" */
940, /* "dhSinglePass-stdDH-sha512kdf-scheme" */
920, /* "dhpublicnumber" */
382, /* "directory" */
887, /* "distinguishedName" */
892, /* "dmdName" */
174, /* "dnQualifier" */
1092, /* "dnsName" */
447, /* "document" */
471, /* "documentAuthor" */
468, /* "documentIdentifier" */
472, /* "documentLocation" */
502, /* "documentPublisher" */
449, /* "documentSeries" */
469, /* "documentTitle" */
470, /* "documentVersion" */
392, /* "domain" */
452, /* "domainRelatedObject" */
802, /* "dsa_with_SHA224" */
803, /* "dsa_with_SHA256" */
1152, /* "dstu28147" */
1154, /* "dstu28147-cfb" */
1153, /* "dstu28147-ofb" */
1155, /* "dstu28147-wrap" */
1157, /* "dstu34311" */
1159, /* "dstu4145be" */
1158, /* "dstu4145le" */
791, /* "ecdsa-with-Recommended" */
416, /* "ecdsa-with-SHA1" */
793, /* "ecdsa-with-SHA224" */
794, /* "ecdsa-with-SHA256" */
795, /* "ecdsa-with-SHA384" */
796, /* "ecdsa-with-SHA512" */
792, /* "ecdsa-with-Specified" */
48, /* "emailAddress" */
132, /* "emailProtection" */
885, /* "enhancedSearchGuide" */
389, /* "enterprises" */
384, /* "experimental" */
172, /* "extReq" */
56, /* "extendedCertificateAttributes" */
126, /* "extendedKeyUsage" */
372, /* "extendedStatus" */
867, /* "facsimileTelephoneNumber" */
462, /* "favouriteDrink" */
1126, /* "ffdhe2048" */
1127, /* "ffdhe3072" */
1128, /* "ffdhe4096" */
1129, /* "ffdhe6144" */
1130, /* "ffdhe8192" */
857, /* "freshestCRL" */
453, /* "friendlyCountry" */
490, /* "friendlyCountryName" */
156, /* "friendlyName" */
509, /* "generationQualifier" */
815, /* "gost-mac" */
976, /* "gost-mac-12" */
811, /* "gost2001" */
851, /* "gost2001cc" */
979, /* "gost2012_256" */
980, /* "gost2012_512" */
813, /* "gost89" */
1009, /* "gost89-cbc" */
814, /* "gost89-cnt" */
975, /* "gost89-cnt-12" */
1011, /* "gost89-ctr" */
1010, /* "gost89-ecb" */
812, /* "gost94" */
850, /* "gost94cc" */
1015, /* "grasshopper-cbc" */
1016, /* "grasshopper-cfb" */
1013, /* "grasshopper-ctr" */
1012, /* "grasshopper-ecb" */
1017, /* "grasshopper-mac" */
1014, /* "grasshopper-ofb" */
1156, /* "hmacWithDstu34311" */
797, /* "hmacWithMD5" */
163, /* "hmacWithSHA1" */
798, /* "hmacWithSHA224" */
799, /* "hmacWithSHA256" */
800, /* "hmacWithSHA384" */
801, /* "hmacWithSHA512" */
1193, /* "hmacWithSHA512-224" */
1194, /* "hmacWithSHA512-256" */
432, /* "holdInstructionCallIssuer" */
430, /* "holdInstructionCode" */
431, /* "holdInstructionNone" */
433, /* "holdInstructionReject" */
486, /* "homePostalAddress" */
473, /* "homeTelephoneNumber" */
466, /* "host" */
889, /* "houseIdentifier" */
442, /* "iA5StringSyntax" */
783, /* "id-DHBasedMac" */
824, /* "id-Gost28147-89-CryptoPro-A-ParamSet" */
825, /* "id-Gost28147-89-CryptoPro-B-ParamSet" */
826, /* "id-Gost28147-89-CryptoPro-C-ParamSet" */
827, /* "id-Gost28147-89-CryptoPro-D-ParamSet" */
819, /* "id-Gost28147-89-CryptoPro-KeyMeshing" */
829, /* "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" */
828, /* "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" */
830, /* "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" */
820, /* "id-Gost28147-89-None-KeyMeshing" */
823, /* "id-Gost28147-89-TestParamSet" */
849, /* "id-Gost28147-89-cc" */
840, /* "id-GostR3410-2001-CryptoPro-A-ParamSet" */
841, /* "id-GostR3410-2001-CryptoPro-B-ParamSet" */
842, /* "id-GostR3410-2001-CryptoPro-C-ParamSet" */
843, /* "id-GostR3410-2001-CryptoPro-XchA-ParamSet" */
844, /* "id-GostR3410-2001-CryptoPro-XchB-ParamSet" */
854, /* "id-GostR3410-2001-ParamSet-cc" */
839, /* "id-GostR3410-2001-TestParamSet" */
817, /* "id-GostR3410-2001DH" */
832, /* "id-GostR3410-94-CryptoPro-A-ParamSet" */
833, /* "id-GostR3410-94-CryptoPro-B-ParamSet" */
834, /* "id-GostR3410-94-CryptoPro-C-ParamSet" */
835, /* "id-GostR3410-94-CryptoPro-D-ParamSet" */
836, /* "id-GostR3410-94-CryptoPro-XchA-ParamSet" */
837, /* "id-GostR3410-94-CryptoPro-XchB-ParamSet" */
838, /* "id-GostR3410-94-CryptoPro-XchC-ParamSet" */
831, /* "id-GostR3410-94-TestParamSet" */
845, /* "id-GostR3410-94-a" */
846, /* "id-GostR3410-94-aBis" */
847, /* "id-GostR3410-94-b" */
848, /* "id-GostR3410-94-bBis" */
818, /* "id-GostR3410-94DH" */
822, /* "id-GostR3411-94-CryptoProParamSet" */
821, /* "id-GostR3411-94-TestParamSet" */
807, /* "id-GostR3411-94-with-GostR3410-2001" */
853, /* "id-GostR3411-94-with-GostR3410-2001-cc" */
808, /* "id-GostR3411-94-with-GostR3410-94" */
852, /* "id-GostR3411-94-with-GostR3410-94-cc" */
810, /* "id-HMACGostR3411-94" */
782, /* "id-PasswordBasedMAC" */
266, /* "id-aca" */
355, /* "id-aca-accessIdentity" */
354, /* "id-aca-authenticationInfo" */
356, /* "id-aca-chargingIdentity" */
399, /* "id-aca-encAttrs" */
357, /* "id-aca-group" */
358, /* "id-aca-role" */
176, /* "id-ad" */
896, /* "id-aes128-CCM" */
895, /* "id-aes128-GCM" */
788, /* "id-aes128-wrap" */
897, /* "id-aes128-wrap-pad" */
899, /* "id-aes192-CCM" */
898, /* "id-aes192-GCM" */
789, /* "id-aes192-wrap" */
900, /* "id-aes192-wrap-pad" */
902, /* "id-aes256-CCM" */
901, /* "id-aes256-GCM" */
790, /* "id-aes256-wrap" */
903, /* "id-aes256-wrap-pad" */
262, /* "id-alg" */
893, /* "id-alg-PWRI-KEK" */
323, /* "id-alg-des40" */
326, /* "id-alg-dh-pop" */
325, /* "id-alg-dh-sig-hmac-sha1" */
324, /* "id-alg-noSignature" */
907, /* "id-camellia128-wrap" */
908, /* "id-camellia192-wrap" */
909, /* "id-camellia256-wrap" */
268, /* "id-cct" */
361, /* "id-cct-PKIData" */
362, /* "id-cct-PKIResponse" */
360, /* "id-cct-crs" */
81, /* "id-ce" */
680, /* "id-characteristic-two-basis" */
263, /* "id-cmc" */
334, /* "id-cmc-addExtensions" */
346, /* "id-cmc-confirmCertAcceptance" */
330, /* "id-cmc-dataReturn" */
336, /* "id-cmc-decryptedPOP" */
335, /* "id-cmc-encryptedPOP" */
339, /* "id-cmc-getCRL" */
338, /* "id-cmc-getCert" */
328, /* "id-cmc-identification" */
329, /* "id-cmc-identityProof" */
337, /* "id-cmc-lraPOPWitness" */
344, /* "id-cmc-popLinkRandom" */
345, /* "id-cmc-popLinkWitness" */
343, /* "id-cmc-queryPending" */
333, /* "id-cmc-recipientNonce" */
341, /* "id-cmc-regInfo" */
342, /* "id-cmc-responseInfo" */
340, /* "id-cmc-revokeRequest" */
332, /* "id-cmc-senderNonce" */
327, /* "id-cmc-statusInfo" */
331, /* "id-cmc-transactionId" */
787, /* "id-ct-asciiTextWithCRLF" */
1060, /* "id-ct-xml" */
1108, /* "id-dsa-with-sha3-224" */
1109, /* "id-dsa-with-sha3-256" */
1110, /* "id-dsa-with-sha3-384" */
1111, /* "id-dsa-with-sha3-512" */
1106, /* "id-dsa-with-sha384" */
1107, /* "id-dsa-with-sha512" */
408, /* "id-ecPublicKey" */
1112, /* "id-ecdsa-with-sha3-224" */
1113, /* "id-ecdsa-with-sha3-256" */
1114, /* "id-ecdsa-with-sha3-384" */
1115, /* "id-ecdsa-with-sha3-512" */
508, /* "id-hex-multipart-message" */
507, /* "id-hex-partial-message" */
1102, /* "id-hmacWithSHA3-224" */
1103, /* "id-hmacWithSHA3-256" */
1104, /* "id-hmacWithSHA3-384" */
1105, /* "id-hmacWithSHA3-512" */
260, /* "id-it" */
302, /* "id-it-caKeyUpdateInfo" */
298, /* "id-it-caProtEncCert" */
311, /* "id-it-confirmWaitTime" */
303, /* "id-it-currentCRL" */
300, /* "id-it-encKeyPairTypes" */
310, /* "id-it-implicitConfirm" */
308, /* "id-it-keyPairParamRep" */
307, /* "id-it-keyPairParamReq" */
312, /* "id-it-origPKIMessage" */
301, /* "id-it-preferredSymmAlg" */
309, /* "id-it-revPassphrase" */
299, /* "id-it-signKeyPairTypes" */
305, /* "id-it-subscriptionRequest" */
306, /* "id-it-subscriptionResponse" */
784, /* "id-it-suppLangTags" */
304, /* "id-it-unsupportedOIDs" */
128, /* "id-kp" */
280, /* "id-mod-attribute-cert" */
274, /* "id-mod-cmc" */
277, /* "id-mod-cmp" */
284, /* "id-mod-cmp2000" */
273, /* "id-mod-crmf" */
283, /* "id-mod-dvcs" */
275, /* "id-mod-kea-profile-88" */
276, /* "id-mod-kea-profile-93" */
282, /* "id-mod-ocsp" */
278, /* "id-mod-qualified-cert-88" */
279, /* "id-mod-qualified-cert-93" */
281, /* "id-mod-timestamp-protocol" */
264, /* "id-on" */
858, /* "id-on-permanentIdentifier" */
347, /* "id-on-personalData" */
265, /* "id-pda" */
352, /* "id-pda-countryOfCitizenship" */
353, /* "id-pda-countryOfResidence" */
348, /* "id-pda-dateOfBirth" */
351, /* "id-pda-gender" */
349, /* "id-pda-placeOfBirth" */
175, /* "id-pe" */
1031, /* "id-pkinit" */
261, /* "id-pkip" */
258, /* "id-pkix-mod" */
269, /* "id-pkix1-explicit-88" */
271, /* "id-pkix1-explicit-93" */
270, /* "id-pkix1-implicit-88" */
272, /* "id-pkix1-implicit-93" */
662, /* "id-ppl" */
664, /* "id-ppl-anyLanguage" */
667, /* "id-ppl-independent" */
665, /* "id-ppl-inheritAll" */
267, /* "id-qcs" */
359, /* "id-qcs-pkixQCSyntax-v1" */
259, /* "id-qt" */
164, /* "id-qt-cps" */
165, /* "id-qt-unotice" */
313, /* "id-regCtrl" */
316, /* "id-regCtrl-authenticator" */
319, /* "id-regCtrl-oldCertID" */
318, /* "id-regCtrl-pkiArchiveOptions" */
317, /* "id-regCtrl-pkiPublicationInfo" */
320, /* "id-regCtrl-protocolEncrKey" */
315, /* "id-regCtrl-regToken" */
314, /* "id-regInfo" */
322, /* "id-regInfo-certReq" */
321, /* "id-regInfo-utf8Pairs" */
1116, /* "id-rsassa-pkcs1-v1_5-with-sha3-224" */
1117, /* "id-rsassa-pkcs1-v1_5-with-sha3-256" */
1118, /* "id-rsassa-pkcs1-v1_5-with-sha3-384" */
1119, /* "id-rsassa-pkcs1-v1_5-with-sha3-512" */
973, /* "id-scrypt" */
512, /* "id-set" */
191, /* "id-smime-aa" */
215, /* "id-smime-aa-contentHint" */
218, /* "id-smime-aa-contentIdentifier" */
221, /* "id-smime-aa-contentReference" */
240, /* "id-smime-aa-dvcs-dvc" */
217, /* "id-smime-aa-encapContentType" */
222, /* "id-smime-aa-encrypKeyPref" */
220, /* "id-smime-aa-equivalentLabels" */
232, /* "id-smime-aa-ets-CertificateRefs" */
233, /* "id-smime-aa-ets-RevocationRefs" */
238, /* "id-smime-aa-ets-archiveTimeStamp" */
237, /* "id-smime-aa-ets-certCRLTimestamp" */
234, /* "id-smime-aa-ets-certValues" */
227, /* "id-smime-aa-ets-commitmentType" */
231, /* "id-smime-aa-ets-contentTimestamp" */
236, /* "id-smime-aa-ets-escTimeStamp" */
230, /* "id-smime-aa-ets-otherSigCert" */
235, /* "id-smime-aa-ets-revocationValues" */
226, /* "id-smime-aa-ets-sigPolicyId" */
229, /* "id-smime-aa-ets-signerAttr" */
228, /* "id-smime-aa-ets-signerLocation" */
219, /* "id-smime-aa-macValue" */
214, /* "id-smime-aa-mlExpandHistory" */
216, /* "id-smime-aa-msgSigDigest" */
212, /* "id-smime-aa-receiptRequest" */
213, /* "id-smime-aa-securityLabel" */
239, /* "id-smime-aa-signatureType" */
223, /* "id-smime-aa-signingCertificate" */
1086, /* "id-smime-aa-signingCertificateV2" */
224, /* "id-smime-aa-smimeEncryptCerts" */
225, /* "id-smime-aa-timeStampToken" */
192, /* "id-smime-alg" */
243, /* "id-smime-alg-3DESwrap" */
246, /* "id-smime-alg-CMS3DESwrap" */
247, /* "id-smime-alg-CMSRC2wrap" */
245, /* "id-smime-alg-ESDH" */
241, /* "id-smime-alg-ESDHwith3DES" */
242, /* "id-smime-alg-ESDHwithRC2" */
244, /* "id-smime-alg-RC2wrap" */
193, /* "id-smime-cd" */
248, /* "id-smime-cd-ldap" */
190, /* "id-smime-ct" */
210, /* "id-smime-ct-DVCSRequestData" */
211, /* "id-smime-ct-DVCSResponseData" */
208, /* "id-smime-ct-TDTInfo" */
207, /* "id-smime-ct-TSTInfo" */
205, /* "id-smime-ct-authData" */
1059, /* "id-smime-ct-authEnvelopedData" */
786, /* "id-smime-ct-compressedData" */
1058, /* "id-smime-ct-contentCollection" */
209, /* "id-smime-ct-contentInfo" */
206, /* "id-smime-ct-publishCert" */
204, /* "id-smime-ct-receipt" */
195, /* "id-smime-cti" */
255, /* "id-smime-cti-ets-proofOfApproval" */
256, /* "id-smime-cti-ets-proofOfCreation" */
253, /* "id-smime-cti-ets-proofOfDelivery" */
251, /* "id-smime-cti-ets-proofOfOrigin" */
252, /* "id-smime-cti-ets-proofOfReceipt" */
254, /* "id-smime-cti-ets-proofOfSender" */
189, /* "id-smime-mod" */
196, /* "id-smime-mod-cms" */
197, /* "id-smime-mod-ess" */
202, /* "id-smime-mod-ets-eSigPolicy-88" */
203, /* "id-smime-mod-ets-eSigPolicy-97" */
200, /* "id-smime-mod-ets-eSignature-88" */
201, /* "id-smime-mod-ets-eSignature-97" */
199, /* "id-smime-mod-msg-v3" */
198, /* "id-smime-mod-oid" */
194, /* "id-smime-spq" */
250, /* "id-smime-spq-ets-sqt-unotice" */
249, /* "id-smime-spq-ets-sqt-uri" */
974, /* "id-tc26" */
991, /* "id-tc26-agreement" */
992, /* "id-tc26-agreement-gost-3410-2012-256" */
993, /* "id-tc26-agreement-gost-3410-2012-512" */
977, /* "id-tc26-algorithms" */
990, /* "id-tc26-cipher" */
1001, /* "id-tc26-cipher-constants" */
1176, /* "id-tc26-cipher-gostr3412-2015-kuznyechik" */
1177, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" */
1178, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" */
1173, /* "id-tc26-cipher-gostr3412-2015-magma" */
1174, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" */
1175, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" */
994, /* "id-tc26-constants" */
981, /* "id-tc26-digest" */
1000, /* "id-tc26-digest-constants" */
1002, /* "id-tc26-gost-28147-constants" */
1003, /* "id-tc26-gost-28147-param-Z" */
1147, /* "id-tc26-gost-3410-2012-256-constants" */
1148, /* "id-tc26-gost-3410-2012-256-paramSetA" */
1184, /* "id-tc26-gost-3410-2012-256-paramSetB" */
1185, /* "id-tc26-gost-3410-2012-256-paramSetC" */
1186, /* "id-tc26-gost-3410-2012-256-paramSetD" */
996, /* "id-tc26-gost-3410-2012-512-constants" */
998, /* "id-tc26-gost-3410-2012-512-paramSetA" */
999, /* "id-tc26-gost-3410-2012-512-paramSetB" */
1149, /* "id-tc26-gost-3410-2012-512-paramSetC" */
997, /* "id-tc26-gost-3410-2012-512-paramSetTest" */
988, /* "id-tc26-hmac-gost-3411-2012-256" */
989, /* "id-tc26-hmac-gost-3411-2012-512" */
987, /* "id-tc26-mac" */
978, /* "id-tc26-sign" */
995, /* "id-tc26-sign-constants" */
984, /* "id-tc26-signwithdigest" */
985, /* "id-tc26-signwithdigest-gost3410-2012-256" */
986, /* "id-tc26-signwithdigest-gost3410-2012-512" */
1179, /* "id-tc26-wrap" */
1182, /* "id-tc26-wrap-gostr3412-2015-kuznyechik" */
1183, /* "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" */
1180, /* "id-tc26-wrap-gostr3412-2015-magma" */
1181, /* "id-tc26-wrap-gostr3412-2015-magma-kexp15" */
676, /* "identified-organization" */
1170, /* "ieee" */
1171, /* "ieee-siswg" */
461, /* "info" */
748, /* "inhibitAnyPolicy" */
101, /* "initials" */
647, /* "international-organizations" */
869, /* "internationaliSDNNumber" */
142, /* "invalidityDate" */
294, /* "ipsecEndSystem" */
1022, /* "ipsecIKE" */
295, /* "ipsecTunnel" */
296, /* "ipsecUser" */
86, /* "issuerAltName" */
1008, /* "issuerSignTool" */
770, /* "issuingDistributionPoint" */
492, /* "janetMailbox" */
957, /* "jurisdictionC" */
955, /* "jurisdictionL" */
956, /* "jurisdictionST" */
150, /* "keyBag" */
83, /* "keyUsage" */
477, /* "lastModifiedBy" */
476, /* "lastModifiedTime" */
157, /* "localKeyID" */
480, /* "mXRecord" */
1190, /* "magma-cbc" */
1191, /* "magma-cfb" */
1188, /* "magma-ctr" */
1187, /* "magma-ecb" */
1192, /* "magma-mac" */
1189, /* "magma-ofb" */
460, /* "mail" */
493, /* "mailPreferenceOption" */
467, /* "manager" */
982, /* "md_gost12_256" */
983, /* "md_gost12_512" */
809, /* "md_gost94" */
875, /* "member" */
182, /* "member-body" */
51, /* "messageDigest" */
383, /* "mgmt" */
504, /* "mime-mhs" */
506, /* "mime-mhs-bodies" */
505, /* "mime-mhs-headings" */
488, /* "mobileTelephoneNumber" */
136, /* "msCTLSign" */
135, /* "msCodeCom" */
134, /* "msCodeInd" */
138, /* "msEFS" */
171, /* "msExtReq" */
137, /* "msSGC" */
648, /* "msSmartcardLogin" */
649, /* "msUPN" */
1091, /* "n3" */
481, /* "nSRecord" */
173, /* "name" */
666, /* "nameConstraints" */
369, /* "noCheck" */
403, /* "noRevAvail" */
72, /* "nsBaseUrl" */
76, /* "nsCaPolicyUrl" */
74, /* "nsCaRevocationUrl" */
58, /* "nsCertExt" */
79, /* "nsCertSequence" */
71, /* "nsCertType" */
78, /* "nsComment" */
59, /* "nsDataType" */
75, /* "nsRenewalUrl" */
73, /* "nsRevocationUrl" */
139, /* "nsSGC" */
77, /* "nsSslServerName" */
681, /* "onBasis" */
1089, /* "organizationIdentifier" */
491, /* "organizationalStatus" */
1141, /* "oscca" */
475, /* "otherMailbox" */
876, /* "owner" */
489, /* "pagerTelephoneNumber" */
374, /* "path" */
112, /* "pbeWithMD5AndCast5CBC" */
499, /* "personalSignature" */
487, /* "personalTitle" */
464, /* "photo" */
863, /* "physicalDeliveryOfficeName" */
437, /* "pilot" */
439, /* "pilotAttributeSyntax" */
438, /* "pilotAttributeType" */
479, /* "pilotAttributeType27" */
456, /* "pilotDSA" */
441, /* "pilotGroups" */
444, /* "pilotObject" */
440, /* "pilotObjectClass" */
455, /* "pilotOrganization" */
445, /* "pilotPerson" */
1032, /* "pkInitClientAuth" */
1033, /* "pkInitKDC" */
2, /* "pkcs" */
186, /* "pkcs1" */
27, /* "pkcs3" */
187, /* "pkcs5" */
20, /* "pkcs7" */
21, /* "pkcs7-data" */
25, /* "pkcs7-digestData" */
26, /* "pkcs7-encryptedData" */
23, /* "pkcs7-envelopedData" */
24, /* "pkcs7-signedAndEnvelopedData" */
22, /* "pkcs7-signedData" */
151, /* "pkcs8ShroudedKeyBag" */
47, /* "pkcs9" */
401, /* "policyConstraints" */
747, /* "policyMappings" */
862, /* "postOfficeBox" */
861, /* "postalAddress" */
661, /* "postalCode" */
683, /* "ppBasis" */
872, /* "preferredDeliveryMethod" */
873, /* "presentationAddress" */
816, /* "prf-gostr3411-94" */
406, /* "prime-field" */
409, /* "prime192v1" */
410, /* "prime192v2" */
411, /* "prime192v3" */
412, /* "prime239v1" */
413, /* "prime239v2" */
414, /* "prime239v3" */
415, /* "prime256v1" */
385, /* "private" */
84, /* "privateKeyUsagePeriod" */
886, /* "protocolInformation" */
663, /* "proxyCertInfo" */
510, /* "pseudonym" */
435, /* "pss" */
286, /* "qcStatements" */
457, /* "qualityLabelledData" */
450, /* "rFC822localPart" */
870, /* "registeredAddress" */
400, /* "role" */
877, /* "roleOccupant" */
448, /* "room" */
463, /* "roomNumber" */
6, /* "rsaEncryption" */
644, /* "rsaOAEPEncryptionSET" */
377, /* "rsaSignature" */
1, /* "rsadsi" */
482, /* "sOARecord" */
155, /* "safeContentsBag" */
291, /* "sbgp-autonomousSysNum" */
290, /* "sbgp-ipAddrBlock" */
292, /* "sbgp-routerIdentifier" */
159, /* "sdsiCertificate" */
859, /* "searchGuide" */
704, /* "secp112r1" */
705, /* "secp112r2" */
706, /* "secp128r1" */
707, /* "secp128r2" */
708, /* "secp160k1" */
709, /* "secp160r1" */
710, /* "secp160r2" */
711, /* "secp192k1" */
712, /* "secp224k1" */
713, /* "secp224r1" */
714, /* "secp256k1" */
715, /* "secp384r1" */
716, /* "secp521r1" */
154, /* "secretBag" */
474, /* "secretary" */
717, /* "sect113r1" */
718, /* "sect113r2" */
719, /* "sect131r1" */
720, /* "sect131r2" */
721, /* "sect163k1" */
722, /* "sect163r1" */
723, /* "sect163r2" */
724, /* "sect193r1" */
725, /* "sect193r2" */
726, /* "sect233k1" */
727, /* "sect233r1" */
728, /* "sect239k1" */
729, /* "sect283k1" */
730, /* "sect283r1" */
731, /* "sect409k1" */
732, /* "sect409r1" */
733, /* "sect571k1" */
734, /* "sect571r1" */
1025, /* "secureShellClient" */
1026, /* "secureShellServer" */
386, /* "security" */
878, /* "seeAlso" */
394, /* "selected-attribute-types" */
1029, /* "sendOwner" */
1030, /* "sendProxiedOwner" */
1028, /* "sendProxiedRouter" */
1027, /* "sendRouter" */
105, /* "serialNumber" */
129, /* "serverAuth" */
371, /* "serviceLocator" */
625, /* "set-addPolicy" */
515, /* "set-attr" */
518, /* "set-brand" */
638, /* "set-brand-AmericanExpress" */
637, /* "set-brand-Diners" */
636, /* "set-brand-IATA-ATA" */
639, /* "set-brand-JCB" */
641, /* "set-brand-MasterCard" */
642, /* "set-brand-Novus" */
640, /* "set-brand-Visa" */
517, /* "set-certExt" */
513, /* "set-ctype" */
514, /* "set-msgExt" */
516, /* "set-policy" */
607, /* "set-policy-root" */
624, /* "set-rootKeyThumb" */
620, /* "setAttr-Cert" */
631, /* "setAttr-GenCryptgrm" */
623, /* "setAttr-IssCap" */
628, /* "setAttr-IssCap-CVM" */
630, /* "setAttr-IssCap-Sig" */
629, /* "setAttr-IssCap-T2" */
621, /* "setAttr-PGWYcap" */
635, /* "setAttr-SecDevSig" */
632, /* "setAttr-T2Enc" */
633, /* "setAttr-T2cleartxt" */
634, /* "setAttr-TokICCsig" */
627, /* "setAttr-Token-B0Prime" */
626, /* "setAttr-Token-EMV" */
622, /* "setAttr-TokenType" */
619, /* "setCext-IssuerCapabilities" */
615, /* "setCext-PGWYcapabilities" */
616, /* "setCext-TokenIdentifier" */
618, /* "setCext-TokenType" */
617, /* "setCext-Track2Data" */
611, /* "setCext-cCertRequired" */
609, /* "setCext-certType" */
608, /* "setCext-hashedRoot" */
610, /* "setCext-merchData" */
613, /* "setCext-setExt" */
614, /* "setCext-setQualf" */
612, /* "setCext-tunneling" */
540, /* "setct-AcqCardCodeMsg" */
576, /* "setct-AcqCardCodeMsgTBE" */
570, /* "setct-AuthReqTBE" */
534, /* "setct-AuthReqTBS" */
527, /* "setct-AuthResBaggage" */
571, /* "setct-AuthResTBE" */
572, /* "setct-AuthResTBEX" */
535, /* "setct-AuthResTBS" */
536, /* "setct-AuthResTBSX" */
528, /* "setct-AuthRevReqBaggage" */
577, /* "setct-AuthRevReqTBE" */
541, /* "setct-AuthRevReqTBS" */
529, /* "setct-AuthRevResBaggage" */
542, /* "setct-AuthRevResData" */
578, /* "setct-AuthRevResTBE" */
579, /* "setct-AuthRevResTBEB" */
543, /* "setct-AuthRevResTBS" */
573, /* "setct-AuthTokenTBE" */
537, /* "setct-AuthTokenTBS" */
600, /* "setct-BCIDistributionTBS" */
558, /* "setct-BatchAdminReqData" */
592, /* "setct-BatchAdminReqTBE" */
559, /* "setct-BatchAdminResData" */
593, /* "setct-BatchAdminResTBE" */
599, /* "setct-CRLNotificationResTBS" */
598, /* "setct-CRLNotificationTBS" */
580, /* "setct-CapReqTBE" */
581, /* "setct-CapReqTBEX" */
544, /* "setct-CapReqTBS" */
545, /* "setct-CapReqTBSX" */
546, /* "setct-CapResData" */
582, /* "setct-CapResTBE" */
583, /* "setct-CapRevReqTBE" */
584, /* "setct-CapRevReqTBEX" */
547, /* "setct-CapRevReqTBS" */
548, /* "setct-CapRevReqTBSX" */
549, /* "setct-CapRevResData" */
585, /* "setct-CapRevResTBE" */
538, /* "setct-CapTokenData" */
530, /* "setct-CapTokenSeq" */
574, /* "setct-CapTokenTBE" */
575, /* "setct-CapTokenTBEX" */
539, /* "setct-CapTokenTBS" */
560, /* "setct-CardCInitResTBS" */
566, /* "setct-CertInqReqTBS" */
563, /* "setct-CertReqData" */
595, /* "setct-CertReqTBE" */
596, /* "setct-CertReqTBEX" */
564, /* "setct-CertReqTBS" */
565, /* "setct-CertResData" */
597, /* "setct-CertResTBE" */
586, /* "setct-CredReqTBE" */
587, /* "setct-CredReqTBEX" */
550, /* "setct-CredReqTBS" */
551, /* "setct-CredReqTBSX" */
552, /* "setct-CredResData" */
588, /* "setct-CredResTBE" */
589, /* "setct-CredRevReqTBE" */
590, /* "setct-CredRevReqTBEX" */
553, /* "setct-CredRevReqTBS" */
554, /* "setct-CredRevReqTBSX" */
555, /* "setct-CredRevResData" */
591, /* "setct-CredRevResTBE" */
567, /* "setct-ErrorTBS" */
526, /* "setct-HODInput" */
561, /* "setct-MeAqCInitResTBS" */
522, /* "setct-OIData" */
519, /* "setct-PANData" */
521, /* "setct-PANOnly" */
520, /* "setct-PANToken" */
556, /* "setct-PCertReqData" */
557, /* "setct-PCertResTBS" */
523, /* "setct-PI" */
532, /* "setct-PI-TBS" */
524, /* "setct-PIData" */
525, /* "setct-PIDataUnsigned" */
568, /* "setct-PIDualSignedTBE" */
569, /* "setct-PIUnsignedTBE" */
531, /* "setct-PInitResData" */
533, /* "setct-PResData" */
594, /* "setct-RegFormReqTBE" */
562, /* "setct-RegFormResTBS" */
606, /* "setext-cv" */
601, /* "setext-genCrypt" */
602, /* "setext-miAuth" */
604, /* "setext-pinAny" */
603, /* "setext-pinSecure" */
605, /* "setext-track2" */
52, /* "signingTime" */
454, /* "simpleSecurityObject" */
496, /* "singleLevelQuality" */
1142, /* "sm-scheme" */
387, /* "snmpv2" */
660, /* "street" */
85, /* "subjectAltName" */
769, /* "subjectDirectoryAttributes" */
398, /* "subjectInfoAccess" */
82, /* "subjectKeyIdentifier" */
1007, /* "subjectSignTool" */
498, /* "subtreeMaximumQuality" */
497, /* "subtreeMinimumQuality" */
890, /* "supportedAlgorithms" */
874, /* "supportedApplicationContext" */
402, /* "targetInformation" */
864, /* "telephoneNumber" */
866, /* "teletexTerminalIdentifier" */
865, /* "telexNumber" */
459, /* "textEncodedORAddress" */
293, /* "textNotice" */
133, /* "timeStamping" */
106, /* "title" */
1020, /* "tlsfeature" */
682, /* "tpBasis" */
375, /* "trustRoot" */
1151, /* "ua-pki" */
1160, /* "uacurve0" */
1161, /* "uacurve1" */
1162, /* "uacurve2" */
1163, /* "uacurve3" */
1164, /* "uacurve4" */
1165, /* "uacurve5" */
1166, /* "uacurve6" */
1167, /* "uacurve7" */
1168, /* "uacurve8" */
1169, /* "uacurve9" */
436, /* "ucl" */
102, /* "uid" */
888, /* "uniqueMember" */
55, /* "unstructuredAddress" */
49, /* "unstructuredName" */
880, /* "userCertificate" */
465, /* "userClass" */
879, /* "userPassword" */
373, /* "valid" */
678, /* "wap" */
679, /* "wap-wsg" */
735, /* "wap-wsg-idm-ecid-wtls1" */
743, /* "wap-wsg-idm-ecid-wtls10" */
744, /* "wap-wsg-idm-ecid-wtls11" */
745, /* "wap-wsg-idm-ecid-wtls12" */
736, /* "wap-wsg-idm-ecid-wtls3" */
737, /* "wap-wsg-idm-ecid-wtls4" */
738, /* "wap-wsg-idm-ecid-wtls5" */
739, /* "wap-wsg-idm-ecid-wtls6" */
740, /* "wap-wsg-idm-ecid-wtls7" */
741, /* "wap-wsg-idm-ecid-wtls8" */
742, /* "wap-wsg-idm-ecid-wtls9" */
804, /* "whirlpool" */
868, /* "x121Address" */
503, /* "x500UniqueIdentifier" */
158, /* "x509Certificate" */
160, /* "x509Crl" */
1093, /* "x509ExtAdmission" */
};
#define NUM_LN 1186
static const unsigned int ln_objs[NUM_LN] = {
363, /* "AD Time Stamping" */
405, /* "ANSI X9.62" */
368, /* "Acceptable OCSP Responses" */
910, /* "Any Extended Key Usage" */
664, /* "Any language" */
177, /* "Authority Information Access" */
365, /* "Basic OCSP Response" */
285, /* "Biometric Info" */
179, /* "CA Issuers" */
785, /* "CA Repository" */
1131, /* "CMC Certificate Authority" */
1132, /* "CMC Registration Authority" */
954, /* "CT Certificate SCTs" */
952, /* "CT Precertificate Poison" */
951, /* "CT Precertificate SCTs" */
953, /* "CT Precertificate Signer" */
131, /* "Code Signing" */
1024, /* "Ctrl/Provision WAP Termination" */
1023, /* "Ctrl/provision WAP Access" */
1159, /* "DSTU 4145-2002 big endian" */
1158, /* "DSTU 4145-2002 little endian" */
1152, /* "DSTU Gost 28147-2009" */
1154, /* "DSTU Gost 28147-2009 CFB mode" */
1153, /* "DSTU Gost 28147-2009 OFB mode" */
1155, /* "DSTU Gost 28147-2009 key wrap" */
1157, /* "DSTU Gost 34311-95" */
1160, /* "DSTU curve 0" */
1161, /* "DSTU curve 1" */
1162, /* "DSTU curve 2" */
1163, /* "DSTU curve 3" */
1164, /* "DSTU curve 4" */
1165, /* "DSTU curve 5" */
1166, /* "DSTU curve 6" */
1167, /* "DSTU curve 7" */
1168, /* "DSTU curve 8" */
1169, /* "DSTU curve 9" */
783, /* "Diffie-Hellman based MAC" */
382, /* "Directory" */
392, /* "Domain" */
132, /* "E-mail Protection" */
1087, /* "ED25519" */
1088, /* "ED448" */
389, /* "Enterprises" */
384, /* "Experimental" */
372, /* "Extended OCSP Status" */
172, /* "Extension Request" */
813, /* "GOST 28147-89" */
849, /* "GOST 28147-89 Cryptocom ParamSet" */
815, /* "GOST 28147-89 MAC" */
1003, /* "GOST 28147-89 TC26 parameter set" */
851, /* "GOST 34.10-2001 Cryptocom" */
850, /* "GOST 34.10-94 Cryptocom" */
811, /* "GOST R 34.10-2001" */
817, /* "GOST R 34.10-2001 DH" */
1148, /* "GOST R 34.10-2012 (256 bit) ParamSet A" */
1184, /* "GOST R 34.10-2012 (256 bit) ParamSet B" */
1185, /* "GOST R 34.10-2012 (256 bit) ParamSet C" */
1186, /* "GOST R 34.10-2012 (256 bit) ParamSet D" */
998, /* "GOST R 34.10-2012 (512 bit) ParamSet A" */
999, /* "GOST R 34.10-2012 (512 bit) ParamSet B" */
1149, /* "GOST R 34.10-2012 (512 bit) ParamSet C" */
997, /* "GOST R 34.10-2012 (512 bit) testing parameter set" */
979, /* "GOST R 34.10-2012 with 256 bit modulus" */
980, /* "GOST R 34.10-2012 with 512 bit modulus" */
985, /* "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)" */
986, /* "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)" */
812, /* "GOST R 34.10-94" */
818, /* "GOST R 34.10-94 DH" */
982, /* "GOST R 34.11-2012 with 256 bit hash" */
983, /* "GOST R 34.11-2012 with 512 bit hash" */
809, /* "GOST R 34.11-94" */
816, /* "GOST R 34.11-94 PRF" */
807, /* "GOST R 34.11-94 with GOST R 34.10-2001" */
853, /* "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom" */
808, /* "GOST R 34.11-94 with GOST R 34.10-94" */
852, /* "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom" */
854, /* "GOST R 3410-2001 Parameter Set Cryptocom" */
1156, /* "HMAC DSTU Gost 34311-95" */
988, /* "HMAC GOST 34.11-2012 256 bit" */
989, /* "HMAC GOST 34.11-2012 512 bit" */
810, /* "HMAC GOST 34.11-94" */
432, /* "Hold Instruction Call Issuer" */
430, /* "Hold Instruction Code" */
431, /* "Hold Instruction None" */
433, /* "Hold Instruction Reject" */
634, /* "ICC or token signature" */
1171, /* "IEEE Security in Storage Working Group" */
1004, /* "INN" */
294, /* "IPSec End System" */
295, /* "IPSec Tunnel" */
296, /* "IPSec User" */
1140, /* "ISO CN Member Body" */
182, /* "ISO Member Body" */
183, /* "ISO US Member Body" */
1150, /* "ISO-UA" */
667, /* "Independent" */
665, /* "Inherit all" */
647, /* "International Organizations" */
142, /* "Invalidity Date" */
504, /* "MIME MHS" */
388, /* "Mail" */
383, /* "Management" */
417, /* "Microsoft CSP Name" */
135, /* "Microsoft Commercial Code Signing" */
138, /* "Microsoft Encrypted File System" */
171, /* "Microsoft Extension Request" */
134, /* "Microsoft Individual Code Signing" */
856, /* "Microsoft Local Key set" */
137, /* "Microsoft Server Gated Crypto" */
648, /* "Microsoft Smartcardlogin" */
136, /* "Microsoft Trust List Signing" */
649, /* "Microsoft Universal Principal Name" */
393, /* "NULL" */
404, /* "NULL" */
72, /* "Netscape Base Url" */
76, /* "Netscape CA Policy Url" */
74, /* "Netscape CA Revocation Url" */
71, /* "Netscape Cert Type" */
58, /* "Netscape Certificate Extension" */
79, /* "Netscape Certificate Sequence" */
78, /* "Netscape Comment" */
57, /* "Netscape Communications Corp." */
59, /* "Netscape Data Type" */
75, /* "Netscape Renewal Url" */
73, /* "Netscape Revocation Url" */
77, /* "Netscape SSL Server Name" */
139, /* "Netscape Server Gated Crypto" */
178, /* "OCSP" */
370, /* "OCSP Archive Cutoff" */
367, /* "OCSP CRL ID" */
369, /* "OCSP No Check" */
366, /* "OCSP Nonce" */
371, /* "OCSP Service Locator" */
180, /* "OCSP Signing" */
1005, /* "OGRN" */
161, /* "PBES2" */
69, /* "PBKDF2" */
162, /* "PBMAC1" */
1032, /* "PKINIT Client Auth" */
127, /* "PKIX" */
858, /* "Permanent Identifier" */
164, /* "Policy Qualifier CPS" */
165, /* "Policy Qualifier User Notice" */
385, /* "Private" */
1093, /* "Professional Information or basis for Admission" */
663, /* "Proxy Certificate Information" */
1, /* "RSA Data Security, Inc." */
2, /* "RSA Data Security, Inc. PKCS" */
1116, /* "RSA-SHA3-224" */
1117, /* "RSA-SHA3-256" */
1118, /* "RSA-SHA3-384" */
1119, /* "RSA-SHA3-512" */
188, /* "S/MIME" */
167, /* "S/MIME Capabilities" */
1006, /* "SNILS" */
387, /* "SNMPv2" */
1025, /* "SSH Client" */
1026, /* "SSH Server" */
512, /* "Secure Electronic Transactions" */
386, /* "Security" */
394, /* "Selected Attribute Types" */
1029, /* "Send Owner" */
1030, /* "Send Proxied Owner" */
1028, /* "Send Proxied Router" */
1027, /* "Send Router" */
1033, /* "Signing KDC Response" */
1008, /* "Signing Tool of Issuer" */
1007, /* "Signing Tool of Subject" */
143, /* "Strong Extranet ID" */
398, /* "Subject Information Access" */
1020, /* "TLS Feature" */
130, /* "TLS Web Client Authentication" */
129, /* "TLS Web Server Authentication" */
133, /* "Time Stamping" */
375, /* "Trust Root" */
1034, /* "X25519" */
1035, /* "X448" */
12, /* "X509" */
402, /* "X509v3 AC Targeting" */
746, /* "X509v3 Any Policy" */
90, /* "X509v3 Authority Key Identifier" */
87, /* "X509v3 Basic Constraints" */
103, /* "X509v3 CRL Distribution Points" */
88, /* "X509v3 CRL Number" */
141, /* "X509v3 CRL Reason Code" */
771, /* "X509v3 Certificate Issuer" */
89, /* "X509v3 Certificate Policies" */
140, /* "X509v3 Delta CRL Indicator" */
126, /* "X509v3 Extended Key Usage" */
857, /* "X509v3 Freshest CRL" */
748, /* "X509v3 Inhibit Any Policy" */
86, /* "X509v3 Issuer Alternative Name" */
770, /* "X509v3 Issuing Distribution Point" */
83, /* "X509v3 Key Usage" */
666, /* "X509v3 Name Constraints" */
403, /* "X509v3 No Revocation Available" */
401, /* "X509v3 Policy Constraints" */
747, /* "X509v3 Policy Mappings" */
84, /* "X509v3 Private Key Usage Period" */
85, /* "X509v3 Subject Alternative Name" */
769, /* "X509v3 Subject Directory Attributes" */
82, /* "X509v3 Subject Key Identifier" */
920, /* "X9.42 DH" */
184, /* "X9.57" */
185, /* "X9.57 CM ?" */
478, /* "aRecord" */
289, /* "aaControls" */
287, /* "ac-auditEntity" */
397, /* "ac-proxying" */
288, /* "ac-targeting" */
446, /* "account" */
364, /* "ad dvcs" */
606, /* "additional verification" */
419, /* "aes-128-cbc" */
916, /* "aes-128-cbc-hmac-sha1" */
948, /* "aes-128-cbc-hmac-sha256" */
896, /* "aes-128-ccm" */
421, /* "aes-128-cfb" */
650, /* "aes-128-cfb1" */
653, /* "aes-128-cfb8" */
904, /* "aes-128-ctr" */
418, /* "aes-128-ecb" */
895, /* "aes-128-gcm" */
958, /* "aes-128-ocb" */
420, /* "aes-128-ofb" */
913, /* "aes-128-xts" */
423, /* "aes-192-cbc" */
917, /* "aes-192-cbc-hmac-sha1" */
949, /* "aes-192-cbc-hmac-sha256" */
899, /* "aes-192-ccm" */
425, /* "aes-192-cfb" */
651, /* "aes-192-cfb1" */
654, /* "aes-192-cfb8" */
905, /* "aes-192-ctr" */
422, /* "aes-192-ecb" */
898, /* "aes-192-gcm" */
959, /* "aes-192-ocb" */
424, /* "aes-192-ofb" */
427, /* "aes-256-cbc" */
918, /* "aes-256-cbc-hmac-sha1" */
950, /* "aes-256-cbc-hmac-sha256" */
902, /* "aes-256-ccm" */
429, /* "aes-256-cfb" */
652, /* "aes-256-cfb1" */
655, /* "aes-256-cfb8" */
906, /* "aes-256-ctr" */
426, /* "aes-256-ecb" */
901, /* "aes-256-gcm" */
960, /* "aes-256-ocb" */
428, /* "aes-256-ofb" */
914, /* "aes-256-xts" */
376, /* "algorithm" */
1066, /* "aria-128-cbc" */
1120, /* "aria-128-ccm" */
1067, /* "aria-128-cfb" */
1080, /* "aria-128-cfb1" */
1083, /* "aria-128-cfb8" */
1069, /* "aria-128-ctr" */
1065, /* "aria-128-ecb" */
1123, /* "aria-128-gcm" */
1068, /* "aria-128-ofb" */
1071, /* "aria-192-cbc" */
1121, /* "aria-192-ccm" */
1072, /* "aria-192-cfb" */
1081, /* "aria-192-cfb1" */
1084, /* "aria-192-cfb8" */
1074, /* "aria-192-ctr" */
1070, /* "aria-192-ecb" */
1124, /* "aria-192-gcm" */
1073, /* "aria-192-ofb" */
1076, /* "aria-256-cbc" */
1122, /* "aria-256-ccm" */
1077, /* "aria-256-cfb" */
1082, /* "aria-256-cfb1" */
1085, /* "aria-256-cfb8" */
1079, /* "aria-256-ctr" */
1075, /* "aria-256-ecb" */
1125, /* "aria-256-gcm" */
1078, /* "aria-256-ofb" */
484, /* "associatedDomain" */
485, /* "associatedName" */
501, /* "audio" */
1064, /* "auth-any" */
1049, /* "auth-dss" */
1047, /* "auth-ecdsa" */
1050, /* "auth-gost01" */
1051, /* "auth-gost12" */
1053, /* "auth-null" */
1048, /* "auth-psk" */
1046, /* "auth-rsa" */
1052, /* "auth-srp" */
882, /* "authorityRevocationList" */
91, /* "bf-cbc" */
93, /* "bf-cfb" */
92, /* "bf-ecb" */
94, /* "bf-ofb" */
1056, /* "blake2b512" */
1057, /* "blake2s256" */
921, /* "brainpoolP160r1" */
922, /* "brainpoolP160t1" */
923, /* "brainpoolP192r1" */
924, /* "brainpoolP192t1" */
925, /* "brainpoolP224r1" */
926, /* "brainpoolP224t1" */
927, /* "brainpoolP256r1" */
928, /* "brainpoolP256t1" */
929, /* "brainpoolP320r1" */
930, /* "brainpoolP320t1" */
931, /* "brainpoolP384r1" */
932, /* "brainpoolP384t1" */
933, /* "brainpoolP512r1" */
934, /* "brainpoolP512t1" */
494, /* "buildingName" */
860, /* "businessCategory" */
691, /* "c2onb191v4" */
692, /* "c2onb191v5" */
697, /* "c2onb239v4" */
698, /* "c2onb239v5" */
684, /* "c2pnb163v1" */
685, /* "c2pnb163v2" */
686, /* "c2pnb163v3" */
687, /* "c2pnb176v1" */
693, /* "c2pnb208w1" */
699, /* "c2pnb272w1" */
700, /* "c2pnb304w1" */
702, /* "c2pnb368w1" */
688, /* "c2tnb191v1" */
689, /* "c2tnb191v2" */
690, /* "c2tnb191v3" */
694, /* "c2tnb239v1" */
695, /* "c2tnb239v2" */
696, /* "c2tnb239v3" */
701, /* "c2tnb359v1" */
703, /* "c2tnb431r1" */
881, /* "cACertificate" */
483, /* "cNAMERecord" */
751, /* "camellia-128-cbc" */
962, /* "camellia-128-ccm" */
757, /* "camellia-128-cfb" */
760, /* "camellia-128-cfb1" */
763, /* "camellia-128-cfb8" */
964, /* "camellia-128-cmac" */
963, /* "camellia-128-ctr" */
754, /* "camellia-128-ecb" */
961, /* "camellia-128-gcm" */
766, /* "camellia-128-ofb" */
752, /* "camellia-192-cbc" */
966, /* "camellia-192-ccm" */
758, /* "camellia-192-cfb" */
761, /* "camellia-192-cfb1" */
764, /* "camellia-192-cfb8" */
968, /* "camellia-192-cmac" */
967, /* "camellia-192-ctr" */
755, /* "camellia-192-ecb" */
965, /* "camellia-192-gcm" */
767, /* "camellia-192-ofb" */
753, /* "camellia-256-cbc" */
970, /* "camellia-256-ccm" */
759, /* "camellia-256-cfb" */
762, /* "camellia-256-cfb1" */
765, /* "camellia-256-cfb8" */
972, /* "camellia-256-cmac" */
971, /* "camellia-256-ctr" */
756, /* "camellia-256-ecb" */
969, /* "camellia-256-gcm" */
768, /* "camellia-256-ofb" */
443, /* "caseIgnoreIA5StringSyntax" */
108, /* "cast5-cbc" */
110, /* "cast5-cfb" */
109, /* "cast5-ecb" */
111, /* "cast5-ofb" */
152, /* "certBag" */
677, /* "certicom-arc" */
517, /* "certificate extensions" */
883, /* "certificateRevocationList" */
1019, /* "chacha20" */
1018, /* "chacha20-poly1305" */
54, /* "challengePassword" */
407, /* "characteristic-two-field" */
395, /* "clearance" */
633, /* "cleartext track 2" */
894, /* "cmac" */
13, /* "commonName" */
513, /* "content types" */
50, /* "contentType" */
53, /* "countersignature" */
1090, /* "countryCode3c" */
1091, /* "countryCode3n" */
14, /* "countryName" */
153, /* "crlBag" */
884, /* "crossCertificatePair" */
806, /* "cryptocom" */
805, /* "cryptopro" */
500, /* "dITRedirect" */
451, /* "dNSDomain" */
495, /* "dSAQuality" */
434, /* "data" */
390, /* "dcObject" */
891, /* "deltaRevocationList" */
31, /* "des-cbc" */
643, /* "des-cdmf" */
30, /* "des-cfb" */
656, /* "des-cfb1" */
657, /* "des-cfb8" */
29, /* "des-ecb" */
32, /* "des-ede" */
43, /* "des-ede-cbc" */
60, /* "des-ede-cfb" */
62, /* "des-ede-ofb" */
33, /* "des-ede3" */
44, /* "des-ede3-cbc" */
61, /* "des-ede3-cfb" */
658, /* "des-ede3-cfb1" */
659, /* "des-ede3-cfb8" */
63, /* "des-ede3-ofb" */
45, /* "des-ofb" */
107, /* "description" */
871, /* "destinationIndicator" */
80, /* "desx-cbc" */
947, /* "dh-cofactor-kdf" */
946, /* "dh-std-kdf" */
28, /* "dhKeyAgreement" */
941, /* "dhSinglePass-cofactorDH-sha1kdf-scheme" */
942, /* "dhSinglePass-cofactorDH-sha224kdf-scheme" */
943, /* "dhSinglePass-cofactorDH-sha256kdf-scheme" */
944, /* "dhSinglePass-cofactorDH-sha384kdf-scheme" */
945, /* "dhSinglePass-cofactorDH-sha512kdf-scheme" */
936, /* "dhSinglePass-stdDH-sha1kdf-scheme" */
937, /* "dhSinglePass-stdDH-sha224kdf-scheme" */
938, /* "dhSinglePass-stdDH-sha256kdf-scheme" */
939, /* "dhSinglePass-stdDH-sha384kdf-scheme" */
940, /* "dhSinglePass-stdDH-sha512kdf-scheme" */
11, /* "directory services (X.500)" */
378, /* "directory services - algorithms" */
887, /* "distinguishedName" */
892, /* "dmdName" */
174, /* "dnQualifier" */
1092, /* "dnsName" */
447, /* "document" */
471, /* "documentAuthor" */
468, /* "documentIdentifier" */
472, /* "documentLocation" */
502, /* "documentPublisher" */
449, /* "documentSeries" */
469, /* "documentTitle" */
470, /* "documentVersion" */
380, /* "dod" */
391, /* "domainComponent" */
452, /* "domainRelatedObject" */
116, /* "dsaEncryption" */
67, /* "dsaEncryption-old" */
66, /* "dsaWithSHA" */
113, /* "dsaWithSHA1" */
70, /* "dsaWithSHA1-old" */
802, /* "dsa_with_SHA224" */
803, /* "dsa_with_SHA256" */
1108, /* "dsa_with_SHA3-224" */
1109, /* "dsa_with_SHA3-256" */
1110, /* "dsa_with_SHA3-384" */
1111, /* "dsa_with_SHA3-512" */
1106, /* "dsa_with_SHA384" */
1107, /* "dsa_with_SHA512" */
297, /* "dvcs" */
791, /* "ecdsa-with-Recommended" */
416, /* "ecdsa-with-SHA1" */
793, /* "ecdsa-with-SHA224" */
794, /* "ecdsa-with-SHA256" */
795, /* "ecdsa-with-SHA384" */
796, /* "ecdsa-with-SHA512" */
792, /* "ecdsa-with-Specified" */
1112, /* "ecdsa_with_SHA3-224" */
1113, /* "ecdsa_with_SHA3-256" */
1114, /* "ecdsa_with_SHA3-384" */
1115, /* "ecdsa_with_SHA3-512" */
48, /* "emailAddress" */
632, /* "encrypted track 2" */
885, /* "enhancedSearchGuide" */
56, /* "extendedCertificateAttributes" */
867, /* "facsimileTelephoneNumber" */
462, /* "favouriteDrink" */
1126, /* "ffdhe2048" */
1127, /* "ffdhe3072" */
1128, /* "ffdhe4096" */
1129, /* "ffdhe6144" */
1130, /* "ffdhe8192" */
453, /* "friendlyCountry" */
490, /* "friendlyCountryName" */
156, /* "friendlyName" */
631, /* "generate cryptogram" */
509, /* "generationQualifier" */
601, /* "generic cryptogram" */
99, /* "givenName" */
976, /* "gost-mac-12" */
1009, /* "gost89-cbc" */
814, /* "gost89-cnt" */
975, /* "gost89-cnt-12" */
1011, /* "gost89-ctr" */
1010, /* "gost89-ecb" */
1015, /* "grasshopper-cbc" */
1016, /* "grasshopper-cfb" */
1013, /* "grasshopper-ctr" */
1012, /* "grasshopper-ecb" */
1017, /* "grasshopper-mac" */
1014, /* "grasshopper-ofb" */
1036, /* "hkdf" */
855, /* "hmac" */
780, /* "hmac-md5" */
781, /* "hmac-sha1" */
1102, /* "hmac-sha3-224" */
1103, /* "hmac-sha3-256" */
1104, /* "hmac-sha3-384" */
1105, /* "hmac-sha3-512" */
797, /* "hmacWithMD5" */
163, /* "hmacWithSHA1" */
798, /* "hmacWithSHA224" */
799, /* "hmacWithSHA256" */
800, /* "hmacWithSHA384" */
801, /* "hmacWithSHA512" */
1193, /* "hmacWithSHA512-224" */
1194, /* "hmacWithSHA512-256" */
486, /* "homePostalAddress" */
473, /* "homeTelephoneNumber" */
466, /* "host" */
889, /* "houseIdentifier" */
442, /* "iA5StringSyntax" */
381, /* "iana" */
824, /* "id-Gost28147-89-CryptoPro-A-ParamSet" */
825, /* "id-Gost28147-89-CryptoPro-B-ParamSet" */
826, /* "id-Gost28147-89-CryptoPro-C-ParamSet" */
827, /* "id-Gost28147-89-CryptoPro-D-ParamSet" */
819, /* "id-Gost28147-89-CryptoPro-KeyMeshing" */
829, /* "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet" */
828, /* "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet" */
830, /* "id-Gost28147-89-CryptoPro-RIC-1-ParamSet" */
820, /* "id-Gost28147-89-None-KeyMeshing" */
823, /* "id-Gost28147-89-TestParamSet" */
840, /* "id-GostR3410-2001-CryptoPro-A-ParamSet" */
841, /* "id-GostR3410-2001-CryptoPro-B-ParamSet" */
842, /* "id-GostR3410-2001-CryptoPro-C-ParamSet" */
843, /* "id-GostR3410-2001-CryptoPro-XchA-ParamSet" */
844, /* "id-GostR3410-2001-CryptoPro-XchB-ParamSet" */
839, /* "id-GostR3410-2001-TestParamSet" */
832, /* "id-GostR3410-94-CryptoPro-A-ParamSet" */
833, /* "id-GostR3410-94-CryptoPro-B-ParamSet" */
834, /* "id-GostR3410-94-CryptoPro-C-ParamSet" */
835, /* "id-GostR3410-94-CryptoPro-D-ParamSet" */
836, /* "id-GostR3410-94-CryptoPro-XchA-ParamSet" */
837, /* "id-GostR3410-94-CryptoPro-XchB-ParamSet" */
838, /* "id-GostR3410-94-CryptoPro-XchC-ParamSet" */
831, /* "id-GostR3410-94-TestParamSet" */
845, /* "id-GostR3410-94-a" */
846, /* "id-GostR3410-94-aBis" */
847, /* "id-GostR3410-94-b" */
848, /* "id-GostR3410-94-bBis" */
822, /* "id-GostR3411-94-CryptoProParamSet" */
821, /* "id-GostR3411-94-TestParamSet" */
266, /* "id-aca" */
355, /* "id-aca-accessIdentity" */
354, /* "id-aca-authenticationInfo" */
356, /* "id-aca-chargingIdentity" */
399, /* "id-aca-encAttrs" */
357, /* "id-aca-group" */
358, /* "id-aca-role" */
176, /* "id-ad" */
788, /* "id-aes128-wrap" */
897, /* "id-aes128-wrap-pad" */
789, /* "id-aes192-wrap" */
900, /* "id-aes192-wrap-pad" */
790, /* "id-aes256-wrap" */
903, /* "id-aes256-wrap-pad" */
262, /* "id-alg" */
893, /* "id-alg-PWRI-KEK" */
323, /* "id-alg-des40" */
326, /* "id-alg-dh-pop" */
325, /* "id-alg-dh-sig-hmac-sha1" */
324, /* "id-alg-noSignature" */
907, /* "id-camellia128-wrap" */
908, /* "id-camellia192-wrap" */
909, /* "id-camellia256-wrap" */
268, /* "id-cct" */
361, /* "id-cct-PKIData" */
362, /* "id-cct-PKIResponse" */
360, /* "id-cct-crs" */
81, /* "id-ce" */
680, /* "id-characteristic-two-basis" */
263, /* "id-cmc" */
334, /* "id-cmc-addExtensions" */
346, /* "id-cmc-confirmCertAcceptance" */
330, /* "id-cmc-dataReturn" */
336, /* "id-cmc-decryptedPOP" */
335, /* "id-cmc-encryptedPOP" */
339, /* "id-cmc-getCRL" */
338, /* "id-cmc-getCert" */
328, /* "id-cmc-identification" */
329, /* "id-cmc-identityProof" */
337, /* "id-cmc-lraPOPWitness" */
344, /* "id-cmc-popLinkRandom" */
345, /* "id-cmc-popLinkWitness" */
343, /* "id-cmc-queryPending" */
333, /* "id-cmc-recipientNonce" */
341, /* "id-cmc-regInfo" */
342, /* "id-cmc-responseInfo" */
340, /* "id-cmc-revokeRequest" */
332, /* "id-cmc-senderNonce" */
327, /* "id-cmc-statusInfo" */
331, /* "id-cmc-transactionId" */
787, /* "id-ct-asciiTextWithCRLF" */
1060, /* "id-ct-xml" */
408, /* "id-ecPublicKey" */
508, /* "id-hex-multipart-message" */
507, /* "id-hex-partial-message" */
260, /* "id-it" */
302, /* "id-it-caKeyUpdateInfo" */
298, /* "id-it-caProtEncCert" */
311, /* "id-it-confirmWaitTime" */
303, /* "id-it-currentCRL" */
300, /* "id-it-encKeyPairTypes" */
310, /* "id-it-implicitConfirm" */
308, /* "id-it-keyPairParamRep" */
307, /* "id-it-keyPairParamReq" */
312, /* "id-it-origPKIMessage" */
301, /* "id-it-preferredSymmAlg" */
309, /* "id-it-revPassphrase" */
299, /* "id-it-signKeyPairTypes" */
305, /* "id-it-subscriptionRequest" */
306, /* "id-it-subscriptionResponse" */
784, /* "id-it-suppLangTags" */
304, /* "id-it-unsupportedOIDs" */
128, /* "id-kp" */
280, /* "id-mod-attribute-cert" */
274, /* "id-mod-cmc" */
277, /* "id-mod-cmp" */
284, /* "id-mod-cmp2000" */
273, /* "id-mod-crmf" */
283, /* "id-mod-dvcs" */
275, /* "id-mod-kea-profile-88" */
276, /* "id-mod-kea-profile-93" */
282, /* "id-mod-ocsp" */
278, /* "id-mod-qualified-cert-88" */
279, /* "id-mod-qualified-cert-93" */
281, /* "id-mod-timestamp-protocol" */
264, /* "id-on" */
347, /* "id-on-personalData" */
265, /* "id-pda" */
352, /* "id-pda-countryOfCitizenship" */
353, /* "id-pda-countryOfResidence" */
348, /* "id-pda-dateOfBirth" */
351, /* "id-pda-gender" */
349, /* "id-pda-placeOfBirth" */
175, /* "id-pe" */
1031, /* "id-pkinit" */
261, /* "id-pkip" */
258, /* "id-pkix-mod" */
269, /* "id-pkix1-explicit-88" */
271, /* "id-pkix1-explicit-93" */
270, /* "id-pkix1-implicit-88" */
272, /* "id-pkix1-implicit-93" */
662, /* "id-ppl" */
267, /* "id-qcs" */
359, /* "id-qcs-pkixQCSyntax-v1" */
259, /* "id-qt" */
313, /* "id-regCtrl" */
316, /* "id-regCtrl-authenticator" */
319, /* "id-regCtrl-oldCertID" */
318, /* "id-regCtrl-pkiArchiveOptions" */
317, /* "id-regCtrl-pkiPublicationInfo" */
320, /* "id-regCtrl-protocolEncrKey" */
315, /* "id-regCtrl-regToken" */
314, /* "id-regInfo" */
322, /* "id-regInfo-certReq" */
321, /* "id-regInfo-utf8Pairs" */
191, /* "id-smime-aa" */
215, /* "id-smime-aa-contentHint" */
218, /* "id-smime-aa-contentIdentifier" */
221, /* "id-smime-aa-contentReference" */
240, /* "id-smime-aa-dvcs-dvc" */
217, /* "id-smime-aa-encapContentType" */
222, /* "id-smime-aa-encrypKeyPref" */
220, /* "id-smime-aa-equivalentLabels" */
232, /* "id-smime-aa-ets-CertificateRefs" */
233, /* "id-smime-aa-ets-RevocationRefs" */
238, /* "id-smime-aa-ets-archiveTimeStamp" */
237, /* "id-smime-aa-ets-certCRLTimestamp" */
234, /* "id-smime-aa-ets-certValues" */
227, /* "id-smime-aa-ets-commitmentType" */
231, /* "id-smime-aa-ets-contentTimestamp" */
236, /* "id-smime-aa-ets-escTimeStamp" */
230, /* "id-smime-aa-ets-otherSigCert" */
235, /* "id-smime-aa-ets-revocationValues" */
226, /* "id-smime-aa-ets-sigPolicyId" */
229, /* "id-smime-aa-ets-signerAttr" */
228, /* "id-smime-aa-ets-signerLocation" */
219, /* "id-smime-aa-macValue" */
214, /* "id-smime-aa-mlExpandHistory" */
216, /* "id-smime-aa-msgSigDigest" */
212, /* "id-smime-aa-receiptRequest" */
213, /* "id-smime-aa-securityLabel" */
239, /* "id-smime-aa-signatureType" */
223, /* "id-smime-aa-signingCertificate" */
1086, /* "id-smime-aa-signingCertificateV2" */
224, /* "id-smime-aa-smimeEncryptCerts" */
225, /* "id-smime-aa-timeStampToken" */
192, /* "id-smime-alg" */
243, /* "id-smime-alg-3DESwrap" */
246, /* "id-smime-alg-CMS3DESwrap" */
247, /* "id-smime-alg-CMSRC2wrap" */
245, /* "id-smime-alg-ESDH" */
241, /* "id-smime-alg-ESDHwith3DES" */
242, /* "id-smime-alg-ESDHwithRC2" */
244, /* "id-smime-alg-RC2wrap" */
193, /* "id-smime-cd" */
248, /* "id-smime-cd-ldap" */
190, /* "id-smime-ct" */
210, /* "id-smime-ct-DVCSRequestData" */
211, /* "id-smime-ct-DVCSResponseData" */
208, /* "id-smime-ct-TDTInfo" */
207, /* "id-smime-ct-TSTInfo" */
205, /* "id-smime-ct-authData" */
1059, /* "id-smime-ct-authEnvelopedData" */
786, /* "id-smime-ct-compressedData" */
1058, /* "id-smime-ct-contentCollection" */
209, /* "id-smime-ct-contentInfo" */
206, /* "id-smime-ct-publishCert" */
204, /* "id-smime-ct-receipt" */
195, /* "id-smime-cti" */
255, /* "id-smime-cti-ets-proofOfApproval" */
256, /* "id-smime-cti-ets-proofOfCreation" */
253, /* "id-smime-cti-ets-proofOfDelivery" */
251, /* "id-smime-cti-ets-proofOfOrigin" */
252, /* "id-smime-cti-ets-proofOfReceipt" */
254, /* "id-smime-cti-ets-proofOfSender" */
189, /* "id-smime-mod" */
196, /* "id-smime-mod-cms" */
197, /* "id-smime-mod-ess" */
202, /* "id-smime-mod-ets-eSigPolicy-88" */
203, /* "id-smime-mod-ets-eSigPolicy-97" */
200, /* "id-smime-mod-ets-eSignature-88" */
201, /* "id-smime-mod-ets-eSignature-97" */
199, /* "id-smime-mod-msg-v3" */
198, /* "id-smime-mod-oid" */
194, /* "id-smime-spq" */
250, /* "id-smime-spq-ets-sqt-unotice" */
249, /* "id-smime-spq-ets-sqt-uri" */
974, /* "id-tc26" */
991, /* "id-tc26-agreement" */
992, /* "id-tc26-agreement-gost-3410-2012-256" */
993, /* "id-tc26-agreement-gost-3410-2012-512" */
977, /* "id-tc26-algorithms" */
990, /* "id-tc26-cipher" */
1001, /* "id-tc26-cipher-constants" */
1176, /* "id-tc26-cipher-gostr3412-2015-kuznyechik" */
1177, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm" */
1178, /* "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac" */
1173, /* "id-tc26-cipher-gostr3412-2015-magma" */
1174, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm" */
1175, /* "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac" */
994, /* "id-tc26-constants" */
981, /* "id-tc26-digest" */
1000, /* "id-tc26-digest-constants" */
1002, /* "id-tc26-gost-28147-constants" */
1147, /* "id-tc26-gost-3410-2012-256-constants" */
996, /* "id-tc26-gost-3410-2012-512-constants" */
987, /* "id-tc26-mac" */
978, /* "id-tc26-sign" */
995, /* "id-tc26-sign-constants" */
984, /* "id-tc26-signwithdigest" */
1179, /* "id-tc26-wrap" */
1182, /* "id-tc26-wrap-gostr3412-2015-kuznyechik" */
1183, /* "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15" */
1180, /* "id-tc26-wrap-gostr3412-2015-magma" */
1181, /* "id-tc26-wrap-gostr3412-2015-magma-kexp15" */
34, /* "idea-cbc" */
35, /* "idea-cfb" */
36, /* "idea-ecb" */
46, /* "idea-ofb" */
676, /* "identified-organization" */
1170, /* "ieee" */
461, /* "info" */
101, /* "initials" */
869, /* "internationaliSDNNumber" */
1022, /* "ipsec Internet Key Exchange" */
749, /* "ipsec3" */
750, /* "ipsec4" */
181, /* "iso" */
623, /* "issuer capabilities" */
645, /* "itu-t" */
492, /* "janetMailbox" */
646, /* "joint-iso-itu-t" */
957, /* "jurisdictionCountryName" */
955, /* "jurisdictionLocalityName" */
956, /* "jurisdictionStateOrProvinceName" */
150, /* "keyBag" */
773, /* "kisa" */
1063, /* "kx-any" */
1039, /* "kx-dhe" */
1041, /* "kx-dhe-psk" */
1038, /* "kx-ecdhe" */
1040, /* "kx-ecdhe-psk" */
1045, /* "kx-gost" */
1043, /* "kx-psk" */
1037, /* "kx-rsa" */
1042, /* "kx-rsa-psk" */
1044, /* "kx-srp" */
477, /* "lastModifiedBy" */
476, /* "lastModifiedTime" */
157, /* "localKeyID" */
15, /* "localityName" */
480, /* "mXRecord" */
1190, /* "magma-cbc" */
1191, /* "magma-cfb" */
1188, /* "magma-ctr" */
1187, /* "magma-ecb" */
1192, /* "magma-mac" */
1189, /* "magma-ofb" */
493, /* "mailPreferenceOption" */
467, /* "manager" */
3, /* "md2" */
7, /* "md2WithRSAEncryption" */
257, /* "md4" */
396, /* "md4WithRSAEncryption" */
4, /* "md5" */
114, /* "md5-sha1" */
104, /* "md5WithRSA" */
8, /* "md5WithRSAEncryption" */
95, /* "mdc2" */
96, /* "mdc2WithRSA" */
875, /* "member" */
602, /* "merchant initiated auth" */
514, /* "message extensions" */
51, /* "messageDigest" */
911, /* "mgf1" */
506, /* "mime-mhs-bodies" */
505, /* "mime-mhs-headings" */
488, /* "mobileTelephoneNumber" */
481, /* "nSRecord" */
173, /* "name" */
681, /* "onBasis" */
379, /* "org" */
1089, /* "organizationIdentifier" */
17, /* "organizationName" */
491, /* "organizationalStatus" */
18, /* "organizationalUnitName" */
1141, /* "oscca" */
475, /* "otherMailbox" */
876, /* "owner" */
935, /* "pSpecified" */
489, /* "pagerTelephoneNumber" */
782, /* "password based MAC" */
374, /* "path" */
621, /* "payment gateway capabilities" */
9, /* "pbeWithMD2AndDES-CBC" */
168, /* "pbeWithMD2AndRC2-CBC" */
112, /* "pbeWithMD5AndCast5CBC" */
10, /* "pbeWithMD5AndDES-CBC" */
169, /* "pbeWithMD5AndRC2-CBC" */
148, /* "pbeWithSHA1And128BitRC2-CBC" */
144, /* "pbeWithSHA1And128BitRC4" */
147, /* "pbeWithSHA1And2-KeyTripleDES-CBC" */
146, /* "pbeWithSHA1And3-KeyTripleDES-CBC" */
149, /* "pbeWithSHA1And40BitRC2-CBC" */
145, /* "pbeWithSHA1And40BitRC4" */
170, /* "pbeWithSHA1AndDES-CBC" */
68, /* "pbeWithSHA1AndRC2-CBC" */
499, /* "personalSignature" */
487, /* "personalTitle" */
464, /* "photo" */
863, /* "physicalDeliveryOfficeName" */
437, /* "pilot" */
439, /* "pilotAttributeSyntax" */
438, /* "pilotAttributeType" */
479, /* "pilotAttributeType27" */
456, /* "pilotDSA" */
441, /* "pilotGroups" */
444, /* "pilotObject" */
440, /* "pilotObjectClass" */
455, /* "pilotOrganization" */
445, /* "pilotPerson" */
186, /* "pkcs1" */
27, /* "pkcs3" */
187, /* "pkcs5" */
20, /* "pkcs7" */
21, /* "pkcs7-data" */
25, /* "pkcs7-digestData" */
26, /* "pkcs7-encryptedData" */
23, /* "pkcs7-envelopedData" */
24, /* "pkcs7-signedAndEnvelopedData" */
22, /* "pkcs7-signedData" */
151, /* "pkcs8ShroudedKeyBag" */
47, /* "pkcs9" */
1061, /* "poly1305" */
862, /* "postOfficeBox" */
861, /* "postalAddress" */
661, /* "postalCode" */
683, /* "ppBasis" */
872, /* "preferredDeliveryMethod" */
873, /* "presentationAddress" */
406, /* "prime-field" */
409, /* "prime192v1" */
410, /* "prime192v2" */
411, /* "prime192v3" */
412, /* "prime239v1" */
413, /* "prime239v2" */
414, /* "prime239v3" */
415, /* "prime256v1" */
886, /* "protocolInformation" */
510, /* "pseudonym" */
435, /* "pss" */
286, /* "qcStatements" */
457, /* "qualityLabelledData" */
450, /* "rFC822localPart" */
98, /* "rc2-40-cbc" */
166, /* "rc2-64-cbc" */
37, /* "rc2-cbc" */
39, /* "rc2-cfb" */
38, /* "rc2-ecb" */
40, /* "rc2-ofb" */
5, /* "rc4" */
97, /* "rc4-40" */
915, /* "rc4-hmac-md5" */
120, /* "rc5-cbc" */
122, /* "rc5-cfb" */
121, /* "rc5-ecb" */
123, /* "rc5-ofb" */
870, /* "registeredAddress" */
460, /* "rfc822Mailbox" */
117, /* "ripemd160" */
119, /* "ripemd160WithRSA" */
400, /* "role" */
877, /* "roleOccupant" */
448, /* "room" */
463, /* "roomNumber" */
19, /* "rsa" */
6, /* "rsaEncryption" */
644, /* "rsaOAEPEncryptionSET" */
377, /* "rsaSignature" */
919, /* "rsaesOaep" */
912, /* "rsassaPss" */
482, /* "sOARecord" */
155, /* "safeContentsBag" */
291, /* "sbgp-autonomousSysNum" */
290, /* "sbgp-ipAddrBlock" */
292, /* "sbgp-routerIdentifier" */
973, /* "scrypt" */
159, /* "sdsiCertificate" */
859, /* "searchGuide" */
704, /* "secp112r1" */
705, /* "secp112r2" */
706, /* "secp128r1" */
707, /* "secp128r2" */
708, /* "secp160k1" */
709, /* "secp160r1" */
710, /* "secp160r2" */
711, /* "secp192k1" */
712, /* "secp224k1" */
713, /* "secp224r1" */
714, /* "secp256k1" */
715, /* "secp384r1" */
716, /* "secp521r1" */
154, /* "secretBag" */
474, /* "secretary" */
717, /* "sect113r1" */
718, /* "sect113r2" */
719, /* "sect131r1" */
720, /* "sect131r2" */
721, /* "sect163k1" */
722, /* "sect163r1" */
723, /* "sect163r2" */
724, /* "sect193r1" */
725, /* "sect193r2" */
726, /* "sect233k1" */
727, /* "sect233r1" */
728, /* "sect239k1" */
729, /* "sect283k1" */
730, /* "sect283r1" */
731, /* "sect409k1" */
732, /* "sect409r1" */
733, /* "sect571k1" */
734, /* "sect571r1" */
635, /* "secure device signature" */
878, /* "seeAlso" */
777, /* "seed-cbc" */
779, /* "seed-cfb" */
776, /* "seed-ecb" */
778, /* "seed-ofb" */
105, /* "serialNumber" */
625, /* "set-addPolicy" */
515, /* "set-attr" */
518, /* "set-brand" */
638, /* "set-brand-AmericanExpress" */
637, /* "set-brand-Diners" */
636, /* "set-brand-IATA-ATA" */
639, /* "set-brand-JCB" */
641, /* "set-brand-MasterCard" */
642, /* "set-brand-Novus" */
640, /* "set-brand-Visa" */
516, /* "set-policy" */
607, /* "set-policy-root" */
624, /* "set-rootKeyThumb" */
620, /* "setAttr-Cert" */
628, /* "setAttr-IssCap-CVM" */
630, /* "setAttr-IssCap-Sig" */
629, /* "setAttr-IssCap-T2" */
627, /* "setAttr-Token-B0Prime" */
626, /* "setAttr-Token-EMV" */
622, /* "setAttr-TokenType" */
619, /* "setCext-IssuerCapabilities" */
615, /* "setCext-PGWYcapabilities" */
616, /* "setCext-TokenIdentifier" */
618, /* "setCext-TokenType" */
617, /* "setCext-Track2Data" */
611, /* "setCext-cCertRequired" */
609, /* "setCext-certType" */
608, /* "setCext-hashedRoot" */
610, /* "setCext-merchData" */
613, /* "setCext-setExt" */
614, /* "setCext-setQualf" */
612, /* "setCext-tunneling" */
540, /* "setct-AcqCardCodeMsg" */
576, /* "setct-AcqCardCodeMsgTBE" */
570, /* "setct-AuthReqTBE" */
534, /* "setct-AuthReqTBS" */
527, /* "setct-AuthResBaggage" */
571, /* "setct-AuthResTBE" */
572, /* "setct-AuthResTBEX" */
535, /* "setct-AuthResTBS" */
536, /* "setct-AuthResTBSX" */
528, /* "setct-AuthRevReqBaggage" */
577, /* "setct-AuthRevReqTBE" */
541, /* "setct-AuthRevReqTBS" */
529, /* "setct-AuthRevResBaggage" */
542, /* "setct-AuthRevResData" */
578, /* "setct-AuthRevResTBE" */
579, /* "setct-AuthRevResTBEB" */
543, /* "setct-AuthRevResTBS" */
573, /* "setct-AuthTokenTBE" */
537, /* "setct-AuthTokenTBS" */
600, /* "setct-BCIDistributionTBS" */
558, /* "setct-BatchAdminReqData" */
592, /* "setct-BatchAdminReqTBE" */
559, /* "setct-BatchAdminResData" */
593, /* "setct-BatchAdminResTBE" */
599, /* "setct-CRLNotificationResTBS" */
598, /* "setct-CRLNotificationTBS" */
580, /* "setct-CapReqTBE" */
581, /* "setct-CapReqTBEX" */
544, /* "setct-CapReqTBS" */
545, /* "setct-CapReqTBSX" */
546, /* "setct-CapResData" */
582, /* "setct-CapResTBE" */
583, /* "setct-CapRevReqTBE" */
584, /* "setct-CapRevReqTBEX" */
547, /* "setct-CapRevReqTBS" */
548, /* "setct-CapRevReqTBSX" */
549, /* "setct-CapRevResData" */
585, /* "setct-CapRevResTBE" */
538, /* "setct-CapTokenData" */
530, /* "setct-CapTokenSeq" */
574, /* "setct-CapTokenTBE" */
575, /* "setct-CapTokenTBEX" */
539, /* "setct-CapTokenTBS" */
560, /* "setct-CardCInitResTBS" */
566, /* "setct-CertInqReqTBS" */
563, /* "setct-CertReqData" */
595, /* "setct-CertReqTBE" */
596, /* "setct-CertReqTBEX" */
564, /* "setct-CertReqTBS" */
565, /* "setct-CertResData" */
597, /* "setct-CertResTBE" */
586, /* "setct-CredReqTBE" */
587, /* "setct-CredReqTBEX" */
550, /* "setct-CredReqTBS" */
551, /* "setct-CredReqTBSX" */
552, /* "setct-CredResData" */
588, /* "setct-CredResTBE" */
589, /* "setct-CredRevReqTBE" */
590, /* "setct-CredRevReqTBEX" */
553, /* "setct-CredRevReqTBS" */
554, /* "setct-CredRevReqTBSX" */
555, /* "setct-CredRevResData" */
591, /* "setct-CredRevResTBE" */
567, /* "setct-ErrorTBS" */
526, /* "setct-HODInput" */
561, /* "setct-MeAqCInitResTBS" */
522, /* "setct-OIData" */
519, /* "setct-PANData" */
521, /* "setct-PANOnly" */
520, /* "setct-PANToken" */
556, /* "setct-PCertReqData" */
557, /* "setct-PCertResTBS" */
523, /* "setct-PI" */
532, /* "setct-PI-TBS" */
524, /* "setct-PIData" */
525, /* "setct-PIDataUnsigned" */
568, /* "setct-PIDualSignedTBE" */
569, /* "setct-PIUnsignedTBE" */
531, /* "setct-PInitResData" */
533, /* "setct-PResData" */
594, /* "setct-RegFormReqTBE" */
562, /* "setct-RegFormResTBS" */
604, /* "setext-pinAny" */
603, /* "setext-pinSecure" */
605, /* "setext-track2" */
41, /* "sha" */
64, /* "sha1" */
115, /* "sha1WithRSA" */
65, /* "sha1WithRSAEncryption" */
675, /* "sha224" */
671, /* "sha224WithRSAEncryption" */
672, /* "sha256" */
668, /* "sha256WithRSAEncryption" */
1096, /* "sha3-224" */
1097, /* "sha3-256" */
1098, /* "sha3-384" */
1099, /* "sha3-512" */
673, /* "sha384" */
669, /* "sha384WithRSAEncryption" */
674, /* "sha512" */
1094, /* "sha512-224" */
1145, /* "sha512-224WithRSAEncryption" */
1095, /* "sha512-256" */
1146, /* "sha512-256WithRSAEncryption" */
670, /* "sha512WithRSAEncryption" */
42, /* "shaWithRSAEncryption" */
1100, /* "shake128" */
1101, /* "shake256" */
52, /* "signingTime" */
454, /* "simpleSecurityObject" */
496, /* "singleLevelQuality" */
1062, /* "siphash" */
1142, /* "sm-scheme" */
1172, /* "sm2" */
1143, /* "sm3" */
1144, /* "sm3WithRSAEncryption" */
1134, /* "sm4-cbc" */
1137, /* "sm4-cfb" */
1136, /* "sm4-cfb1" */
1138, /* "sm4-cfb8" */
1139, /* "sm4-ctr" */
1133, /* "sm4-ecb" */
1135, /* "sm4-ofb" */
16, /* "stateOrProvinceName" */
660, /* "streetAddress" */
498, /* "subtreeMaximumQuality" */
497, /* "subtreeMinimumQuality" */
890, /* "supportedAlgorithms" */
874, /* "supportedApplicationContext" */
100, /* "surname" */
864, /* "telephoneNumber" */
866, /* "teletexTerminalIdentifier" */
865, /* "telexNumber" */
459, /* "textEncodedORAddress" */
293, /* "textNotice" */
106, /* "title" */
1021, /* "tls1-prf" */
682, /* "tpBasis" */
1151, /* "ua-pki" */
436, /* "ucl" */
0, /* "undefined" */
102, /* "uniqueIdentifier" */
888, /* "uniqueMember" */
55, /* "unstructuredAddress" */
49, /* "unstructuredName" */
880, /* "userCertificate" */
465, /* "userClass" */
458, /* "userId" */
879, /* "userPassword" */
373, /* "valid" */
678, /* "wap" */
679, /* "wap-wsg" */
735, /* "wap-wsg-idm-ecid-wtls1" */
743, /* "wap-wsg-idm-ecid-wtls10" */
744, /* "wap-wsg-idm-ecid-wtls11" */
745, /* "wap-wsg-idm-ecid-wtls12" */
736, /* "wap-wsg-idm-ecid-wtls3" */
737, /* "wap-wsg-idm-ecid-wtls4" */
738, /* "wap-wsg-idm-ecid-wtls5" */
739, /* "wap-wsg-idm-ecid-wtls6" */
740, /* "wap-wsg-idm-ecid-wtls7" */
741, /* "wap-wsg-idm-ecid-wtls8" */
742, /* "wap-wsg-idm-ecid-wtls9" */
804, /* "whirlpool" */
868, /* "x121Address" */
503, /* "x500UniqueIdentifier" */
158, /* "x509Certificate" */
160, /* "x509Crl" */
125, /* "zlib compression" */
};
#define NUM_OBJ 1071
static const unsigned int obj_objs[NUM_OBJ] = {
0, /* OBJ_undef 0 */
181, /* OBJ_iso 1 */
393, /* OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t */
404, /* OBJ_ccitt OBJ_itu_t */
645, /* OBJ_itu_t 0 */
646, /* OBJ_joint_iso_itu_t 2 */
434, /* OBJ_data 0 9 */
182, /* OBJ_member_body 1 2 */
379, /* OBJ_org 1 3 */
676, /* OBJ_identified_organization 1 3 */
11, /* OBJ_X500 2 5 */
647, /* OBJ_international_organizations 2 23 */
380, /* OBJ_dod 1 3 6 */
1170, /* OBJ_ieee 1 3 111 */
12, /* OBJ_X509 2 5 4 */
378, /* OBJ_X500algorithms 2 5 8 */
81, /* OBJ_id_ce 2 5 29 */
512, /* OBJ_id_set 2 23 42 */
678, /* OBJ_wap 2 23 43 */
435, /* OBJ_pss 0 9 2342 */
1140, /* OBJ_ISO_CN 1 2 156 */
1150, /* OBJ_ISO_UA 1 2 804 */
183, /* OBJ_ISO_US 1 2 840 */
381, /* OBJ_iana 1 3 6 1 */
1034, /* OBJ_X25519 1 3 101 110 */
1035, /* OBJ_X448 1 3 101 111 */
1087, /* OBJ_ED25519 1 3 101 112 */
1088, /* OBJ_ED448 1 3 101 113 */
677, /* OBJ_certicom_arc 1 3 132 */
394, /* OBJ_selected_attribute_types 2 5 1 5 */
13, /* OBJ_commonName 2 5 4 3 */
100, /* OBJ_surname 2 5 4 4 */
105, /* OBJ_serialNumber 2 5 4 5 */
14, /* OBJ_countryName 2 5 4 6 */
15, /* OBJ_localityName 2 5 4 7 */
16, /* OBJ_stateOrProvinceName 2 5 4 8 */
660, /* OBJ_streetAddress 2 5 4 9 */
17, /* OBJ_organizationName 2 5 4 10 */
18, /* OBJ_organizationalUnitName 2 5 4 11 */
106, /* OBJ_title 2 5 4 12 */
107, /* OBJ_description 2 5 4 13 */
859, /* OBJ_searchGuide 2 5 4 14 */
860, /* OBJ_businessCategory 2 5 4 15 */
861, /* OBJ_postalAddress 2 5 4 16 */
661, /* OBJ_postalCode 2 5 4 17 */
862, /* OBJ_postOfficeBox 2 5 4 18 */
863, /* OBJ_physicalDeliveryOfficeName 2 5 4 19 */
864, /* OBJ_telephoneNumber 2 5 4 20 */
865, /* OBJ_telexNumber 2 5 4 21 */
866, /* OBJ_teletexTerminalIdentifier 2 5 4 22 */
867, /* OBJ_facsimileTelephoneNumber 2 5 4 23 */
868, /* OBJ_x121Address 2 5 4 24 */
869, /* OBJ_internationaliSDNNumber 2 5 4 25 */
870, /* OBJ_registeredAddress 2 5 4 26 */
871, /* OBJ_destinationIndicator 2 5 4 27 */
872, /* OBJ_preferredDeliveryMethod 2 5 4 28 */
873, /* OBJ_presentationAddress 2 5 4 29 */
874, /* OBJ_supportedApplicationContext 2 5 4 30 */
875, /* OBJ_member 2 5 4 31 */
876, /* OBJ_owner 2 5 4 32 */
877, /* OBJ_roleOccupant 2 5 4 33 */
878, /* OBJ_seeAlso 2 5 4 34 */
879, /* OBJ_userPassword 2 5 4 35 */
880, /* OBJ_userCertificate 2 5 4 36 */
881, /* OBJ_cACertificate 2 5 4 37 */
882, /* OBJ_authorityRevocationList 2 5 4 38 */
883, /* OBJ_certificateRevocationList 2 5 4 39 */
884, /* OBJ_crossCertificatePair 2 5 4 40 */
173, /* OBJ_name 2 5 4 41 */
99, /* OBJ_givenName 2 5 4 42 */
101, /* OBJ_initials 2 5 4 43 */
509, /* OBJ_generationQualifier 2 5 4 44 */
503, /* OBJ_x500UniqueIdentifier 2 5 4 45 */
174, /* OBJ_dnQualifier 2 5 4 46 */
885, /* OBJ_enhancedSearchGuide 2 5 4 47 */
886, /* OBJ_protocolInformation 2 5 4 48 */
887, /* OBJ_distinguishedName 2 5 4 49 */
888, /* OBJ_uniqueMember 2 5 4 50 */
889, /* OBJ_houseIdentifier 2 5 4 51 */
890, /* OBJ_supportedAlgorithms 2 5 4 52 */
891, /* OBJ_deltaRevocationList 2 5 4 53 */
892, /* OBJ_dmdName 2 5 4 54 */
510, /* OBJ_pseudonym 2 5 4 65 */
400, /* OBJ_role 2 5 4 72 */
1089, /* OBJ_organizationIdentifier 2 5 4 97 */
1090, /* OBJ_countryCode3c 2 5 4 98 */
1091, /* OBJ_countryCode3n 2 5 4 99 */
1092, /* OBJ_dnsName 2 5 4 100 */
769, /* OBJ_subject_directory_attributes 2 5 29 9 */
82, /* OBJ_subject_key_identifier 2 5 29 14 */
83, /* OBJ_key_usage 2 5 29 15 */
84, /* OBJ_private_key_usage_period 2 5 29 16 */
85, /* OBJ_subject_alt_name 2 5 29 17 */
86, /* OBJ_issuer_alt_name 2 5 29 18 */
87, /* OBJ_basic_constraints 2 5 29 19 */
88, /* OBJ_crl_number 2 5 29 20 */
141, /* OBJ_crl_reason 2 5 29 21 */
430, /* OBJ_hold_instruction_code 2 5 29 23 */
142, /* OBJ_invalidity_date 2 5 29 24 */
140, /* OBJ_delta_crl 2 5 29 27 */
770, /* OBJ_issuing_distribution_point 2 5 29 28 */
771, /* OBJ_certificate_issuer 2 5 29 29 */
666, /* OBJ_name_constraints 2 5 29 30 */
103, /* OBJ_crl_distribution_points 2 5 29 31 */
89, /* OBJ_certificate_policies 2 5 29 32 */
747, /* OBJ_policy_mappings 2 5 29 33 */
90, /* OBJ_authority_key_identifier 2 5 29 35 */
401, /* OBJ_policy_constraints 2 5 29 36 */
126, /* OBJ_ext_key_usage 2 5 29 37 */
857, /* OBJ_freshest_crl 2 5 29 46 */
748, /* OBJ_inhibit_any_policy 2 5 29 54 */
402, /* OBJ_target_information 2 5 29 55 */
403, /* OBJ_no_rev_avail 2 5 29 56 */
513, /* OBJ_set_ctype 2 23 42 0 */
514, /* OBJ_set_msgExt 2 23 42 1 */
515, /* OBJ_set_attr 2 23 42 3 */
516, /* OBJ_set_policy 2 23 42 5 */
517, /* OBJ_set_certExt 2 23 42 7 */
518, /* OBJ_set_brand 2 23 42 8 */
679, /* OBJ_wap_wsg 2 23 43 1 */
382, /* OBJ_Directory 1 3 6 1 1 */
383, /* OBJ_Management 1 3 6 1 2 */
384, /* OBJ_Experimental 1 3 6 1 3 */
385, /* OBJ_Private 1 3 6 1 4 */
386, /* OBJ_Security 1 3 6 1 5 */
387, /* OBJ_SNMPv2 1 3 6 1 6 */
388, /* OBJ_Mail 1 3 6 1 7 */
376, /* OBJ_algorithm 1 3 14 3 2 */
395, /* OBJ_clearance 2 5 1 5 55 */
19, /* OBJ_rsa 2 5 8 1 1 */
96, /* OBJ_mdc2WithRSA 2 5 8 3 100 */
95, /* OBJ_mdc2 2 5 8 3 101 */
746, /* OBJ_any_policy 2 5 29 32 0 */
910, /* OBJ_anyExtendedKeyUsage 2 5 29 37 0 */
519, /* OBJ_setct_PANData 2 23 42 0 0 */
520, /* OBJ_setct_PANToken 2 23 42 0 1 */
521, /* OBJ_setct_PANOnly 2 23 42 0 2 */
522, /* OBJ_setct_OIData 2 23 42 0 3 */
523, /* OBJ_setct_PI 2 23 42 0 4 */
524, /* OBJ_setct_PIData 2 23 42 0 5 */
525, /* OBJ_setct_PIDataUnsigned 2 23 42 0 6 */
526, /* OBJ_setct_HODInput 2 23 42 0 7 */
527, /* OBJ_setct_AuthResBaggage 2 23 42 0 8 */
528, /* OBJ_setct_AuthRevReqBaggage 2 23 42 0 9 */
529, /* OBJ_setct_AuthRevResBaggage 2 23 42 0 10 */
530, /* OBJ_setct_CapTokenSeq 2 23 42 0 11 */
531, /* OBJ_setct_PInitResData 2 23 42 0 12 */
532, /* OBJ_setct_PI_TBS 2 23 42 0 13 */
533, /* OBJ_setct_PResData 2 23 42 0 14 */
534, /* OBJ_setct_AuthReqTBS 2 23 42 0 16 */
535, /* OBJ_setct_AuthResTBS 2 23 42 0 17 */
536, /* OBJ_setct_AuthResTBSX 2 23 42 0 18 */
537, /* OBJ_setct_AuthTokenTBS 2 23 42 0 19 */
538, /* OBJ_setct_CapTokenData 2 23 42 0 20 */
539, /* OBJ_setct_CapTokenTBS 2 23 42 0 21 */
540, /* OBJ_setct_AcqCardCodeMsg 2 23 42 0 22 */
541, /* OBJ_setct_AuthRevReqTBS 2 23 42 0 23 */
542, /* OBJ_setct_AuthRevResData 2 23 42 0 24 */
543, /* OBJ_setct_AuthRevResTBS 2 23 42 0 25 */
544, /* OBJ_setct_CapReqTBS 2 23 42 0 26 */
545, /* OBJ_setct_CapReqTBSX 2 23 42 0 27 */
546, /* OBJ_setct_CapResData 2 23 42 0 28 */
547, /* OBJ_setct_CapRevReqTBS 2 23 42 0 29 */
548, /* OBJ_setct_CapRevReqTBSX 2 23 42 0 30 */
549, /* OBJ_setct_CapRevResData 2 23 42 0 31 */
550, /* OBJ_setct_CredReqTBS 2 23 42 0 32 */
551, /* OBJ_setct_CredReqTBSX 2 23 42 0 33 */
552, /* OBJ_setct_CredResData 2 23 42 0 34 */
553, /* OBJ_setct_CredRevReqTBS 2 23 42 0 35 */
554, /* OBJ_setct_CredRevReqTBSX 2 23 42 0 36 */
555, /* OBJ_setct_CredRevResData 2 23 42 0 37 */
556, /* OBJ_setct_PCertReqData 2 23 42 0 38 */
557, /* OBJ_setct_PCertResTBS 2 23 42 0 39 */
558, /* OBJ_setct_BatchAdminReqData 2 23 42 0 40 */
559, /* OBJ_setct_BatchAdminResData 2 23 42 0 41 */
560, /* OBJ_setct_CardCInitResTBS 2 23 42 0 42 */
561, /* OBJ_setct_MeAqCInitResTBS 2 23 42 0 43 */
562, /* OBJ_setct_RegFormResTBS 2 23 42 0 44 */
563, /* OBJ_setct_CertReqData 2 23 42 0 45 */
564, /* OBJ_setct_CertReqTBS 2 23 42 0 46 */
565, /* OBJ_setct_CertResData 2 23 42 0 47 */
566, /* OBJ_setct_CertInqReqTBS 2 23 42 0 48 */
567, /* OBJ_setct_ErrorTBS 2 23 42 0 49 */
568, /* OBJ_setct_PIDualSignedTBE 2 23 42 0 50 */
569, /* OBJ_setct_PIUnsignedTBE 2 23 42 0 51 */
570, /* OBJ_setct_AuthReqTBE 2 23 42 0 52 */
571, /* OBJ_setct_AuthResTBE 2 23 42 0 53 */
572, /* OBJ_setct_AuthResTBEX 2 23 42 0 54 */
573, /* OBJ_setct_AuthTokenTBE 2 23 42 0 55 */
574, /* OBJ_setct_CapTokenTBE 2 23 42 0 56 */
575, /* OBJ_setct_CapTokenTBEX 2 23 42 0 57 */
576, /* OBJ_setct_AcqCardCodeMsgTBE 2 23 42 0 58 */
577, /* OBJ_setct_AuthRevReqTBE 2 23 42 0 59 */
578, /* OBJ_setct_AuthRevResTBE 2 23 42 0 60 */
579, /* OBJ_setct_AuthRevResTBEB 2 23 42 0 61 */
580, /* OBJ_setct_CapReqTBE 2 23 42 0 62 */
581, /* OBJ_setct_CapReqTBEX 2 23 42 0 63 */
582, /* OBJ_setct_CapResTBE 2 23 42 0 64 */
583, /* OBJ_setct_CapRevReqTBE 2 23 42 0 65 */
584, /* OBJ_setct_CapRevReqTBEX 2 23 42 0 66 */
585, /* OBJ_setct_CapRevResTBE 2 23 42 0 67 */
586, /* OBJ_setct_CredReqTBE 2 23 42 0 68 */
587, /* OBJ_setct_CredReqTBEX 2 23 42 0 69 */
588, /* OBJ_setct_CredResTBE 2 23 42 0 70 */
589, /* OBJ_setct_CredRevReqTBE 2 23 42 0 71 */
590, /* OBJ_setct_CredRevReqTBEX 2 23 42 0 72 */
591, /* OBJ_setct_CredRevResTBE 2 23 42 0 73 */
592, /* OBJ_setct_BatchAdminReqTBE 2 23 42 0 74 */
593, /* OBJ_setct_BatchAdminResTBE 2 23 42 0 75 */
594, /* OBJ_setct_RegFormReqTBE 2 23 42 0 76 */
595, /* OBJ_setct_CertReqTBE 2 23 42 0 77 */
596, /* OBJ_setct_CertReqTBEX 2 23 42 0 78 */
597, /* OBJ_setct_CertResTBE 2 23 42 0 79 */
598, /* OBJ_setct_CRLNotificationTBS 2 23 42 0 80 */
599, /* OBJ_setct_CRLNotificationResTBS 2 23 42 0 81 */
600, /* OBJ_setct_BCIDistributionTBS 2 23 42 0 82 */
601, /* OBJ_setext_genCrypt 2 23 42 1 1 */
602, /* OBJ_setext_miAuth 2 23 42 1 3 */
603, /* OBJ_setext_pinSecure 2 23 42 1 4 */
604, /* OBJ_setext_pinAny 2 23 42 1 5 */
605, /* OBJ_setext_track2 2 23 42 1 7 */
606, /* OBJ_setext_cv 2 23 42 1 8 */
620, /* OBJ_setAttr_Cert 2 23 42 3 0 */
621, /* OBJ_setAttr_PGWYcap 2 23 42 3 1 */
622, /* OBJ_setAttr_TokenType 2 23 42 3 2 */
623, /* OBJ_setAttr_IssCap 2 23 42 3 3 */
607, /* OBJ_set_policy_root 2 23 42 5 0 */
608, /* OBJ_setCext_hashedRoot 2 23 42 7 0 */
609, /* OBJ_setCext_certType 2 23 42 7 1 */
610, /* OBJ_setCext_merchData 2 23 42 7 2 */
611, /* OBJ_setCext_cCertRequired 2 23 42 7 3 */
612, /* OBJ_setCext_tunneling 2 23 42 7 4 */
613, /* OBJ_setCext_setExt 2 23 42 7 5 */
614, /* OBJ_setCext_setQualf 2 23 42 7 6 */
615, /* OBJ_setCext_PGWYcapabilities 2 23 42 7 7 */
616, /* OBJ_setCext_TokenIdentifier 2 23 42 7 8 */
617, /* OBJ_setCext_Track2Data 2 23 42 7 9 */
618, /* OBJ_setCext_TokenType 2 23 42 7 10 */
619, /* OBJ_setCext_IssuerCapabilities 2 23 42 7 11 */
636, /* OBJ_set_brand_IATA_ATA 2 23 42 8 1 */
640, /* OBJ_set_brand_Visa 2 23 42 8 4 */
641, /* OBJ_set_brand_MasterCard 2 23 42 8 5 */
637, /* OBJ_set_brand_Diners 2 23 42 8 30 */
638, /* OBJ_set_brand_AmericanExpress 2 23 42 8 34 */
639, /* OBJ_set_brand_JCB 2 23 42 8 35 */
1141, /* OBJ_oscca 1 2 156 10197 */
805, /* OBJ_cryptopro 1 2 643 2 2 */
806, /* OBJ_cryptocom 1 2 643 2 9 */
974, /* OBJ_id_tc26 1 2 643 7 1 */
1005, /* OBJ_OGRN 1 2 643 100 1 */
1006, /* OBJ_SNILS 1 2 643 100 3 */
1007, /* OBJ_subjectSignTool 1 2 643 100 111 */
1008, /* OBJ_issuerSignTool 1 2 643 100 112 */
184, /* OBJ_X9_57 1 2 840 10040 */
405, /* OBJ_ansi_X9_62 1 2 840 10045 */
389, /* OBJ_Enterprises 1 3 6 1 4 1 */
504, /* OBJ_mime_mhs 1 3 6 1 7 1 */
104, /* OBJ_md5WithRSA 1 3 14 3 2 3 */
29, /* OBJ_des_ecb 1 3 14 3 2 6 */
31, /* OBJ_des_cbc 1 3 14 3 2 7 */
45, /* OBJ_des_ofb64 1 3 14 3 2 8 */
30, /* OBJ_des_cfb64 1 3 14 3 2 9 */
377, /* OBJ_rsaSignature 1 3 14 3 2 11 */
67, /* OBJ_dsa_2 1 3 14 3 2 12 */
66, /* OBJ_dsaWithSHA 1 3 14 3 2 13 */
42, /* OBJ_shaWithRSAEncryption 1 3 14 3 2 15 */
32, /* OBJ_des_ede_ecb 1 3 14 3 2 17 */
41, /* OBJ_sha 1 3 14 3 2 18 */
64, /* OBJ_sha1 1 3 14 3 2 26 */
70, /* OBJ_dsaWithSHA1_2 1 3 14 3 2 27 */
115, /* OBJ_sha1WithRSA 1 3 14 3 2 29 */
117, /* OBJ_ripemd160 1 3 36 3 2 1 */
1093, /* OBJ_x509ExtAdmission 1 3 36 8 3 3 */
143, /* OBJ_sxnet 1 3 101 1 4 1 */
1171, /* OBJ_ieee_siswg 1 3 111 2 1619 */
721, /* OBJ_sect163k1 1 3 132 0 1 */
722, /* OBJ_sect163r1 1 3 132 0 2 */
728, /* OBJ_sect239k1 1 3 132 0 3 */
717, /* OBJ_sect113r1 1 3 132 0 4 */
718, /* OBJ_sect113r2 1 3 132 0 5 */
704, /* OBJ_secp112r1 1 3 132 0 6 */
705, /* OBJ_secp112r2 1 3 132 0 7 */
709, /* OBJ_secp160r1 1 3 132 0 8 */
708, /* OBJ_secp160k1 1 3 132 0 9 */
714, /* OBJ_secp256k1 1 3 132 0 10 */
723, /* OBJ_sect163r2 1 3 132 0 15 */
729, /* OBJ_sect283k1 1 3 132 0 16 */
730, /* OBJ_sect283r1 1 3 132 0 17 */
719, /* OBJ_sect131r1 1 3 132 0 22 */
720, /* OBJ_sect131r2 1 3 132 0 23 */
724, /* OBJ_sect193r1 1 3 132 0 24 */
725, /* OBJ_sect193r2 1 3 132 0 25 */
726, /* OBJ_sect233k1 1 3 132 0 26 */
727, /* OBJ_sect233r1 1 3 132 0 27 */
706, /* OBJ_secp128r1 1 3 132 0 28 */
707, /* OBJ_secp128r2 1 3 132 0 29 */
710, /* OBJ_secp160r2 1 3 132 0 30 */
711, /* OBJ_secp192k1 1 3 132 0 31 */
712, /* OBJ_secp224k1 1 3 132 0 32 */
713, /* OBJ_secp224r1 1 3 132 0 33 */
715, /* OBJ_secp384r1 1 3 132 0 34 */
716, /* OBJ_secp521r1 1 3 132 0 35 */
731, /* OBJ_sect409k1 1 3 132 0 36 */
732, /* OBJ_sect409r1 1 3 132 0 37 */
733, /* OBJ_sect571k1 1 3 132 0 38 */
734, /* OBJ_sect571r1 1 3 132 0 39 */
624, /* OBJ_set_rootKeyThumb 2 23 42 3 0 0 */
625, /* OBJ_set_addPolicy 2 23 42 3 0 1 */
626, /* OBJ_setAttr_Token_EMV 2 23 42 3 2 1 */
627, /* OBJ_setAttr_Token_B0Prime 2 23 42 3 2 2 */
628, /* OBJ_setAttr_IssCap_CVM 2 23 42 3 3 3 */
629, /* OBJ_setAttr_IssCap_T2 2 23 42 3 3 4 */
630, /* OBJ_setAttr_IssCap_Sig 2 23 42 3 3 5 */
642, /* OBJ_set_brand_Novus 2 23 42 8 6011 */
735, /* OBJ_wap_wsg_idm_ecid_wtls1 2 23 43 1 4 1 */
736, /* OBJ_wap_wsg_idm_ecid_wtls3 2 23 43 1 4 3 */
737, /* OBJ_wap_wsg_idm_ecid_wtls4 2 23 43 1 4 4 */
738, /* OBJ_wap_wsg_idm_ecid_wtls5 2 23 43 1 4 5 */
739, /* OBJ_wap_wsg_idm_ecid_wtls6 2 23 43 1 4 6 */
740, /* OBJ_wap_wsg_idm_ecid_wtls7 2 23 43 1 4 7 */
741, /* OBJ_wap_wsg_idm_ecid_wtls8 2 23 43 1 4 8 */
742, /* OBJ_wap_wsg_idm_ecid_wtls9 2 23 43 1 4 9 */
743, /* OBJ_wap_wsg_idm_ecid_wtls10 2 23 43 1 4 10 */
744, /* OBJ_wap_wsg_idm_ecid_wtls11 2 23 43 1 4 11 */
745, /* OBJ_wap_wsg_idm_ecid_wtls12 2 23 43 1 4 12 */
804, /* OBJ_whirlpool 1 0 10118 3 0 55 */
1142, /* OBJ_sm_scheme 1 2 156 10197 1 */
773, /* OBJ_kisa 1 2 410 200004 */
807, /* OBJ_id_GostR3411_94_with_GostR3410_2001 1 2 643 2 2 3 */
808, /* OBJ_id_GostR3411_94_with_GostR3410_94 1 2 643 2 2 4 */
809, /* OBJ_id_GostR3411_94 1 2 643 2 2 9 */
810, /* OBJ_id_HMACGostR3411_94 1 2 643 2 2 10 */
811, /* OBJ_id_GostR3410_2001 1 2 643 2 2 19 */
812, /* OBJ_id_GostR3410_94 1 2 643 2 2 20 */
813, /* OBJ_id_Gost28147_89 1 2 643 2 2 21 */
815, /* OBJ_id_Gost28147_89_MAC 1 2 643 2 2 22 */
816, /* OBJ_id_GostR3411_94_prf 1 2 643 2 2 23 */
817, /* OBJ_id_GostR3410_2001DH 1 2 643 2 2 98 */
818, /* OBJ_id_GostR3410_94DH 1 2 643 2 2 99 */
977, /* OBJ_id_tc26_algorithms 1 2 643 7 1 1 */
994, /* OBJ_id_tc26_constants 1 2 643 7 1 2 */
1, /* OBJ_rsadsi 1 2 840 113549 */
185, /* OBJ_X9cm 1 2 840 10040 4 */
1031, /* OBJ_id_pkinit 1 3 6 1 5 2 3 */
127, /* OBJ_id_pkix 1 3 6 1 5 5 7 */
505, /* OBJ_mime_mhs_headings 1 3 6 1 7 1 1 */
506, /* OBJ_mime_mhs_bodies 1 3 6 1 7 1 2 */
119, /* OBJ_ripemd160WithRSA 1 3 36 3 3 1 2 */
937, /* OBJ_dhSinglePass_stdDH_sha224kdf_scheme 1 3 132 1 11 0 */
938, /* OBJ_dhSinglePass_stdDH_sha256kdf_scheme 1 3 132 1 11 1 */
939, /* OBJ_dhSinglePass_stdDH_sha384kdf_scheme 1 3 132 1 11 2 */
940, /* OBJ_dhSinglePass_stdDH_sha512kdf_scheme 1 3 132 1 11 3 */
942, /* OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme 1 3 132 1 14 0 */
943, /* OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme 1 3 132 1 14 1 */
944, /* OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme 1 3 132 1 14 2 */
945, /* OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme 1 3 132 1 14 3 */
631, /* OBJ_setAttr_GenCryptgrm 2 23 42 3 3 3 1 */
632, /* OBJ_setAttr_T2Enc 2 23 42 3 3 4 1 */
633, /* OBJ_setAttr_T2cleartxt 2 23 42 3 3 4 2 */
634, /* OBJ_setAttr_TokICCsig 2 23 42 3 3 5 1 */
635, /* OBJ_setAttr_SecDevSig 2 23 42 3 3 5 2 */
436, /* OBJ_ucl 0 9 2342 19200300 */
820, /* OBJ_id_Gost28147_89_None_KeyMeshing 1 2 643 2 2 14 0 */
819, /* OBJ_id_Gost28147_89_CryptoPro_KeyMeshing 1 2 643 2 2 14 1 */
845, /* OBJ_id_GostR3410_94_a 1 2 643 2 2 20 1 */
846, /* OBJ_id_GostR3410_94_aBis 1 2 643 2 2 20 2 */
847, /* OBJ_id_GostR3410_94_b 1 2 643 2 2 20 3 */
848, /* OBJ_id_GostR3410_94_bBis 1 2 643 2 2 20 4 */
821, /* OBJ_id_GostR3411_94_TestParamSet 1 2 643 2 2 30 0 */
822, /* OBJ_id_GostR3411_94_CryptoProParamSet 1 2 643 2 2 30 1 */
823, /* OBJ_id_Gost28147_89_TestParamSet 1 2 643 2 2 31 0 */
824, /* OBJ_id_Gost28147_89_CryptoPro_A_ParamSet 1 2 643 2 2 31 1 */
825, /* OBJ_id_Gost28147_89_CryptoPro_B_ParamSet 1 2 643 2 2 31 2 */
826, /* OBJ_id_Gost28147_89_CryptoPro_C_ParamSet 1 2 643 2 2 31 3 */
827, /* OBJ_id_Gost28147_89_CryptoPro_D_ParamSet 1 2 643 2 2 31 4 */
828, /* OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 1 2 643 2 2 31 5 */
829, /* OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 1 2 643 2 2 31 6 */
830, /* OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 1 2 643 2 2 31 7 */
831, /* OBJ_id_GostR3410_94_TestParamSet 1 2 643 2 2 32 0 */
832, /* OBJ_id_GostR3410_94_CryptoPro_A_ParamSet 1 2 643 2 2 32 2 */
833, /* OBJ_id_GostR3410_94_CryptoPro_B_ParamSet 1 2 643 2 2 32 3 */
834, /* OBJ_id_GostR3410_94_CryptoPro_C_ParamSet 1 2 643 2 2 32 4 */
835, /* OBJ_id_GostR3410_94_CryptoPro_D_ParamSet 1 2 643 2 2 32 5 */
836, /* OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet 1 2 643 2 2 33 1 */
837, /* OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet 1 2 643 2 2 33 2 */
838, /* OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet 1 2 643 2 2 33 3 */
839, /* OBJ_id_GostR3410_2001_TestParamSet 1 2 643 2 2 35 0 */
840, /* OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet 1 2 643 2 2 35 1 */
841, /* OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet 1 2 643 2 2 35 2 */
842, /* OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet 1 2 643 2 2 35 3 */
843, /* OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet 1 2 643 2 2 36 0 */
844, /* OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet 1 2 643 2 2 36 1 */
978, /* OBJ_id_tc26_sign 1 2 643 7 1 1 1 */
981, /* OBJ_id_tc26_digest 1 2 643 7 1 1 2 */
984, /* OBJ_id_tc26_signwithdigest 1 2 643 7 1 1 3 */
987, /* OBJ_id_tc26_mac 1 2 643 7 1 1 4 */
990, /* OBJ_id_tc26_cipher 1 2 643 7 1 1 5 */
991, /* OBJ_id_tc26_agreement 1 2 643 7 1 1 6 */
1179, /* OBJ_id_tc26_wrap 1 2 643 7 1 1 7 */
995, /* OBJ_id_tc26_sign_constants 1 2 643 7 1 2 1 */
1000, /* OBJ_id_tc26_digest_constants 1 2 643 7 1 2 2 */
1001, /* OBJ_id_tc26_cipher_constants 1 2 643 7 1 2 5 */
1151, /* OBJ_ua_pki 1 2 804 2 1 1 1 */
2, /* OBJ_pkcs 1 2 840 113549 1 */
431, /* OBJ_hold_instruction_none 1 2 840 10040 2 1 */
432, /* OBJ_hold_instruction_call_issuer 1 2 840 10040 2 2 */
433, /* OBJ_hold_instruction_reject 1 2 840 10040 2 3 */
116, /* OBJ_dsa 1 2 840 10040 4 1 */
113, /* OBJ_dsaWithSHA1 1 2 840 10040 4 3 */
406, /* OBJ_X9_62_prime_field 1 2 840 10045 1 1 */
407, /* OBJ_X9_62_characteristic_two_field 1 2 840 10045 1 2 */
408, /* OBJ_X9_62_id_ecPublicKey 1 2 840 10045 2 1 */
416, /* OBJ_ecdsa_with_SHA1 1 2 840 10045 4 1 */
791, /* OBJ_ecdsa_with_Recommended 1 2 840 10045 4 2 */
792, /* OBJ_ecdsa_with_Specified 1 2 840 10045 4 3 */
920, /* OBJ_dhpublicnumber 1 2 840 10046 2 1 */
1032, /* OBJ_pkInitClientAuth 1 3 6 1 5 2 3 4 */
1033, /* OBJ_pkInitKDC 1 3 6 1 5 2 3 5 */
258, /* OBJ_id_pkix_mod 1 3 6 1 5 5 7 0 */
175, /* OBJ_id_pe 1 3 6 1 5 5 7 1 */
259, /* OBJ_id_qt 1 3 6 1 5 5 7 2 */
128, /* OBJ_id_kp 1 3 6 1 5 5 7 3 */
260, /* OBJ_id_it 1 3 6 1 5 5 7 4 */
261, /* OBJ_id_pkip 1 3 6 1 5 5 7 5 */
262, /* OBJ_id_alg 1 3 6 1 5 5 7 6 */
263, /* OBJ_id_cmc 1 3 6 1 5 5 7 7 */
264, /* OBJ_id_on 1 3 6 1 5 5 7 8 */
265, /* OBJ_id_pda 1 3 6 1 5 5 7 9 */
266, /* OBJ_id_aca 1 3 6 1 5 5 7 10 */
267, /* OBJ_id_qcs 1 3 6 1 5 5 7 11 */
268, /* OBJ_id_cct 1 3 6 1 5 5 7 12 */
662, /* OBJ_id_ppl 1 3 6 1 5 5 7 21 */
176, /* OBJ_id_ad 1 3 6 1 5 5 7 48 */
507, /* OBJ_id_hex_partial_message 1 3 6 1 7 1 1 1 */
508, /* OBJ_id_hex_multipart_message 1 3 6 1 7 1 1 2 */
57, /* OBJ_netscape 2 16 840 1 113730 */
754, /* OBJ_camellia_128_ecb 0 3 4401 5 3 1 9 1 */
766, /* OBJ_camellia_128_ofb128 0 3 4401 5 3 1 9 3 */
757, /* OBJ_camellia_128_cfb128 0 3 4401 5 3 1 9 4 */
961, /* OBJ_camellia_128_gcm 0 3 4401 5 3 1 9 6 */
962, /* OBJ_camellia_128_ccm 0 3 4401 5 3 1 9 7 */
963, /* OBJ_camellia_128_ctr 0 3 4401 5 3 1 9 9 */
964, /* OBJ_camellia_128_cmac 0 3 4401 5 3 1 9 10 */
755, /* OBJ_camellia_192_ecb 0 3 4401 5 3 1 9 21 */
767, /* OBJ_camellia_192_ofb128 0 3 4401 5 3 1 9 23 */
758, /* OBJ_camellia_192_cfb128 0 3 4401 5 3 1 9 24 */
965, /* OBJ_camellia_192_gcm 0 3 4401 5 3 1 9 26 */
966, /* OBJ_camellia_192_ccm 0 3 4401 5 3 1 9 27 */
967, /* OBJ_camellia_192_ctr 0 3 4401 5 3 1 9 29 */
968, /* OBJ_camellia_192_cmac 0 3 4401 5 3 1 9 30 */
756, /* OBJ_camellia_256_ecb 0 3 4401 5 3 1 9 41 */
768, /* OBJ_camellia_256_ofb128 0 3 4401 5 3 1 9 43 */
759, /* OBJ_camellia_256_cfb128 0 3 4401 5 3 1 9 44 */
969, /* OBJ_camellia_256_gcm 0 3 4401 5 3 1 9 46 */
970, /* OBJ_camellia_256_ccm 0 3 4401 5 3 1 9 47 */
971, /* OBJ_camellia_256_ctr 0 3 4401 5 3 1 9 49 */
972, /* OBJ_camellia_256_cmac 0 3 4401 5 3 1 9 50 */
437, /* OBJ_pilot 0 9 2342 19200300 100 */
1133, /* OBJ_sm4_ecb 1 2 156 10197 1 104 1 */
1134, /* OBJ_sm4_cbc 1 2 156 10197 1 104 2 */
1135, /* OBJ_sm4_ofb128 1 2 156 10197 1 104 3 */
1137, /* OBJ_sm4_cfb128 1 2 156 10197 1 104 4 */
1136, /* OBJ_sm4_cfb1 1 2 156 10197 1 104 5 */
1138, /* OBJ_sm4_cfb8 1 2 156 10197 1 104 6 */
1139, /* OBJ_sm4_ctr 1 2 156 10197 1 104 7 */
1172, /* OBJ_sm2 1 2 156 10197 1 301 */
1143, /* OBJ_sm3 1 2 156 10197 1 401 */
1144, /* OBJ_sm3WithRSAEncryption 1 2 156 10197 1 504 */
776, /* OBJ_seed_ecb 1 2 410 200004 1 3 */
777, /* OBJ_seed_cbc 1 2 410 200004 1 4 */
779, /* OBJ_seed_cfb128 1 2 410 200004 1 5 */
778, /* OBJ_seed_ofb128 1 2 410 200004 1 6 */
852, /* OBJ_id_GostR3411_94_with_GostR3410_94_cc 1 2 643 2 9 1 3 3 */
853, /* OBJ_id_GostR3411_94_with_GostR3410_2001_cc 1 2 643 2 9 1 3 4 */
850, /* OBJ_id_GostR3410_94_cc 1 2 643 2 9 1 5 3 */
851, /* OBJ_id_GostR3410_2001_cc 1 2 643 2 9 1 5 4 */
849, /* OBJ_id_Gost28147_89_cc 1 2 643 2 9 1 6 1 */
854, /* OBJ_id_GostR3410_2001_ParamSet_cc 1 2 643 2 9 1 8 1 */
1004, /* OBJ_INN 1 2 643 3 131 1 1 */
979, /* OBJ_id_GostR3410_2012_256 1 2 643 7 1 1 1 1 */
980, /* OBJ_id_GostR3410_2012_512 1 2 643 7 1 1 1 2 */
982, /* OBJ_id_GostR3411_2012_256 1 2 643 7 1 1 2 2 */
983, /* OBJ_id_GostR3411_2012_512 1 2 643 7 1 1 2 3 */
985, /* OBJ_id_tc26_signwithdigest_gost3410_2012_256 1 2 643 7 1 1 3 2 */
986, /* OBJ_id_tc26_signwithdigest_gost3410_2012_512 1 2 643 7 1 1 3 3 */
988, /* OBJ_id_tc26_hmac_gost_3411_2012_256 1 2 643 7 1 1 4 1 */
989, /* OBJ_id_tc26_hmac_gost_3411_2012_512 1 2 643 7 1 1 4 2 */
1173, /* OBJ_id_tc26_cipher_gostr3412_2015_magma 1 2 643 7 1 1 5 1 */
1176, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik 1 2 643 7 1 1 5 2 */
992, /* OBJ_id_tc26_agreement_gost_3410_2012_256 1 2 643 7 1 1 6 1 */
993, /* OBJ_id_tc26_agreement_gost_3410_2012_512 1 2 643 7 1 1 6 2 */
1180, /* OBJ_id_tc26_wrap_gostr3412_2015_magma 1 2 643 7 1 1 7 1 */
1182, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik 1 2 643 7 1 1 7 2 */
1147, /* OBJ_id_tc26_gost_3410_2012_256_constants 1 2 643 7 1 2 1 1 */
996, /* OBJ_id_tc26_gost_3410_2012_512_constants 1 2 643 7 1 2 1 2 */
1002, /* OBJ_id_tc26_gost_28147_constants 1 2 643 7 1 2 5 1 */
186, /* OBJ_pkcs1 1 2 840 113549 1 1 */
27, /* OBJ_pkcs3 1 2 840 113549 1 3 */
187, /* OBJ_pkcs5 1 2 840 113549 1 5 */
20, /* OBJ_pkcs7 1 2 840 113549 1 7 */
47, /* OBJ_pkcs9 1 2 840 113549 1 9 */
3, /* OBJ_md2 1 2 840 113549 2 2 */
257, /* OBJ_md4 1 2 840 113549 2 4 */
4, /* OBJ_md5 1 2 840 113549 2 5 */
797, /* OBJ_hmacWithMD5 1 2 840 113549 2 6 */
163, /* OBJ_hmacWithSHA1 1 2 840 113549 2 7 */
798, /* OBJ_hmacWithSHA224 1 2 840 113549 2 8 */
799, /* OBJ_hmacWithSHA256 1 2 840 113549 2 9 */
800, /* OBJ_hmacWithSHA384 1 2 840 113549 2 10 */
801, /* OBJ_hmacWithSHA512 1 2 840 113549 2 11 */
1193, /* OBJ_hmacWithSHA512_224 1 2 840 113549 2 12 */
1194, /* OBJ_hmacWithSHA512_256 1 2 840 113549 2 13 */
37, /* OBJ_rc2_cbc 1 2 840 113549 3 2 */
5, /* OBJ_rc4 1 2 840 113549 3 4 */
44, /* OBJ_des_ede3_cbc 1 2 840 113549 3 7 */
120, /* OBJ_rc5_cbc 1 2 840 113549 3 8 */
643, /* OBJ_des_cdmf 1 2 840 113549 3 10 */
680, /* OBJ_X9_62_id_characteristic_two_basis 1 2 840 10045 1 2 3 */
684, /* OBJ_X9_62_c2pnb163v1 1 2 840 10045 3 0 1 */
685, /* OBJ_X9_62_c2pnb163v2 1 2 840 10045 3 0 2 */
686, /* OBJ_X9_62_c2pnb163v3 1 2 840 10045 3 0 3 */
687, /* OBJ_X9_62_c2pnb176v1 1 2 840 10045 3 0 4 */
688, /* OBJ_X9_62_c2tnb191v1 1 2 840 10045 3 0 5 */
689, /* OBJ_X9_62_c2tnb191v2 1 2 840 10045 3 0 6 */
690, /* OBJ_X9_62_c2tnb191v3 1 2 840 10045 3 0 7 */
691, /* OBJ_X9_62_c2onb191v4 1 2 840 10045 3 0 8 */
692, /* OBJ_X9_62_c2onb191v5 1 2 840 10045 3 0 9 */
693, /* OBJ_X9_62_c2pnb208w1 1 2 840 10045 3 0 10 */
694, /* OBJ_X9_62_c2tnb239v1 1 2 840 10045 3 0 11 */
695, /* OBJ_X9_62_c2tnb239v2 1 2 840 10045 3 0 12 */
696, /* OBJ_X9_62_c2tnb239v3 1 2 840 10045 3 0 13 */
697, /* OBJ_X9_62_c2onb239v4 1 2 840 10045 3 0 14 */
698, /* OBJ_X9_62_c2onb239v5 1 2 840 10045 3 0 15 */
699, /* OBJ_X9_62_c2pnb272w1 1 2 840 10045 3 0 16 */
700, /* OBJ_X9_62_c2pnb304w1 1 2 840 10045 3 0 17 */
701, /* OBJ_X9_62_c2tnb359v1 1 2 840 10045 3 0 18 */
702, /* OBJ_X9_62_c2pnb368w1 1 2 840 10045 3 0 19 */
703, /* OBJ_X9_62_c2tnb431r1 1 2 840 10045 3 0 20 */
409, /* OBJ_X9_62_prime192v1 1 2 840 10045 3 1 1 */
410, /* OBJ_X9_62_prime192v2 1 2 840 10045 3 1 2 */
411, /* OBJ_X9_62_prime192v3 1 2 840 10045 3 1 3 */
412, /* OBJ_X9_62_prime239v1 1 2 840 10045 3 1 4 */
413, /* OBJ_X9_62_prime239v2 1 2 840 10045 3 1 5 */
414, /* OBJ_X9_62_prime239v3 1 2 840 10045 3 1 6 */
415, /* OBJ_X9_62_prime256v1 1 2 840 10045 3 1 7 */
793, /* OBJ_ecdsa_with_SHA224 1 2 840 10045 4 3 1 */
794, /* OBJ_ecdsa_with_SHA256 1 2 840 10045 4 3 2 */
795, /* OBJ_ecdsa_with_SHA384 1 2 840 10045 4 3 3 */
796, /* OBJ_ecdsa_with_SHA512 1 2 840 10045 4 3 4 */
269, /* OBJ_id_pkix1_explicit_88 1 3 6 1 5 5 7 0 1 */
270, /* OBJ_id_pkix1_implicit_88 1 3 6 1 5 5 7 0 2 */
271, /* OBJ_id_pkix1_explicit_93 1 3 6 1 5 5 7 0 3 */
272, /* OBJ_id_pkix1_implicit_93 1 3 6 1 5 5 7 0 4 */
273, /* OBJ_id_mod_crmf 1 3 6 1 5 5 7 0 5 */
274, /* OBJ_id_mod_cmc 1 3 6 1 5 5 7 0 6 */
275, /* OBJ_id_mod_kea_profile_88 1 3 6 1 5 5 7 0 7 */
276, /* OBJ_id_mod_kea_profile_93 1 3 6 1 5 5 7 0 8 */
277, /* OBJ_id_mod_cmp 1 3 6 1 5 5 7 0 9 */
278, /* OBJ_id_mod_qualified_cert_88 1 3 6 1 5 5 7 0 10 */
279, /* OBJ_id_mod_qualified_cert_93 1 3 6 1 5 5 7 0 11 */
280, /* OBJ_id_mod_attribute_cert 1 3 6 1 5 5 7 0 12 */
281, /* OBJ_id_mod_timestamp_protocol 1 3 6 1 5 5 7 0 13 */
282, /* OBJ_id_mod_ocsp 1 3 6 1 5 5 7 0 14 */
283, /* OBJ_id_mod_dvcs 1 3 6 1 5 5 7 0 15 */
284, /* OBJ_id_mod_cmp2000 1 3 6 1 5 5 7 0 16 */
177, /* OBJ_info_access 1 3 6 1 5 5 7 1 1 */
285, /* OBJ_biometricInfo 1 3 6 1 5 5 7 1 2 */
286, /* OBJ_qcStatements 1 3 6 1 5 5 7 1 3 */
287, /* OBJ_ac_auditEntity 1 3 6 1 5 5 7 1 4 */
288, /* OBJ_ac_targeting 1 3 6 1 5 5 7 1 5 */
289, /* OBJ_aaControls 1 3 6 1 5 5 7 1 6 */
290, /* OBJ_sbgp_ipAddrBlock 1 3 6 1 5 5 7 1 7 */
291, /* OBJ_sbgp_autonomousSysNum 1 3 6 1 5 5 7 1 8 */
292, /* OBJ_sbgp_routerIdentifier 1 3 6 1 5 5 7 1 9 */
397, /* OBJ_ac_proxying 1 3 6 1 5 5 7 1 10 */
398, /* OBJ_sinfo_access 1 3 6 1 5 5 7 1 11 */
663, /* OBJ_proxyCertInfo 1 3 6 1 5 5 7 1 14 */
1020, /* OBJ_tlsfeature 1 3 6 1 5 5 7 1 24 */
164, /* OBJ_id_qt_cps 1 3 6 1 5 5 7 2 1 */
165, /* OBJ_id_qt_unotice 1 3 6 1 5 5 7 2 2 */
293, /* OBJ_textNotice 1 3 6 1 5 5 7 2 3 */
129, /* OBJ_server_auth 1 3 6 1 5 5 7 3 1 */
130, /* OBJ_client_auth 1 3 6 1 5 5 7 3 2 */
131, /* OBJ_code_sign 1 3 6 1 5 5 7 3 3 */
132, /* OBJ_email_protect 1 3 6 1 5 5 7 3 4 */
294, /* OBJ_ipsecEndSystem 1 3 6 1 5 5 7 3 5 */
295, /* OBJ_ipsecTunnel 1 3 6 1 5 5 7 3 6 */
296, /* OBJ_ipsecUser 1 3 6 1 5 5 7 3 7 */
133, /* OBJ_time_stamp 1 3 6 1 5 5 7 3 8 */
180, /* OBJ_OCSP_sign 1 3 6 1 5 5 7 3 9 */
297, /* OBJ_dvcs 1 3 6 1 5 5 7 3 10 */
1022, /* OBJ_ipsec_IKE 1 3 6 1 5 5 7 3 17 */
1023, /* OBJ_capwapAC 1 3 6 1 5 5 7 3 18 */
1024, /* OBJ_capwapWTP 1 3 6 1 5 5 7 3 19 */
1025, /* OBJ_sshClient 1 3 6 1 5 5 7 3 21 */
1026, /* OBJ_sshServer 1 3 6 1 5 5 7 3 22 */
1027, /* OBJ_sendRouter 1 3 6 1 5 5 7 3 23 */
1028, /* OBJ_sendProxiedRouter 1 3 6 1 5 5 7 3 24 */
1029, /* OBJ_sendOwner 1 3 6 1 5 5 7 3 25 */
1030, /* OBJ_sendProxiedOwner 1 3 6 1 5 5 7 3 26 */
1131, /* OBJ_cmcCA 1 3 6 1 5 5 7 3 27 */
1132, /* OBJ_cmcRA 1 3 6 1 5 5 7 3 28 */
298, /* OBJ_id_it_caProtEncCert 1 3 6 1 5 5 7 4 1 */
299, /* OBJ_id_it_signKeyPairTypes 1 3 6 1 5 5 7 4 2 */
300, /* OBJ_id_it_encKeyPairTypes 1 3 6 1 5 5 7 4 3 */
301, /* OBJ_id_it_preferredSymmAlg 1 3 6 1 5 5 7 4 4 */
302, /* OBJ_id_it_caKeyUpdateInfo 1 3 6 1 5 5 7 4 5 */
303, /* OBJ_id_it_currentCRL 1 3 6 1 5 5 7 4 6 */
304, /* OBJ_id_it_unsupportedOIDs 1 3 6 1 5 5 7 4 7 */
305, /* OBJ_id_it_subscriptionRequest 1 3 6 1 5 5 7 4 8 */
306, /* OBJ_id_it_subscriptionResponse 1 3 6 1 5 5 7 4 9 */
307, /* OBJ_id_it_keyPairParamReq 1 3 6 1 5 5 7 4 10 */
308, /* OBJ_id_it_keyPairParamRep 1 3 6 1 5 5 7 4 11 */
309, /* OBJ_id_it_revPassphrase 1 3 6 1 5 5 7 4 12 */
310, /* OBJ_id_it_implicitConfirm 1 3 6 1 5 5 7 4 13 */
311, /* OBJ_id_it_confirmWaitTime 1 3 6 1 5 5 7 4 14 */
312, /* OBJ_id_it_origPKIMessage 1 3 6 1 5 5 7 4 15 */
784, /* OBJ_id_it_suppLangTags 1 3 6 1 5 5 7 4 16 */
313, /* OBJ_id_regCtrl 1 3 6 1 5 5 7 5 1 */
314, /* OBJ_id_regInfo 1 3 6 1 5 5 7 5 2 */
323, /* OBJ_id_alg_des40 1 3 6 1 5 5 7 6 1 */
324, /* OBJ_id_alg_noSignature 1 3 6 1 5 5 7 6 2 */
325, /* OBJ_id_alg_dh_sig_hmac_sha1 1 3 6 1 5 5 7 6 3 */
326, /* OBJ_id_alg_dh_pop 1 3 6 1 5 5 7 6 4 */
327, /* OBJ_id_cmc_statusInfo 1 3 6 1 5 5 7 7 1 */
328, /* OBJ_id_cmc_identification 1 3 6 1 5 5 7 7 2 */
329, /* OBJ_id_cmc_identityProof 1 3 6 1 5 5 7 7 3 */
330, /* OBJ_id_cmc_dataReturn 1 3 6 1 5 5 7 7 4 */
331, /* OBJ_id_cmc_transactionId 1 3 6 1 5 5 7 7 5 */
332, /* OBJ_id_cmc_senderNonce 1 3 6 1 5 5 7 7 6 */
333, /* OBJ_id_cmc_recipientNonce 1 3 6 1 5 5 7 7 7 */
334, /* OBJ_id_cmc_addExtensions 1 3 6 1 5 5 7 7 8 */
335, /* OBJ_id_cmc_encryptedPOP 1 3 6 1 5 5 7 7 9 */
336, /* OBJ_id_cmc_decryptedPOP 1 3 6 1 5 5 7 7 10 */
337, /* OBJ_id_cmc_lraPOPWitness 1 3 6 1 5 5 7 7 11 */
338, /* OBJ_id_cmc_getCert 1 3 6 1 5 5 7 7 15 */
339, /* OBJ_id_cmc_getCRL 1 3 6 1 5 5 7 7 16 */
340, /* OBJ_id_cmc_revokeRequest 1 3 6 1 5 5 7 7 17 */
341, /* OBJ_id_cmc_regInfo 1 3 6 1 5 5 7 7 18 */
342, /* OBJ_id_cmc_responseInfo 1 3 6 1 5 5 7 7 19 */
343, /* OBJ_id_cmc_queryPending 1 3 6 1 5 5 7 7 21 */
344, /* OBJ_id_cmc_popLinkRandom 1 3 6 1 5 5 7 7 22 */
345, /* OBJ_id_cmc_popLinkWitness 1 3 6 1 5 5 7 7 23 */
346, /* OBJ_id_cmc_confirmCertAcceptance 1 3 6 1 5 5 7 7 24 */
347, /* OBJ_id_on_personalData 1 3 6 1 5 5 7 8 1 */
858, /* OBJ_id_on_permanentIdentifier 1 3 6 1 5 5 7 8 3 */
348, /* OBJ_id_pda_dateOfBirth 1 3 6 1 5 5 7 9 1 */
349, /* OBJ_id_pda_placeOfBirth 1 3 6 1 5 5 7 9 2 */
351, /* OBJ_id_pda_gender 1 3 6 1 5 5 7 9 3 */
352, /* OBJ_id_pda_countryOfCitizenship 1 3 6 1 5 5 7 9 4 */
353, /* OBJ_id_pda_countryOfResidence 1 3 6 1 5 5 7 9 5 */
354, /* OBJ_id_aca_authenticationInfo 1 3 6 1 5 5 7 10 1 */
355, /* OBJ_id_aca_accessIdentity 1 3 6 1 5 5 7 10 2 */
356, /* OBJ_id_aca_chargingIdentity 1 3 6 1 5 5 7 10 3 */
357, /* OBJ_id_aca_group 1 3 6 1 5 5 7 10 4 */
358, /* OBJ_id_aca_role 1 3 6 1 5 5 7 10 5 */
399, /* OBJ_id_aca_encAttrs 1 3 6 1 5 5 7 10 6 */
359, /* OBJ_id_qcs_pkixQCSyntax_v1 1 3 6 1 5 5 7 11 1 */
360, /* OBJ_id_cct_crs 1 3 6 1 5 5 7 12 1 */
361, /* OBJ_id_cct_PKIData 1 3 6 1 5 5 7 12 2 */
362, /* OBJ_id_cct_PKIResponse 1 3 6 1 5 5 7 12 3 */
664, /* OBJ_id_ppl_anyLanguage 1 3 6 1 5 5 7 21 0 */
665, /* OBJ_id_ppl_inheritAll 1 3 6 1 5 5 7 21 1 */
667, /* OBJ_Independent 1 3 6 1 5 5 7 21 2 */
178, /* OBJ_ad_OCSP 1 3 6 1 5 5 7 48 1 */
179, /* OBJ_ad_ca_issuers 1 3 6 1 5 5 7 48 2 */
363, /* OBJ_ad_timeStamping 1 3 6 1 5 5 7 48 3 */
364, /* OBJ_ad_dvcs 1 3 6 1 5 5 7 48 4 */
785, /* OBJ_caRepository 1 3 6 1 5 5 7 48 5 */
780, /* OBJ_hmac_md5 1 3 6 1 5 5 8 1 1 */
781, /* OBJ_hmac_sha1 1 3 6 1 5 5 8 1 2 */
913, /* OBJ_aes_128_xts 1 3 111 2 1619 0 1 1 */
914, /* OBJ_aes_256_xts 1 3 111 2 1619 0 1 2 */
58, /* OBJ_netscape_cert_extension 2 16 840 1 113730 1 */
59, /* OBJ_netscape_data_type 2 16 840 1 113730 2 */
438, /* OBJ_pilotAttributeType 0 9 2342 19200300 100 1 */
439, /* OBJ_pilotAttributeSyntax 0 9 2342 19200300 100 3 */
440, /* OBJ_pilotObjectClass 0 9 2342 19200300 100 4 */
441, /* OBJ_pilotGroups 0 9 2342 19200300 100 10 */
1065, /* OBJ_aria_128_ecb 1 2 410 200046 1 1 1 */
1066, /* OBJ_aria_128_cbc 1 2 410 200046 1 1 2 */
1067, /* OBJ_aria_128_cfb128 1 2 410 200046 1 1 3 */
1068, /* OBJ_aria_128_ofb128 1 2 410 200046 1 1 4 */
1069, /* OBJ_aria_128_ctr 1 2 410 200046 1 1 5 */
1070, /* OBJ_aria_192_ecb 1 2 410 200046 1 1 6 */
1071, /* OBJ_aria_192_cbc 1 2 410 200046 1 1 7 */
1072, /* OBJ_aria_192_cfb128 1 2 410 200046 1 1 8 */
1073, /* OBJ_aria_192_ofb128 1 2 410 200046 1 1 9 */
1074, /* OBJ_aria_192_ctr 1 2 410 200046 1 1 10 */
1075, /* OBJ_aria_256_ecb 1 2 410 200046 1 1 11 */
1076, /* OBJ_aria_256_cbc 1 2 410 200046 1 1 12 */
1077, /* OBJ_aria_256_cfb128 1 2 410 200046 1 1 13 */
1078, /* OBJ_aria_256_ofb128 1 2 410 200046 1 1 14 */
1079, /* OBJ_aria_256_ctr 1 2 410 200046 1 1 15 */
1123, /* OBJ_aria_128_gcm 1 2 410 200046 1 1 34 */
1124, /* OBJ_aria_192_gcm 1 2 410 200046 1 1 35 */
1125, /* OBJ_aria_256_gcm 1 2 410 200046 1 1 36 */
1120, /* OBJ_aria_128_ccm 1 2 410 200046 1 1 37 */
1121, /* OBJ_aria_192_ccm 1 2 410 200046 1 1 38 */
1122, /* OBJ_aria_256_ccm 1 2 410 200046 1 1 39 */
1174, /* OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1 2 643 7 1 1 5 1 1 */
1175, /* OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1 2 643 7 1 1 5 1 2 */
1177, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1 2 643 7 1 1 5 2 1 */
1178, /* OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1 2 643 7 1 1 5 2 2 */
1181, /* OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 1 2 643 7 1 1 7 1 1 */
- 1183, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 1 1 */
+ 1183, /* OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1 2 643 7 1 1 7 2 1 */
1148, /* OBJ_id_tc26_gost_3410_2012_256_paramSetA 1 2 643 7 1 2 1 1 1 */
1184, /* OBJ_id_tc26_gost_3410_2012_256_paramSetB 1 2 643 7 1 2 1 1 2 */
1185, /* OBJ_id_tc26_gost_3410_2012_256_paramSetC 1 2 643 7 1 2 1 1 3 */
1186, /* OBJ_id_tc26_gost_3410_2012_256_paramSetD 1 2 643 7 1 2 1 1 4 */
997, /* OBJ_id_tc26_gost_3410_2012_512_paramSetTest 1 2 643 7 1 2 1 2 0 */
998, /* OBJ_id_tc26_gost_3410_2012_512_paramSetA 1 2 643 7 1 2 1 2 1 */
999, /* OBJ_id_tc26_gost_3410_2012_512_paramSetB 1 2 643 7 1 2 1 2 2 */
1149, /* OBJ_id_tc26_gost_3410_2012_512_paramSetC 1 2 643 7 1 2 1 2 3 */
1003, /* OBJ_id_tc26_gost_28147_param_Z 1 2 643 7 1 2 5 1 1 */
108, /* OBJ_cast5_cbc 1 2 840 113533 7 66 10 */
112, /* OBJ_pbeWithMD5AndCast5_CBC 1 2 840 113533 7 66 12 */
782, /* OBJ_id_PasswordBasedMAC 1 2 840 113533 7 66 13 */
783, /* OBJ_id_DHBasedMac 1 2 840 113533 7 66 30 */
6, /* OBJ_rsaEncryption 1 2 840 113549 1 1 1 */
7, /* OBJ_md2WithRSAEncryption 1 2 840 113549 1 1 2 */
396, /* OBJ_md4WithRSAEncryption 1 2 840 113549 1 1 3 */
8, /* OBJ_md5WithRSAEncryption 1 2 840 113549 1 1 4 */
65, /* OBJ_sha1WithRSAEncryption 1 2 840 113549 1 1 5 */
644, /* OBJ_rsaOAEPEncryptionSET 1 2 840 113549 1 1 6 */
919, /* OBJ_rsaesOaep 1 2 840 113549 1 1 7 */
911, /* OBJ_mgf1 1 2 840 113549 1 1 8 */
935, /* OBJ_pSpecified 1 2 840 113549 1 1 9 */
912, /* OBJ_rsassaPss 1 2 840 113549 1 1 10 */
668, /* OBJ_sha256WithRSAEncryption 1 2 840 113549 1 1 11 */
669, /* OBJ_sha384WithRSAEncryption 1 2 840 113549 1 1 12 */
670, /* OBJ_sha512WithRSAEncryption 1 2 840 113549 1 1 13 */
671, /* OBJ_sha224WithRSAEncryption 1 2 840 113549 1 1 14 */
1145, /* OBJ_sha512_224WithRSAEncryption 1 2 840 113549 1 1 15 */
1146, /* OBJ_sha512_256WithRSAEncryption 1 2 840 113549 1 1 16 */
28, /* OBJ_dhKeyAgreement 1 2 840 113549 1 3 1 */
9, /* OBJ_pbeWithMD2AndDES_CBC 1 2 840 113549 1 5 1 */
10, /* OBJ_pbeWithMD5AndDES_CBC 1 2 840 113549 1 5 3 */
168, /* OBJ_pbeWithMD2AndRC2_CBC 1 2 840 113549 1 5 4 */
169, /* OBJ_pbeWithMD5AndRC2_CBC 1 2 840 113549 1 5 6 */
170, /* OBJ_pbeWithSHA1AndDES_CBC 1 2 840 113549 1 5 10 */
68, /* OBJ_pbeWithSHA1AndRC2_CBC 1 2 840 113549 1 5 11 */
69, /* OBJ_id_pbkdf2 1 2 840 113549 1 5 12 */
161, /* OBJ_pbes2 1 2 840 113549 1 5 13 */
162, /* OBJ_pbmac1 1 2 840 113549 1 5 14 */
21, /* OBJ_pkcs7_data 1 2 840 113549 1 7 1 */
22, /* OBJ_pkcs7_signed 1 2 840 113549 1 7 2 */
23, /* OBJ_pkcs7_enveloped 1 2 840 113549 1 7 3 */
24, /* OBJ_pkcs7_signedAndEnveloped 1 2 840 113549 1 7 4 */
25, /* OBJ_pkcs7_digest 1 2 840 113549 1 7 5 */
26, /* OBJ_pkcs7_encrypted 1 2 840 113549 1 7 6 */
48, /* OBJ_pkcs9_emailAddress 1 2 840 113549 1 9 1 */
49, /* OBJ_pkcs9_unstructuredName 1 2 840 113549 1 9 2 */
50, /* OBJ_pkcs9_contentType 1 2 840 113549 1 9 3 */
51, /* OBJ_pkcs9_messageDigest 1 2 840 113549 1 9 4 */
52, /* OBJ_pkcs9_signingTime 1 2 840 113549 1 9 5 */
53, /* OBJ_pkcs9_countersignature 1 2 840 113549 1 9 6 */
54, /* OBJ_pkcs9_challengePassword 1 2 840 113549 1 9 7 */
55, /* OBJ_pkcs9_unstructuredAddress 1 2 840 113549 1 9 8 */
56, /* OBJ_pkcs9_extCertAttributes 1 2 840 113549 1 9 9 */
172, /* OBJ_ext_req 1 2 840 113549 1 9 14 */
167, /* OBJ_SMIMECapabilities 1 2 840 113549 1 9 15 */
188, /* OBJ_SMIME 1 2 840 113549 1 9 16 */
156, /* OBJ_friendlyName 1 2 840 113549 1 9 20 */
157, /* OBJ_localKeyID 1 2 840 113549 1 9 21 */
681, /* OBJ_X9_62_onBasis 1 2 840 10045 1 2 3 1 */
682, /* OBJ_X9_62_tpBasis 1 2 840 10045 1 2 3 2 */
683, /* OBJ_X9_62_ppBasis 1 2 840 10045 1 2 3 3 */
417, /* OBJ_ms_csp_name 1 3 6 1 4 1 311 17 1 */
856, /* OBJ_LocalKeySet 1 3 6 1 4 1 311 17 2 */
390, /* OBJ_dcObject 1 3 6 1 4 1 1466 344 */
91, /* OBJ_bf_cbc 1 3 6 1 4 1 3029 1 2 */
973, /* OBJ_id_scrypt 1 3 6 1 4 1 11591 4 11 */
315, /* OBJ_id_regCtrl_regToken 1 3 6 1 5 5 7 5 1 1 */
316, /* OBJ_id_regCtrl_authenticator 1 3 6 1 5 5 7 5 1 2 */
317, /* OBJ_id_regCtrl_pkiPublicationInfo 1 3 6 1 5 5 7 5 1 3 */
318, /* OBJ_id_regCtrl_pkiArchiveOptions 1 3 6 1 5 5 7 5 1 4 */
319, /* OBJ_id_regCtrl_oldCertID 1 3 6 1 5 5 7 5 1 5 */
320, /* OBJ_id_regCtrl_protocolEncrKey 1 3 6 1 5 5 7 5 1 6 */
321, /* OBJ_id_regInfo_utf8Pairs 1 3 6 1 5 5 7 5 2 1 */
322, /* OBJ_id_regInfo_certReq 1 3 6 1 5 5 7 5 2 2 */
365, /* OBJ_id_pkix_OCSP_basic 1 3 6 1 5 5 7 48 1 1 */
366, /* OBJ_id_pkix_OCSP_Nonce 1 3 6 1 5 5 7 48 1 2 */
367, /* OBJ_id_pkix_OCSP_CrlID 1 3 6 1 5 5 7 48 1 3 */
368, /* OBJ_id_pkix_OCSP_acceptableResponses 1 3 6 1 5 5 7 48 1 4 */
369, /* OBJ_id_pkix_OCSP_noCheck 1 3 6 1 5 5 7 48 1 5 */
370, /* OBJ_id_pkix_OCSP_archiveCutoff 1 3 6 1 5 5 7 48 1 6 */
371, /* OBJ_id_pkix_OCSP_serviceLocator 1 3 6 1 5 5 7 48 1 7 */
372, /* OBJ_id_pkix_OCSP_extendedStatus 1 3 6 1 5 5 7 48 1 8 */
373, /* OBJ_id_pkix_OCSP_valid 1 3 6 1 5 5 7 48 1 9 */
374, /* OBJ_id_pkix_OCSP_path 1 3 6 1 5 5 7 48 1 10 */
375, /* OBJ_id_pkix_OCSP_trustRoot 1 3 6 1 5 5 7 48 1 11 */
921, /* OBJ_brainpoolP160r1 1 3 36 3 3 2 8 1 1 1 */
922, /* OBJ_brainpoolP160t1 1 3 36 3 3 2 8 1 1 2 */
923, /* OBJ_brainpoolP192r1 1 3 36 3 3 2 8 1 1 3 */
924, /* OBJ_brainpoolP192t1 1 3 36 3 3 2 8 1 1 4 */
925, /* OBJ_brainpoolP224r1 1 3 36 3 3 2 8 1 1 5 */
926, /* OBJ_brainpoolP224t1 1 3 36 3 3 2 8 1 1 6 */
927, /* OBJ_brainpoolP256r1 1 3 36 3 3 2 8 1 1 7 */
928, /* OBJ_brainpoolP256t1 1 3 36 3 3 2 8 1 1 8 */
929, /* OBJ_brainpoolP320r1 1 3 36 3 3 2 8 1 1 9 */
930, /* OBJ_brainpoolP320t1 1 3 36 3 3 2 8 1 1 10 */
931, /* OBJ_brainpoolP384r1 1 3 36 3 3 2 8 1 1 11 */
932, /* OBJ_brainpoolP384t1 1 3 36 3 3 2 8 1 1 12 */
933, /* OBJ_brainpoolP512r1 1 3 36 3 3 2 8 1 1 13 */
934, /* OBJ_brainpoolP512t1 1 3 36 3 3 2 8 1 1 14 */
936, /* OBJ_dhSinglePass_stdDH_sha1kdf_scheme 1 3 133 16 840 63 0 2 */
941, /* OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme 1 3 133 16 840 63 0 3 */
418, /* OBJ_aes_128_ecb 2 16 840 1 101 3 4 1 1 */
419, /* OBJ_aes_128_cbc 2 16 840 1 101 3 4 1 2 */
420, /* OBJ_aes_128_ofb128 2 16 840 1 101 3 4 1 3 */
421, /* OBJ_aes_128_cfb128 2 16 840 1 101 3 4 1 4 */
788, /* OBJ_id_aes128_wrap 2 16 840 1 101 3 4 1 5 */
895, /* OBJ_aes_128_gcm 2 16 840 1 101 3 4 1 6 */
896, /* OBJ_aes_128_ccm 2 16 840 1 101 3 4 1 7 */
897, /* OBJ_id_aes128_wrap_pad 2 16 840 1 101 3 4 1 8 */
422, /* OBJ_aes_192_ecb 2 16 840 1 101 3 4 1 21 */
423, /* OBJ_aes_192_cbc 2 16 840 1 101 3 4 1 22 */
424, /* OBJ_aes_192_ofb128 2 16 840 1 101 3 4 1 23 */
425, /* OBJ_aes_192_cfb128 2 16 840 1 101 3 4 1 24 */
789, /* OBJ_id_aes192_wrap 2 16 840 1 101 3 4 1 25 */
898, /* OBJ_aes_192_gcm 2 16 840 1 101 3 4 1 26 */
899, /* OBJ_aes_192_ccm 2 16 840 1 101 3 4 1 27 */
900, /* OBJ_id_aes192_wrap_pad 2 16 840 1 101 3 4 1 28 */
426, /* OBJ_aes_256_ecb 2 16 840 1 101 3 4 1 41 */
427, /* OBJ_aes_256_cbc 2 16 840 1 101 3 4 1 42 */
428, /* OBJ_aes_256_ofb128 2 16 840 1 101 3 4 1 43 */
429, /* OBJ_aes_256_cfb128 2 16 840 1 101 3 4 1 44 */
790, /* OBJ_id_aes256_wrap 2 16 840 1 101 3 4 1 45 */
901, /* OBJ_aes_256_gcm 2 16 840 1 101 3 4 1 46 */
902, /* OBJ_aes_256_ccm 2 16 840 1 101 3 4 1 47 */
903, /* OBJ_id_aes256_wrap_pad 2 16 840 1 101 3 4 1 48 */
672, /* OBJ_sha256 2 16 840 1 101 3 4 2 1 */
673, /* OBJ_sha384 2 16 840 1 101 3 4 2 2 */
674, /* OBJ_sha512 2 16 840 1 101 3 4 2 3 */
675, /* OBJ_sha224 2 16 840 1 101 3 4 2 4 */
1094, /* OBJ_sha512_224 2 16 840 1 101 3 4 2 5 */
1095, /* OBJ_sha512_256 2 16 840 1 101 3 4 2 6 */
1096, /* OBJ_sha3_224 2 16 840 1 101 3 4 2 7 */
1097, /* OBJ_sha3_256 2 16 840 1 101 3 4 2 8 */
1098, /* OBJ_sha3_384 2 16 840 1 101 3 4 2 9 */
1099, /* OBJ_sha3_512 2 16 840 1 101 3 4 2 10 */
1100, /* OBJ_shake128 2 16 840 1 101 3 4 2 11 */
1101, /* OBJ_shake256 2 16 840 1 101 3 4 2 12 */
1102, /* OBJ_hmac_sha3_224 2 16 840 1 101 3 4 2 13 */
1103, /* OBJ_hmac_sha3_256 2 16 840 1 101 3 4 2 14 */
1104, /* OBJ_hmac_sha3_384 2 16 840 1 101 3 4 2 15 */
1105, /* OBJ_hmac_sha3_512 2 16 840 1 101 3 4 2 16 */
802, /* OBJ_dsa_with_SHA224 2 16 840 1 101 3 4 3 1 */
803, /* OBJ_dsa_with_SHA256 2 16 840 1 101 3 4 3 2 */
1106, /* OBJ_dsa_with_SHA384 2 16 840 1 101 3 4 3 3 */
1107, /* OBJ_dsa_with_SHA512 2 16 840 1 101 3 4 3 4 */
1108, /* OBJ_dsa_with_SHA3_224 2 16 840 1 101 3 4 3 5 */
1109, /* OBJ_dsa_with_SHA3_256 2 16 840 1 101 3 4 3 6 */
1110, /* OBJ_dsa_with_SHA3_384 2 16 840 1 101 3 4 3 7 */
1111, /* OBJ_dsa_with_SHA3_512 2 16 840 1 101 3 4 3 8 */
1112, /* OBJ_ecdsa_with_SHA3_224 2 16 840 1 101 3 4 3 9 */
1113, /* OBJ_ecdsa_with_SHA3_256 2 16 840 1 101 3 4 3 10 */
1114, /* OBJ_ecdsa_with_SHA3_384 2 16 840 1 101 3 4 3 11 */
1115, /* OBJ_ecdsa_with_SHA3_512 2 16 840 1 101 3 4 3 12 */
1116, /* OBJ_RSA_SHA3_224 2 16 840 1 101 3 4 3 13 */
1117, /* OBJ_RSA_SHA3_256 2 16 840 1 101 3 4 3 14 */
1118, /* OBJ_RSA_SHA3_384 2 16 840 1 101 3 4 3 15 */
1119, /* OBJ_RSA_SHA3_512 2 16 840 1 101 3 4 3 16 */
71, /* OBJ_netscape_cert_type 2 16 840 1 113730 1 1 */
72, /* OBJ_netscape_base_url 2 16 840 1 113730 1 2 */
73, /* OBJ_netscape_revocation_url 2 16 840 1 113730 1 3 */
74, /* OBJ_netscape_ca_revocation_url 2 16 840 1 113730 1 4 */
75, /* OBJ_netscape_renewal_url 2 16 840 1 113730 1 7 */
76, /* OBJ_netscape_ca_policy_url 2 16 840 1 113730 1 8 */
77, /* OBJ_netscape_ssl_server_name 2 16 840 1 113730 1 12 */
78, /* OBJ_netscape_comment 2 16 840 1 113730 1 13 */
79, /* OBJ_netscape_cert_sequence 2 16 840 1 113730 2 5 */
139, /* OBJ_ns_sgc 2 16 840 1 113730 4 1 */
458, /* OBJ_userId 0 9 2342 19200300 100 1 1 */
459, /* OBJ_textEncodedORAddress 0 9 2342 19200300 100 1 2 */
460, /* OBJ_rfc822Mailbox 0 9 2342 19200300 100 1 3 */
461, /* OBJ_info 0 9 2342 19200300 100 1 4 */
462, /* OBJ_favouriteDrink 0 9 2342 19200300 100 1 5 */
463, /* OBJ_roomNumber 0 9 2342 19200300 100 1 6 */
464, /* OBJ_photo 0 9 2342 19200300 100 1 7 */
465, /* OBJ_userClass 0 9 2342 19200300 100 1 8 */
466, /* OBJ_host 0 9 2342 19200300 100 1 9 */
467, /* OBJ_manager 0 9 2342 19200300 100 1 10 */
468, /* OBJ_documentIdentifier 0 9 2342 19200300 100 1 11 */
469, /* OBJ_documentTitle 0 9 2342 19200300 100 1 12 */
470, /* OBJ_documentVersion 0 9 2342 19200300 100 1 13 */
471, /* OBJ_documentAuthor 0 9 2342 19200300 100 1 14 */
472, /* OBJ_documentLocation 0 9 2342 19200300 100 1 15 */
473, /* OBJ_homeTelephoneNumber 0 9 2342 19200300 100 1 20 */
474, /* OBJ_secretary 0 9 2342 19200300 100 1 21 */
475, /* OBJ_otherMailbox 0 9 2342 19200300 100 1 22 */
476, /* OBJ_lastModifiedTime 0 9 2342 19200300 100 1 23 */
477, /* OBJ_lastModifiedBy 0 9 2342 19200300 100 1 24 */
391, /* OBJ_domainComponent 0 9 2342 19200300 100 1 25 */
478, /* OBJ_aRecord 0 9 2342 19200300 100 1 26 */
479, /* OBJ_pilotAttributeType27 0 9 2342 19200300 100 1 27 */
480, /* OBJ_mXRecord 0 9 2342 19200300 100 1 28 */
481, /* OBJ_nSRecord 0 9 2342 19200300 100 1 29 */
482, /* OBJ_sOARecord 0 9 2342 19200300 100 1 30 */
483, /* OBJ_cNAMERecord 0 9 2342 19200300 100 1 31 */
484, /* OBJ_associatedDomain 0 9 2342 19200300 100 1 37 */
485, /* OBJ_associatedName 0 9 2342 19200300 100 1 38 */
486, /* OBJ_homePostalAddress 0 9 2342 19200300 100 1 39 */
487, /* OBJ_personalTitle 0 9 2342 19200300 100 1 40 */
488, /* OBJ_mobileTelephoneNumber 0 9 2342 19200300 100 1 41 */
489, /* OBJ_pagerTelephoneNumber 0 9 2342 19200300 100 1 42 */
490, /* OBJ_friendlyCountryName 0 9 2342 19200300 100 1 43 */
102, /* OBJ_uniqueIdentifier 0 9 2342 19200300 100 1 44 */
491, /* OBJ_organizationalStatus 0 9 2342 19200300 100 1 45 */
492, /* OBJ_janetMailbox 0 9 2342 19200300 100 1 46 */
493, /* OBJ_mailPreferenceOption 0 9 2342 19200300 100 1 47 */
494, /* OBJ_buildingName 0 9 2342 19200300 100 1 48 */
495, /* OBJ_dSAQuality 0 9 2342 19200300 100 1 49 */
496, /* OBJ_singleLevelQuality 0 9 2342 19200300 100 1 50 */
497, /* OBJ_subtreeMinimumQuality 0 9 2342 19200300 100 1 51 */
498, /* OBJ_subtreeMaximumQuality 0 9 2342 19200300 100 1 52 */
499, /* OBJ_personalSignature 0 9 2342 19200300 100 1 53 */
500, /* OBJ_dITRedirect 0 9 2342 19200300 100 1 54 */
501, /* OBJ_audio 0 9 2342 19200300 100 1 55 */
502, /* OBJ_documentPublisher 0 9 2342 19200300 100 1 56 */
442, /* OBJ_iA5StringSyntax 0 9 2342 19200300 100 3 4 */
443, /* OBJ_caseIgnoreIA5StringSyntax 0 9 2342 19200300 100 3 5 */
444, /* OBJ_pilotObject 0 9 2342 19200300 100 4 3 */
445, /* OBJ_pilotPerson 0 9 2342 19200300 100 4 4 */
446, /* OBJ_account 0 9 2342 19200300 100 4 5 */
447, /* OBJ_document 0 9 2342 19200300 100 4 6 */
448, /* OBJ_room 0 9 2342 19200300 100 4 7 */
449, /* OBJ_documentSeries 0 9 2342 19200300 100 4 9 */
392, /* OBJ_Domain 0 9 2342 19200300 100 4 13 */
450, /* OBJ_rFC822localPart 0 9 2342 19200300 100 4 14 */
451, /* OBJ_dNSDomain 0 9 2342 19200300 100 4 15 */
452, /* OBJ_domainRelatedObject 0 9 2342 19200300 100 4 17 */
453, /* OBJ_friendlyCountry 0 9 2342 19200300 100 4 18 */
454, /* OBJ_simpleSecurityObject 0 9 2342 19200300 100 4 19 */
455, /* OBJ_pilotOrganization 0 9 2342 19200300 100 4 20 */
456, /* OBJ_pilotDSA 0 9 2342 19200300 100 4 21 */
457, /* OBJ_qualityLabelledData 0 9 2342 19200300 100 4 22 */
1152, /* OBJ_dstu28147 1 2 804 2 1 1 1 1 1 1 */
1156, /* OBJ_hmacWithDstu34311 1 2 804 2 1 1 1 1 1 2 */
1157, /* OBJ_dstu34311 1 2 804 2 1 1 1 1 2 1 */
189, /* OBJ_id_smime_mod 1 2 840 113549 1 9 16 0 */
190, /* OBJ_id_smime_ct 1 2 840 113549 1 9 16 1 */
191, /* OBJ_id_smime_aa 1 2 840 113549 1 9 16 2 */
192, /* OBJ_id_smime_alg 1 2 840 113549 1 9 16 3 */
193, /* OBJ_id_smime_cd 1 2 840 113549 1 9 16 4 */
194, /* OBJ_id_smime_spq 1 2 840 113549 1 9 16 5 */
195, /* OBJ_id_smime_cti 1 2 840 113549 1 9 16 6 */
158, /* OBJ_x509Certificate 1 2 840 113549 1 9 22 1 */
159, /* OBJ_sdsiCertificate 1 2 840 113549 1 9 22 2 */
160, /* OBJ_x509Crl 1 2 840 113549 1 9 23 1 */
144, /* OBJ_pbe_WithSHA1And128BitRC4 1 2 840 113549 1 12 1 1 */
145, /* OBJ_pbe_WithSHA1And40BitRC4 1 2 840 113549 1 12 1 2 */
146, /* OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC 1 2 840 113549 1 12 1 3 */
147, /* OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC 1 2 840 113549 1 12 1 4 */
148, /* OBJ_pbe_WithSHA1And128BitRC2_CBC 1 2 840 113549 1 12 1 5 */
149, /* OBJ_pbe_WithSHA1And40BitRC2_CBC 1 2 840 113549 1 12 1 6 */
171, /* OBJ_ms_ext_req 1 3 6 1 4 1 311 2 1 14 */
134, /* OBJ_ms_code_ind 1 3 6 1 4 1 311 2 1 21 */
135, /* OBJ_ms_code_com 1 3 6 1 4 1 311 2 1 22 */
136, /* OBJ_ms_ctl_sign 1 3 6 1 4 1 311 10 3 1 */
137, /* OBJ_ms_sgc 1 3 6 1 4 1 311 10 3 3 */
138, /* OBJ_ms_efs 1 3 6 1 4 1 311 10 3 4 */
648, /* OBJ_ms_smartcard_login 1 3 6 1 4 1 311 20 2 2 */
649, /* OBJ_ms_upn 1 3 6 1 4 1 311 20 2 3 */
951, /* OBJ_ct_precert_scts 1 3 6 1 4 1 11129 2 4 2 */
952, /* OBJ_ct_precert_poison 1 3 6 1 4 1 11129 2 4 3 */
953, /* OBJ_ct_precert_signer 1 3 6 1 4 1 11129 2 4 4 */
954, /* OBJ_ct_cert_scts 1 3 6 1 4 1 11129 2 4 5 */
751, /* OBJ_camellia_128_cbc 1 2 392 200011 61 1 1 1 2 */
752, /* OBJ_camellia_192_cbc 1 2 392 200011 61 1 1 1 3 */
753, /* OBJ_camellia_256_cbc 1 2 392 200011 61 1 1 1 4 */
907, /* OBJ_id_camellia128_wrap 1 2 392 200011 61 1 1 3 2 */
908, /* OBJ_id_camellia192_wrap 1 2 392 200011 61 1 1 3 3 */
909, /* OBJ_id_camellia256_wrap 1 2 392 200011 61 1 1 3 4 */
1153, /* OBJ_dstu28147_ofb 1 2 804 2 1 1 1 1 1 1 2 */
1154, /* OBJ_dstu28147_cfb 1 2 804 2 1 1 1 1 1 1 3 */
1155, /* OBJ_dstu28147_wrap 1 2 804 2 1 1 1 1 1 1 5 */
1158, /* OBJ_dstu4145le 1 2 804 2 1 1 1 1 3 1 1 */
196, /* OBJ_id_smime_mod_cms 1 2 840 113549 1 9 16 0 1 */
197, /* OBJ_id_smime_mod_ess 1 2 840 113549 1 9 16 0 2 */
198, /* OBJ_id_smime_mod_oid 1 2 840 113549 1 9 16 0 3 */
199, /* OBJ_id_smime_mod_msg_v3 1 2 840 113549 1 9 16 0 4 */
200, /* OBJ_id_smime_mod_ets_eSignature_88 1 2 840 113549 1 9 16 0 5 */
201, /* OBJ_id_smime_mod_ets_eSignature_97 1 2 840 113549 1 9 16 0 6 */
202, /* OBJ_id_smime_mod_ets_eSigPolicy_88 1 2 840 113549 1 9 16 0 7 */
203, /* OBJ_id_smime_mod_ets_eSigPolicy_97 1 2 840 113549 1 9 16 0 8 */
204, /* OBJ_id_smime_ct_receipt 1 2 840 113549 1 9 16 1 1 */
205, /* OBJ_id_smime_ct_authData 1 2 840 113549 1 9 16 1 2 */
206, /* OBJ_id_smime_ct_publishCert 1 2 840 113549 1 9 16 1 3 */
207, /* OBJ_id_smime_ct_TSTInfo 1 2 840 113549 1 9 16 1 4 */
208, /* OBJ_id_smime_ct_TDTInfo 1 2 840 113549 1 9 16 1 5 */
209, /* OBJ_id_smime_ct_contentInfo 1 2 840 113549 1 9 16 1 6 */
210, /* OBJ_id_smime_ct_DVCSRequestData 1 2 840 113549 1 9 16 1 7 */
211, /* OBJ_id_smime_ct_DVCSResponseData 1 2 840 113549 1 9 16 1 8 */
786, /* OBJ_id_smime_ct_compressedData 1 2 840 113549 1 9 16 1 9 */
1058, /* OBJ_id_smime_ct_contentCollection 1 2 840 113549 1 9 16 1 19 */
1059, /* OBJ_id_smime_ct_authEnvelopedData 1 2 840 113549 1 9 16 1 23 */
787, /* OBJ_id_ct_asciiTextWithCRLF 1 2 840 113549 1 9 16 1 27 */
1060, /* OBJ_id_ct_xml 1 2 840 113549 1 9 16 1 28 */
212, /* OBJ_id_smime_aa_receiptRequest 1 2 840 113549 1 9 16 2 1 */
213, /* OBJ_id_smime_aa_securityLabel 1 2 840 113549 1 9 16 2 2 */
214, /* OBJ_id_smime_aa_mlExpandHistory 1 2 840 113549 1 9 16 2 3 */
215, /* OBJ_id_smime_aa_contentHint 1 2 840 113549 1 9 16 2 4 */
216, /* OBJ_id_smime_aa_msgSigDigest 1 2 840 113549 1 9 16 2 5 */
217, /* OBJ_id_smime_aa_encapContentType 1 2 840 113549 1 9 16 2 6 */
218, /* OBJ_id_smime_aa_contentIdentifier 1 2 840 113549 1 9 16 2 7 */
219, /* OBJ_id_smime_aa_macValue 1 2 840 113549 1 9 16 2 8 */
220, /* OBJ_id_smime_aa_equivalentLabels 1 2 840 113549 1 9 16 2 9 */
221, /* OBJ_id_smime_aa_contentReference 1 2 840 113549 1 9 16 2 10 */
222, /* OBJ_id_smime_aa_encrypKeyPref 1 2 840 113549 1 9 16 2 11 */
223, /* OBJ_id_smime_aa_signingCertificate 1 2 840 113549 1 9 16 2 12 */
224, /* OBJ_id_smime_aa_smimeEncryptCerts 1 2 840 113549 1 9 16 2 13 */
225, /* OBJ_id_smime_aa_timeStampToken 1 2 840 113549 1 9 16 2 14 */
226, /* OBJ_id_smime_aa_ets_sigPolicyId 1 2 840 113549 1 9 16 2 15 */
227, /* OBJ_id_smime_aa_ets_commitmentType 1 2 840 113549 1 9 16 2 16 */
228, /* OBJ_id_smime_aa_ets_signerLocation 1 2 840 113549 1 9 16 2 17 */
229, /* OBJ_id_smime_aa_ets_signerAttr 1 2 840 113549 1 9 16 2 18 */
230, /* OBJ_id_smime_aa_ets_otherSigCert 1 2 840 113549 1 9 16 2 19 */
231, /* OBJ_id_smime_aa_ets_contentTimestamp 1 2 840 113549 1 9 16 2 20 */
232, /* OBJ_id_smime_aa_ets_CertificateRefs 1 2 840 113549 1 9 16 2 21 */
233, /* OBJ_id_smime_aa_ets_RevocationRefs 1 2 840 113549 1 9 16 2 22 */
234, /* OBJ_id_smime_aa_ets_certValues 1 2 840 113549 1 9 16 2 23 */
235, /* OBJ_id_smime_aa_ets_revocationValues 1 2 840 113549 1 9 16 2 24 */
236, /* OBJ_id_smime_aa_ets_escTimeStamp 1 2 840 113549 1 9 16 2 25 */
237, /* OBJ_id_smime_aa_ets_certCRLTimestamp 1 2 840 113549 1 9 16 2 26 */
238, /* OBJ_id_smime_aa_ets_archiveTimeStamp 1 2 840 113549 1 9 16 2 27 */
239, /* OBJ_id_smime_aa_signatureType 1 2 840 113549 1 9 16 2 28 */
240, /* OBJ_id_smime_aa_dvcs_dvc 1 2 840 113549 1 9 16 2 29 */
1086, /* OBJ_id_smime_aa_signingCertificateV2 1 2 840 113549 1 9 16 2 47 */
241, /* OBJ_id_smime_alg_ESDHwith3DES 1 2 840 113549 1 9 16 3 1 */
242, /* OBJ_id_smime_alg_ESDHwithRC2 1 2 840 113549 1 9 16 3 2 */
243, /* OBJ_id_smime_alg_3DESwrap 1 2 840 113549 1 9 16 3 3 */
244, /* OBJ_id_smime_alg_RC2wrap 1 2 840 113549 1 9 16 3 4 */
245, /* OBJ_id_smime_alg_ESDH 1 2 840 113549 1 9 16 3 5 */
246, /* OBJ_id_smime_alg_CMS3DESwrap 1 2 840 113549 1 9 16 3 6 */
247, /* OBJ_id_smime_alg_CMSRC2wrap 1 2 840 113549 1 9 16 3 7 */
125, /* OBJ_zlib_compression 1 2 840 113549 1 9 16 3 8 */
893, /* OBJ_id_alg_PWRI_KEK 1 2 840 113549 1 9 16 3 9 */
248, /* OBJ_id_smime_cd_ldap 1 2 840 113549 1 9 16 4 1 */
249, /* OBJ_id_smime_spq_ets_sqt_uri 1 2 840 113549 1 9 16 5 1 */
250, /* OBJ_id_smime_spq_ets_sqt_unotice 1 2 840 113549 1 9 16 5 2 */
251, /* OBJ_id_smime_cti_ets_proofOfOrigin 1 2 840 113549 1 9 16 6 1 */
252, /* OBJ_id_smime_cti_ets_proofOfReceipt 1 2 840 113549 1 9 16 6 2 */
253, /* OBJ_id_smime_cti_ets_proofOfDelivery 1 2 840 113549 1 9 16 6 3 */
254, /* OBJ_id_smime_cti_ets_proofOfSender 1 2 840 113549 1 9 16 6 4 */
255, /* OBJ_id_smime_cti_ets_proofOfApproval 1 2 840 113549 1 9 16 6 5 */
256, /* OBJ_id_smime_cti_ets_proofOfCreation 1 2 840 113549 1 9 16 6 6 */
150, /* OBJ_keyBag 1 2 840 113549 1 12 10 1 1 */
151, /* OBJ_pkcs8ShroudedKeyBag 1 2 840 113549 1 12 10 1 2 */
152, /* OBJ_certBag 1 2 840 113549 1 12 10 1 3 */
153, /* OBJ_crlBag 1 2 840 113549 1 12 10 1 4 */
154, /* OBJ_secretBag 1 2 840 113549 1 12 10 1 5 */
155, /* OBJ_safeContentsBag 1 2 840 113549 1 12 10 1 6 */
34, /* OBJ_idea_cbc 1 3 6 1 4 1 188 7 1 1 2 */
955, /* OBJ_jurisdictionLocalityName 1 3 6 1 4 1 311 60 2 1 1 */
956, /* OBJ_jurisdictionStateOrProvinceName 1 3 6 1 4 1 311 60 2 1 2 */
957, /* OBJ_jurisdictionCountryName 1 3 6 1 4 1 311 60 2 1 3 */
1056, /* OBJ_blake2b512 1 3 6 1 4 1 1722 12 2 1 16 */
1057, /* OBJ_blake2s256 1 3 6 1 4 1 1722 12 2 2 8 */
1159, /* OBJ_dstu4145be 1 2 804 2 1 1 1 1 3 1 1 1 1 */
1160, /* OBJ_uacurve0 1 2 804 2 1 1 1 1 3 1 1 2 0 */
1161, /* OBJ_uacurve1 1 2 804 2 1 1 1 1 3 1 1 2 1 */
1162, /* OBJ_uacurve2 1 2 804 2 1 1 1 1 3 1 1 2 2 */
1163, /* OBJ_uacurve3 1 2 804 2 1 1 1 1 3 1 1 2 3 */
1164, /* OBJ_uacurve4 1 2 804 2 1 1 1 1 3 1 1 2 4 */
1165, /* OBJ_uacurve5 1 2 804 2 1 1 1 1 3 1 1 2 5 */
1166, /* OBJ_uacurve6 1 2 804 2 1 1 1 1 3 1 1 2 6 */
1167, /* OBJ_uacurve7 1 2 804 2 1 1 1 1 3 1 1 2 7 */
1168, /* OBJ_uacurve8 1 2 804 2 1 1 1 1 3 1 1 2 8 */
1169, /* OBJ_uacurve9 1 2 804 2 1 1 1 1 3 1 1 2 9 */
};
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
index 6dbc41ce3727..5b2bb54eb929 100644
--- a/crypto/objects/objects.txt
+++ b/crypto/objects/objects.txt
@@ -1,1677 +1,1677 @@
# CCITT was renamed to ITU-T quite some time ago
0 : ITU-T : itu-t
!Alias ccitt itu-t
1 : ISO : iso
2 : JOINT-ISO-ITU-T : joint-iso-itu-t
!Alias joint-iso-ccitt joint-iso-itu-t
iso 2 : member-body : ISO Member Body
iso 3 : identified-organization
# HMAC OIDs
identified-organization 6 1 5 5 8 1 1 : HMAC-MD5 : hmac-md5
identified-organization 6 1 5 5 8 1 2 : HMAC-SHA1 : hmac-sha1
# "1.3.36.8.3.3"
identified-organization 36 8 3 3 : x509ExtAdmission : Professional Information or basis for Admission
identified-organization 132 : certicom-arc
identified-organization 111 : ieee
ieee 2 1619 : ieee-siswg : IEEE Security in Storage Working Group
joint-iso-itu-t 23 : international-organizations : International Organizations
international-organizations 43 : wap
wap 1 : wap-wsg
joint-iso-itu-t 5 1 5 : selected-attribute-types : Selected Attribute Types
selected-attribute-types 55 : clearance
member-body 840 : ISO-US : ISO US Member Body
ISO-US 10040 : X9-57 : X9.57
X9-57 4 : X9cm : X9.57 CM ?
member-body 156 : ISO-CN : ISO CN Member Body
ISO-CN 10197 : oscca
oscca 1 : sm-scheme
!Cname dsa
X9cm 1 : DSA : dsaEncryption
X9cm 3 : DSA-SHA1 : dsaWithSHA1
ISO-US 10045 : ansi-X9-62 : ANSI X9.62
!module X9-62
!Alias id-fieldType ansi-X9-62 1
X9-62_id-fieldType 1 : prime-field
X9-62_id-fieldType 2 : characteristic-two-field
X9-62_characteristic-two-field 3 : id-characteristic-two-basis
X9-62_id-characteristic-two-basis 1 : onBasis
X9-62_id-characteristic-two-basis 2 : tpBasis
X9-62_id-characteristic-two-basis 3 : ppBasis
!Alias id-publicKeyType ansi-X9-62 2
X9-62_id-publicKeyType 1 : id-ecPublicKey
!Alias ellipticCurve ansi-X9-62 3
!Alias c-TwoCurve X9-62_ellipticCurve 0
X9-62_c-TwoCurve 1 : c2pnb163v1
X9-62_c-TwoCurve 2 : c2pnb163v2
X9-62_c-TwoCurve 3 : c2pnb163v3
X9-62_c-TwoCurve 4 : c2pnb176v1
X9-62_c-TwoCurve 5 : c2tnb191v1
X9-62_c-TwoCurve 6 : c2tnb191v2
X9-62_c-TwoCurve 7 : c2tnb191v3
X9-62_c-TwoCurve 8 : c2onb191v4
X9-62_c-TwoCurve 9 : c2onb191v5
X9-62_c-TwoCurve 10 : c2pnb208w1
X9-62_c-TwoCurve 11 : c2tnb239v1
X9-62_c-TwoCurve 12 : c2tnb239v2
X9-62_c-TwoCurve 13 : c2tnb239v3
X9-62_c-TwoCurve 14 : c2onb239v4
X9-62_c-TwoCurve 15 : c2onb239v5
X9-62_c-TwoCurve 16 : c2pnb272w1
X9-62_c-TwoCurve 17 : c2pnb304w1
X9-62_c-TwoCurve 18 : c2tnb359v1
X9-62_c-TwoCurve 19 : c2pnb368w1
X9-62_c-TwoCurve 20 : c2tnb431r1
!Alias primeCurve X9-62_ellipticCurve 1
X9-62_primeCurve 1 : prime192v1
X9-62_primeCurve 2 : prime192v2
X9-62_primeCurve 3 : prime192v3
X9-62_primeCurve 4 : prime239v1
X9-62_primeCurve 5 : prime239v2
X9-62_primeCurve 6 : prime239v3
X9-62_primeCurve 7 : prime256v1
!Alias id-ecSigType ansi-X9-62 4
!global
X9-62_id-ecSigType 1 : ecdsa-with-SHA1
X9-62_id-ecSigType 2 : ecdsa-with-Recommended
X9-62_id-ecSigType 3 : ecdsa-with-Specified
ecdsa-with-Specified 1 : ecdsa-with-SHA224
ecdsa-with-Specified 2 : ecdsa-with-SHA256
ecdsa-with-Specified 3 : ecdsa-with-SHA384
ecdsa-with-Specified 4 : ecdsa-with-SHA512
# SECG curve OIDs from "SEC 2: Recommended Elliptic Curve Domain Parameters"
# (http://www.secg.org/)
!Alias secg_ellipticCurve certicom-arc 0
# SECG prime curves OIDs
secg-ellipticCurve 6 : secp112r1
secg-ellipticCurve 7 : secp112r2
secg-ellipticCurve 28 : secp128r1
secg-ellipticCurve 29 : secp128r2
secg-ellipticCurve 9 : secp160k1
secg-ellipticCurve 8 : secp160r1
secg-ellipticCurve 30 : secp160r2
secg-ellipticCurve 31 : secp192k1
# NOTE: the curve secp192r1 is the same as prime192v1 defined above
# and is therefore omitted
secg-ellipticCurve 32 : secp224k1
secg-ellipticCurve 33 : secp224r1
secg-ellipticCurve 10 : secp256k1
# NOTE: the curve secp256r1 is the same as prime256v1 defined above
# and is therefore omitted
secg-ellipticCurve 34 : secp384r1
secg-ellipticCurve 35 : secp521r1
# SECG characteristic two curves OIDs
secg-ellipticCurve 4 : sect113r1
secg-ellipticCurve 5 : sect113r2
secg-ellipticCurve 22 : sect131r1
secg-ellipticCurve 23 : sect131r2
secg-ellipticCurve 1 : sect163k1
secg-ellipticCurve 2 : sect163r1
secg-ellipticCurve 15 : sect163r2
secg-ellipticCurve 24 : sect193r1
secg-ellipticCurve 25 : sect193r2
secg-ellipticCurve 26 : sect233k1
secg-ellipticCurve 27 : sect233r1
secg-ellipticCurve 3 : sect239k1
secg-ellipticCurve 16 : sect283k1
secg-ellipticCurve 17 : sect283r1
secg-ellipticCurve 36 : sect409k1
secg-ellipticCurve 37 : sect409r1
secg-ellipticCurve 38 : sect571k1
secg-ellipticCurve 39 : sect571r1
# WAP/TLS curve OIDs (http://www.wapforum.org/)
!Alias wap-wsg-idm-ecid wap-wsg 4
wap-wsg-idm-ecid 1 : wap-wsg-idm-ecid-wtls1
wap-wsg-idm-ecid 3 : wap-wsg-idm-ecid-wtls3
wap-wsg-idm-ecid 4 : wap-wsg-idm-ecid-wtls4
wap-wsg-idm-ecid 5 : wap-wsg-idm-ecid-wtls5
wap-wsg-idm-ecid 6 : wap-wsg-idm-ecid-wtls6
wap-wsg-idm-ecid 7 : wap-wsg-idm-ecid-wtls7
wap-wsg-idm-ecid 8 : wap-wsg-idm-ecid-wtls8
wap-wsg-idm-ecid 9 : wap-wsg-idm-ecid-wtls9
wap-wsg-idm-ecid 10 : wap-wsg-idm-ecid-wtls10
wap-wsg-idm-ecid 11 : wap-wsg-idm-ecid-wtls11
wap-wsg-idm-ecid 12 : wap-wsg-idm-ecid-wtls12
ISO-US 113533 7 66 10 : CAST5-CBC : cast5-cbc
: CAST5-ECB : cast5-ecb
!Cname cast5-cfb64
: CAST5-CFB : cast5-cfb
!Cname cast5-ofb64
: CAST5-OFB : cast5-ofb
!Cname pbeWithMD5AndCast5-CBC
ISO-US 113533 7 66 12 : : pbeWithMD5AndCast5CBC
# Macs for CMP and CRMF
ISO-US 113533 7 66 13 : id-PasswordBasedMAC : password based MAC
ISO-US 113533 7 66 30 : id-DHBasedMac : Diffie-Hellman based MAC
ISO-US 113549 : rsadsi : RSA Data Security, Inc.
rsadsi 1 : pkcs : RSA Data Security, Inc. PKCS
pkcs 1 : pkcs1
pkcs1 1 : : rsaEncryption
pkcs1 2 : RSA-MD2 : md2WithRSAEncryption
pkcs1 3 : RSA-MD4 : md4WithRSAEncryption
pkcs1 4 : RSA-MD5 : md5WithRSAEncryption
pkcs1 5 : RSA-SHA1 : sha1WithRSAEncryption
# According to PKCS #1 version 2.1
pkcs1 7 : RSAES-OAEP : rsaesOaep
pkcs1 8 : MGF1 : mgf1
pkcs1 9 : PSPECIFIED : pSpecified
pkcs1 10 : RSASSA-PSS : rsassaPss
pkcs1 11 : RSA-SHA256 : sha256WithRSAEncryption
pkcs1 12 : RSA-SHA384 : sha384WithRSAEncryption
pkcs1 13 : RSA-SHA512 : sha512WithRSAEncryption
pkcs1 14 : RSA-SHA224 : sha224WithRSAEncryption
pkcs1 15 : RSA-SHA512/224 : sha512-224WithRSAEncryption
pkcs1 16 : RSA-SHA512/256 : sha512-256WithRSAEncryption
pkcs 3 : pkcs3
pkcs3 1 : : dhKeyAgreement
pkcs 5 : pkcs5
pkcs5 1 : PBE-MD2-DES : pbeWithMD2AndDES-CBC
pkcs5 3 : PBE-MD5-DES : pbeWithMD5AndDES-CBC
pkcs5 4 : PBE-MD2-RC2-64 : pbeWithMD2AndRC2-CBC
pkcs5 6 : PBE-MD5-RC2-64 : pbeWithMD5AndRC2-CBC
pkcs5 10 : PBE-SHA1-DES : pbeWithSHA1AndDES-CBC
pkcs5 11 : PBE-SHA1-RC2-64 : pbeWithSHA1AndRC2-CBC
!Cname id_pbkdf2
pkcs5 12 : : PBKDF2
!Cname pbes2
pkcs5 13 : : PBES2
!Cname pbmac1
pkcs5 14 : : PBMAC1
pkcs 7 : pkcs7
pkcs7 1 : : pkcs7-data
!Cname pkcs7-signed
pkcs7 2 : : pkcs7-signedData
!Cname pkcs7-enveloped
pkcs7 3 : : pkcs7-envelopedData
!Cname pkcs7-signedAndEnveloped
pkcs7 4 : : pkcs7-signedAndEnvelopedData
!Cname pkcs7-digest
pkcs7 5 : : pkcs7-digestData
!Cname pkcs7-encrypted
pkcs7 6 : : pkcs7-encryptedData
pkcs 9 : pkcs9
!module pkcs9
pkcs9 1 : : emailAddress
pkcs9 2 : : unstructuredName
pkcs9 3 : : contentType
pkcs9 4 : : messageDigest
pkcs9 5 : : signingTime
pkcs9 6 : : countersignature
pkcs9 7 : : challengePassword
pkcs9 8 : : unstructuredAddress
!Cname extCertAttributes
pkcs9 9 : : extendedCertificateAttributes
!global
!Cname ext-req
pkcs9 14 : extReq : Extension Request
!Cname SMIMECapabilities
pkcs9 15 : SMIME-CAPS : S/MIME Capabilities
# S/MIME
!Cname SMIME
pkcs9 16 : SMIME : S/MIME
SMIME 0 : id-smime-mod
SMIME 1 : id-smime-ct
SMIME 2 : id-smime-aa
SMIME 3 : id-smime-alg
SMIME 4 : id-smime-cd
SMIME 5 : id-smime-spq
SMIME 6 : id-smime-cti
# S/MIME Modules
id-smime-mod 1 : id-smime-mod-cms
id-smime-mod 2 : id-smime-mod-ess
id-smime-mod 3 : id-smime-mod-oid
id-smime-mod 4 : id-smime-mod-msg-v3
id-smime-mod 5 : id-smime-mod-ets-eSignature-88
id-smime-mod 6 : id-smime-mod-ets-eSignature-97
id-smime-mod 7 : id-smime-mod-ets-eSigPolicy-88
id-smime-mod 8 : id-smime-mod-ets-eSigPolicy-97
# S/MIME Content Types
id-smime-ct 1 : id-smime-ct-receipt
id-smime-ct 2 : id-smime-ct-authData
id-smime-ct 3 : id-smime-ct-publishCert
id-smime-ct 4 : id-smime-ct-TSTInfo
id-smime-ct 5 : id-smime-ct-TDTInfo
id-smime-ct 6 : id-smime-ct-contentInfo
id-smime-ct 7 : id-smime-ct-DVCSRequestData
id-smime-ct 8 : id-smime-ct-DVCSResponseData
id-smime-ct 9 : id-smime-ct-compressedData
id-smime-ct 19 : id-smime-ct-contentCollection
id-smime-ct 23 : id-smime-ct-authEnvelopedData
id-smime-ct 27 : id-ct-asciiTextWithCRLF
id-smime-ct 28 : id-ct-xml
# S/MIME Attributes
id-smime-aa 1 : id-smime-aa-receiptRequest
id-smime-aa 2 : id-smime-aa-securityLabel
id-smime-aa 3 : id-smime-aa-mlExpandHistory
id-smime-aa 4 : id-smime-aa-contentHint
id-smime-aa 5 : id-smime-aa-msgSigDigest
# obsolete
id-smime-aa 6 : id-smime-aa-encapContentType
id-smime-aa 7 : id-smime-aa-contentIdentifier
# obsolete
id-smime-aa 8 : id-smime-aa-macValue
id-smime-aa 9 : id-smime-aa-equivalentLabels
id-smime-aa 10 : id-smime-aa-contentReference
id-smime-aa 11 : id-smime-aa-encrypKeyPref
id-smime-aa 12 : id-smime-aa-signingCertificate
id-smime-aa 13 : id-smime-aa-smimeEncryptCerts
id-smime-aa 14 : id-smime-aa-timeStampToken
id-smime-aa 15 : id-smime-aa-ets-sigPolicyId
id-smime-aa 16 : id-smime-aa-ets-commitmentType
id-smime-aa 17 : id-smime-aa-ets-signerLocation
id-smime-aa 18 : id-smime-aa-ets-signerAttr
id-smime-aa 19 : id-smime-aa-ets-otherSigCert
id-smime-aa 20 : id-smime-aa-ets-contentTimestamp
id-smime-aa 21 : id-smime-aa-ets-CertificateRefs
id-smime-aa 22 : id-smime-aa-ets-RevocationRefs
id-smime-aa 23 : id-smime-aa-ets-certValues
id-smime-aa 24 : id-smime-aa-ets-revocationValues
id-smime-aa 25 : id-smime-aa-ets-escTimeStamp
id-smime-aa 26 : id-smime-aa-ets-certCRLTimestamp
id-smime-aa 27 : id-smime-aa-ets-archiveTimeStamp
id-smime-aa 28 : id-smime-aa-signatureType
id-smime-aa 29 : id-smime-aa-dvcs-dvc
id-smime-aa 47 : id-smime-aa-signingCertificateV2
# S/MIME Algorithm Identifiers
# obsolete
id-smime-alg 1 : id-smime-alg-ESDHwith3DES
# obsolete
id-smime-alg 2 : id-smime-alg-ESDHwithRC2
# obsolete
id-smime-alg 3 : id-smime-alg-3DESwrap
# obsolete
id-smime-alg 4 : id-smime-alg-RC2wrap
id-smime-alg 5 : id-smime-alg-ESDH
id-smime-alg 6 : id-smime-alg-CMS3DESwrap
id-smime-alg 7 : id-smime-alg-CMSRC2wrap
id-smime-alg 9 : id-alg-PWRI-KEK
# S/MIME Certificate Distribution
id-smime-cd 1 : id-smime-cd-ldap
# S/MIME Signature Policy Qualifier
id-smime-spq 1 : id-smime-spq-ets-sqt-uri
id-smime-spq 2 : id-smime-spq-ets-sqt-unotice
# S/MIME Commitment Type Identifier
id-smime-cti 1 : id-smime-cti-ets-proofOfOrigin
id-smime-cti 2 : id-smime-cti-ets-proofOfReceipt
id-smime-cti 3 : id-smime-cti-ets-proofOfDelivery
id-smime-cti 4 : id-smime-cti-ets-proofOfSender
id-smime-cti 5 : id-smime-cti-ets-proofOfApproval
id-smime-cti 6 : id-smime-cti-ets-proofOfCreation
pkcs9 20 : : friendlyName
pkcs9 21 : : localKeyID
!Cname ms-csp-name
1 3 6 1 4 1 311 17 1 : CSPName : Microsoft CSP Name
1 3 6 1 4 1 311 17 2 : LocalKeySet : Microsoft Local Key set
!Alias certTypes pkcs9 22
certTypes 1 : : x509Certificate
certTypes 2 : : sdsiCertificate
!Alias crlTypes pkcs9 23
crlTypes 1 : : x509Crl
!Alias pkcs12 pkcs 12
!Alias pkcs12-pbeids pkcs12 1
!Cname pbe-WithSHA1And128BitRC4
pkcs12-pbeids 1 : PBE-SHA1-RC4-128 : pbeWithSHA1And128BitRC4
!Cname pbe-WithSHA1And40BitRC4
pkcs12-pbeids 2 : PBE-SHA1-RC4-40 : pbeWithSHA1And40BitRC4
!Cname pbe-WithSHA1And3_Key_TripleDES-CBC
pkcs12-pbeids 3 : PBE-SHA1-3DES : pbeWithSHA1And3-KeyTripleDES-CBC
!Cname pbe-WithSHA1And2_Key_TripleDES-CBC
pkcs12-pbeids 4 : PBE-SHA1-2DES : pbeWithSHA1And2-KeyTripleDES-CBC
!Cname pbe-WithSHA1And128BitRC2-CBC
pkcs12-pbeids 5 : PBE-SHA1-RC2-128 : pbeWithSHA1And128BitRC2-CBC
!Cname pbe-WithSHA1And40BitRC2-CBC
pkcs12-pbeids 6 : PBE-SHA1-RC2-40 : pbeWithSHA1And40BitRC2-CBC
!Alias pkcs12-Version1 pkcs12 10
!Alias pkcs12-BagIds pkcs12-Version1 1
pkcs12-BagIds 1 : : keyBag
pkcs12-BagIds 2 : : pkcs8ShroudedKeyBag
pkcs12-BagIds 3 : : certBag
pkcs12-BagIds 4 : : crlBag
pkcs12-BagIds 5 : : secretBag
pkcs12-BagIds 6 : : safeContentsBag
rsadsi 2 2 : MD2 : md2
rsadsi 2 4 : MD4 : md4
rsadsi 2 5 : MD5 : md5
: MD5-SHA1 : md5-sha1
rsadsi 2 6 : : hmacWithMD5
rsadsi 2 7 : : hmacWithSHA1
sm-scheme 301 : SM2 : sm2
sm-scheme 401 : SM3 : sm3
sm-scheme 504 : RSA-SM3 : sm3WithRSAEncryption
# From RFC4231
rsadsi 2 8 : : hmacWithSHA224
rsadsi 2 9 : : hmacWithSHA256
rsadsi 2 10 : : hmacWithSHA384
rsadsi 2 11 : : hmacWithSHA512
# From RFC8018
rsadsi 2 12 : : hmacWithSHA512-224
rsadsi 2 13 : : hmacWithSHA512-256
rsadsi 3 2 : RC2-CBC : rc2-cbc
: RC2-ECB : rc2-ecb
!Cname rc2-cfb64
: RC2-CFB : rc2-cfb
!Cname rc2-ofb64
: RC2-OFB : rc2-ofb
: RC2-40-CBC : rc2-40-cbc
: RC2-64-CBC : rc2-64-cbc
rsadsi 3 4 : RC4 : rc4
: RC4-40 : rc4-40
rsadsi 3 7 : DES-EDE3-CBC : des-ede3-cbc
rsadsi 3 8 : RC5-CBC : rc5-cbc
: RC5-ECB : rc5-ecb
!Cname rc5-cfb64
: RC5-CFB : rc5-cfb
!Cname rc5-ofb64
: RC5-OFB : rc5-ofb
!Cname ms-ext-req
1 3 6 1 4 1 311 2 1 14 : msExtReq : Microsoft Extension Request
!Cname ms-code-ind
1 3 6 1 4 1 311 2 1 21 : msCodeInd : Microsoft Individual Code Signing
!Cname ms-code-com
1 3 6 1 4 1 311 2 1 22 : msCodeCom : Microsoft Commercial Code Signing
!Cname ms-ctl-sign
1 3 6 1 4 1 311 10 3 1 : msCTLSign : Microsoft Trust List Signing
!Cname ms-sgc
1 3 6 1 4 1 311 10 3 3 : msSGC : Microsoft Server Gated Crypto
!Cname ms-efs
1 3 6 1 4 1 311 10 3 4 : msEFS : Microsoft Encrypted File System
!Cname ms-smartcard-login
1 3 6 1 4 1 311 20 2 2 : msSmartcardLogin : Microsoft Smartcardlogin
!Cname ms-upn
1 3 6 1 4 1 311 20 2 3 : msUPN : Microsoft Universal Principal Name
1 3 6 1 4 1 188 7 1 1 2 : IDEA-CBC : idea-cbc
: IDEA-ECB : idea-ecb
!Cname idea-cfb64
: IDEA-CFB : idea-cfb
!Cname idea-ofb64
: IDEA-OFB : idea-ofb
1 3 6 1 4 1 3029 1 2 : BF-CBC : bf-cbc
: BF-ECB : bf-ecb
!Cname bf-cfb64
: BF-CFB : bf-cfb
!Cname bf-ofb64
: BF-OFB : bf-ofb
!Cname id-pkix
1 3 6 1 5 5 7 : PKIX
# PKIX Arcs
id-pkix 0 : id-pkix-mod
id-pkix 1 : id-pe
id-pkix 2 : id-qt
id-pkix 3 : id-kp
id-pkix 4 : id-it
id-pkix 5 : id-pkip
id-pkix 6 : id-alg
id-pkix 7 : id-cmc
id-pkix 8 : id-on
id-pkix 9 : id-pda
id-pkix 10 : id-aca
id-pkix 11 : id-qcs
id-pkix 12 : id-cct
id-pkix 21 : id-ppl
id-pkix 48 : id-ad
# PKIX Modules
id-pkix-mod 1 : id-pkix1-explicit-88
id-pkix-mod 2 : id-pkix1-implicit-88
id-pkix-mod 3 : id-pkix1-explicit-93
id-pkix-mod 4 : id-pkix1-implicit-93
id-pkix-mod 5 : id-mod-crmf
id-pkix-mod 6 : id-mod-cmc
id-pkix-mod 7 : id-mod-kea-profile-88
id-pkix-mod 8 : id-mod-kea-profile-93
id-pkix-mod 9 : id-mod-cmp
id-pkix-mod 10 : id-mod-qualified-cert-88
id-pkix-mod 11 : id-mod-qualified-cert-93
id-pkix-mod 12 : id-mod-attribute-cert
id-pkix-mod 13 : id-mod-timestamp-protocol
id-pkix-mod 14 : id-mod-ocsp
id-pkix-mod 15 : id-mod-dvcs
id-pkix-mod 16 : id-mod-cmp2000
# PKIX Private Extensions
!Cname info-access
id-pe 1 : authorityInfoAccess : Authority Information Access
id-pe 2 : biometricInfo : Biometric Info
id-pe 3 : qcStatements
id-pe 4 : ac-auditEntity
id-pe 5 : ac-targeting
id-pe 6 : aaControls
id-pe 7 : sbgp-ipAddrBlock
id-pe 8 : sbgp-autonomousSysNum
id-pe 9 : sbgp-routerIdentifier
id-pe 10 : ac-proxying
!Cname sinfo-access
id-pe 11 : subjectInfoAccess : Subject Information Access
id-pe 14 : proxyCertInfo : Proxy Certificate Information
id-pe 24 : tlsfeature : TLS Feature
# PKIX policyQualifiers for Internet policy qualifiers
id-qt 1 : id-qt-cps : Policy Qualifier CPS
id-qt 2 : id-qt-unotice : Policy Qualifier User Notice
id-qt 3 : textNotice
# PKIX key purpose identifiers
!Cname server-auth
id-kp 1 : serverAuth : TLS Web Server Authentication
!Cname client-auth
id-kp 2 : clientAuth : TLS Web Client Authentication
!Cname code-sign
id-kp 3 : codeSigning : Code Signing
!Cname email-protect
id-kp 4 : emailProtection : E-mail Protection
id-kp 5 : ipsecEndSystem : IPSec End System
id-kp 6 : ipsecTunnel : IPSec Tunnel
id-kp 7 : ipsecUser : IPSec User
!Cname time-stamp
id-kp 8 : timeStamping : Time Stamping
# From OCSP spec RFC2560
!Cname OCSP-sign
id-kp 9 : OCSPSigning : OCSP Signing
id-kp 10 : DVCS : dvcs
!Cname ipsec-IKE
id-kp 17 : ipsecIKE : ipsec Internet Key Exchange
id-kp 18 : capwapAC : Ctrl/provision WAP Access
id-kp 19 : capwapWTP : Ctrl/Provision WAP Termination
!Cname sshClient
id-kp 21 : secureShellClient : SSH Client
!Cname sshServer
id-kp 22 : secureShellServer : SSH Server
id-kp 23 : sendRouter : Send Router
id-kp 24 : sendProxiedRouter : Send Proxied Router
id-kp 25 : sendOwner : Send Owner
id-kp 26 : sendProxiedOwner : Send Proxied Owner
id-kp 27 : cmcCA : CMC Certificate Authority
id-kp 28 : cmcRA : CMC Registration Authority
# CMP information types
id-it 1 : id-it-caProtEncCert
id-it 2 : id-it-signKeyPairTypes
id-it 3 : id-it-encKeyPairTypes
id-it 4 : id-it-preferredSymmAlg
id-it 5 : id-it-caKeyUpdateInfo
id-it 6 : id-it-currentCRL
id-it 7 : id-it-unsupportedOIDs
# obsolete
id-it 8 : id-it-subscriptionRequest
# obsolete
id-it 9 : id-it-subscriptionResponse
id-it 10 : id-it-keyPairParamReq
id-it 11 : id-it-keyPairParamRep
id-it 12 : id-it-revPassphrase
id-it 13 : id-it-implicitConfirm
id-it 14 : id-it-confirmWaitTime
id-it 15 : id-it-origPKIMessage
id-it 16 : id-it-suppLangTags
# CRMF registration
id-pkip 1 : id-regCtrl
id-pkip 2 : id-regInfo
# CRMF registration controls
id-regCtrl 1 : id-regCtrl-regToken
id-regCtrl 2 : id-regCtrl-authenticator
id-regCtrl 3 : id-regCtrl-pkiPublicationInfo
id-regCtrl 4 : id-regCtrl-pkiArchiveOptions
id-regCtrl 5 : id-regCtrl-oldCertID
id-regCtrl 6 : id-regCtrl-protocolEncrKey
# CRMF registration information
id-regInfo 1 : id-regInfo-utf8Pairs
id-regInfo 2 : id-regInfo-certReq
# algorithms
id-alg 1 : id-alg-des40
id-alg 2 : id-alg-noSignature
id-alg 3 : id-alg-dh-sig-hmac-sha1
id-alg 4 : id-alg-dh-pop
# CMC controls
id-cmc 1 : id-cmc-statusInfo
id-cmc 2 : id-cmc-identification
id-cmc 3 : id-cmc-identityProof
id-cmc 4 : id-cmc-dataReturn
id-cmc 5 : id-cmc-transactionId
id-cmc 6 : id-cmc-senderNonce
id-cmc 7 : id-cmc-recipientNonce
id-cmc 8 : id-cmc-addExtensions
id-cmc 9 : id-cmc-encryptedPOP
id-cmc 10 : id-cmc-decryptedPOP
id-cmc 11 : id-cmc-lraPOPWitness
id-cmc 15 : id-cmc-getCert
id-cmc 16 : id-cmc-getCRL
id-cmc 17 : id-cmc-revokeRequest
id-cmc 18 : id-cmc-regInfo
id-cmc 19 : id-cmc-responseInfo
id-cmc 21 : id-cmc-queryPending
id-cmc 22 : id-cmc-popLinkRandom
id-cmc 23 : id-cmc-popLinkWitness
id-cmc 24 : id-cmc-confirmCertAcceptance
# other names
id-on 1 : id-on-personalData
id-on 3 : id-on-permanentIdentifier : Permanent Identifier
# personal data attributes
id-pda 1 : id-pda-dateOfBirth
id-pda 2 : id-pda-placeOfBirth
id-pda 3 : id-pda-gender
id-pda 4 : id-pda-countryOfCitizenship
id-pda 5 : id-pda-countryOfResidence
# attribute certificate attributes
id-aca 1 : id-aca-authenticationInfo
id-aca 2 : id-aca-accessIdentity
id-aca 3 : id-aca-chargingIdentity
id-aca 4 : id-aca-group
# attention : the following seems to be obsolete, replace by 'role'
id-aca 5 : id-aca-role
id-aca 6 : id-aca-encAttrs
# qualified certificate statements
id-qcs 1 : id-qcs-pkixQCSyntax-v1
# CMC content types
id-cct 1 : id-cct-crs
id-cct 2 : id-cct-PKIData
id-cct 3 : id-cct-PKIResponse
# Predefined Proxy Certificate policy languages
id-ppl 0 : id-ppl-anyLanguage : Any language
id-ppl 1 : id-ppl-inheritAll : Inherit all
id-ppl 2 : id-ppl-independent : Independent
# access descriptors for authority info access extension
!Cname ad-OCSP
id-ad 1 : OCSP : OCSP
!Cname ad-ca-issuers
id-ad 2 : caIssuers : CA Issuers
!Cname ad-timeStamping
id-ad 3 : ad_timestamping : AD Time Stamping
!Cname ad-dvcs
id-ad 4 : AD_DVCS : ad dvcs
id-ad 5 : caRepository : CA Repository
!Alias id-pkix-OCSP ad-OCSP
!module id-pkix-OCSP
!Cname basic
id-pkix-OCSP 1 : basicOCSPResponse : Basic OCSP Response
id-pkix-OCSP 2 : Nonce : OCSP Nonce
id-pkix-OCSP 3 : CrlID : OCSP CRL ID
id-pkix-OCSP 4 : acceptableResponses : Acceptable OCSP Responses
id-pkix-OCSP 5 : noCheck : OCSP No Check
id-pkix-OCSP 6 : archiveCutoff : OCSP Archive Cutoff
id-pkix-OCSP 7 : serviceLocator : OCSP Service Locator
id-pkix-OCSP 8 : extendedStatus : Extended OCSP Status
id-pkix-OCSP 9 : valid
id-pkix-OCSP 10 : path
id-pkix-OCSP 11 : trustRoot : Trust Root
!global
1 3 14 3 2 : algorithm : algorithm
algorithm 3 : RSA-NP-MD5 : md5WithRSA
algorithm 6 : DES-ECB : des-ecb
algorithm 7 : DES-CBC : des-cbc
!Cname des-ofb64
algorithm 8 : DES-OFB : des-ofb
!Cname des-cfb64
algorithm 9 : DES-CFB : des-cfb
algorithm 11 : rsaSignature
!Cname dsa-2
algorithm 12 : DSA-old : dsaEncryption-old
algorithm 13 : DSA-SHA : dsaWithSHA
algorithm 15 : RSA-SHA : shaWithRSAEncryption
!Cname des-ede-ecb
algorithm 17 : DES-EDE : des-ede
!Cname des-ede3-ecb
: DES-EDE3 : des-ede3
: DES-EDE-CBC : des-ede-cbc
!Cname des-ede-cfb64
: DES-EDE-CFB : des-ede-cfb
!Cname des-ede3-cfb64
: DES-EDE3-CFB : des-ede3-cfb
!Cname des-ede-ofb64
: DES-EDE-OFB : des-ede-ofb
!Cname des-ede3-ofb64
: DES-EDE3-OFB : des-ede3-ofb
: DESX-CBC : desx-cbc
algorithm 18 : SHA : sha
algorithm 26 : SHA1 : sha1
!Cname dsaWithSHA1-2
algorithm 27 : DSA-SHA1-old : dsaWithSHA1-old
algorithm 29 : RSA-SHA1-2 : sha1WithRSA
1 3 36 3 2 1 : RIPEMD160 : ripemd160
1 3 36 3 3 1 2 : RSA-RIPEMD160 : ripemd160WithRSA
1 3 6 1 4 1 1722 12 2 1 16 : BLAKE2b512 : blake2b512
1 3 6 1 4 1 1722 12 2 2 8 : BLAKE2s256 : blake2s256
!Cname sxnet
1 3 101 1 4 1 : SXNetID : Strong Extranet ID
2 5 : X500 : directory services (X.500)
X500 4 : X509
X509 3 : CN : commonName
X509 4 : SN : surname
X509 5 : : serialNumber
X509 6 : C : countryName
X509 7 : L : localityName
X509 8 : ST : stateOrProvinceName
X509 9 : street : streetAddress
X509 10 : O : organizationName
X509 11 : OU : organizationalUnitName
X509 12 : title : title
X509 13 : : description
X509 14 : : searchGuide
X509 15 : : businessCategory
X509 16 : : postalAddress
X509 17 : : postalCode
X509 18 : : postOfficeBox
X509 19 : : physicalDeliveryOfficeName
X509 20 : : telephoneNumber
X509 21 : : telexNumber
X509 22 : : teletexTerminalIdentifier
X509 23 : : facsimileTelephoneNumber
X509 24 : : x121Address
X509 25 : : internationaliSDNNumber
X509 26 : : registeredAddress
X509 27 : : destinationIndicator
X509 28 : : preferredDeliveryMethod
X509 29 : : presentationAddress
X509 30 : : supportedApplicationContext
X509 31 : member :
X509 32 : owner :
X509 33 : : roleOccupant
X509 34 : seeAlso :
X509 35 : : userPassword
X509 36 : : userCertificate
X509 37 : : cACertificate
X509 38 : : authorityRevocationList
X509 39 : : certificateRevocationList
X509 40 : : crossCertificatePair
X509 41 : name : name
X509 42 : GN : givenName
X509 43 : initials : initials
X509 44 : : generationQualifier
X509 45 : : x500UniqueIdentifier
X509 46 : dnQualifier : dnQualifier
X509 47 : : enhancedSearchGuide
X509 48 : : protocolInformation
X509 49 : : distinguishedName
X509 50 : : uniqueMember
X509 51 : : houseIdentifier
X509 52 : : supportedAlgorithms
X509 53 : : deltaRevocationList
X509 54 : dmdName :
X509 65 : : pseudonym
X509 72 : role : role
X509 97 : : organizationIdentifier
X509 98 : c3 : countryCode3c
X509 99 : n3 : countryCode3n
X509 100 : : dnsName
X500 8 : X500algorithms : directory services - algorithms
X500algorithms 1 1 : RSA : rsa
X500algorithms 3 100 : RSA-MDC2 : mdc2WithRSA
X500algorithms 3 101 : MDC2 : mdc2
X500 29 : id-ce
!Cname subject-directory-attributes
id-ce 9 : subjectDirectoryAttributes : X509v3 Subject Directory Attributes
!Cname subject-key-identifier
id-ce 14 : subjectKeyIdentifier : X509v3 Subject Key Identifier
!Cname key-usage
id-ce 15 : keyUsage : X509v3 Key Usage
!Cname private-key-usage-period
id-ce 16 : privateKeyUsagePeriod : X509v3 Private Key Usage Period
!Cname subject-alt-name
id-ce 17 : subjectAltName : X509v3 Subject Alternative Name
!Cname issuer-alt-name
id-ce 18 : issuerAltName : X509v3 Issuer Alternative Name
!Cname basic-constraints
id-ce 19 : basicConstraints : X509v3 Basic Constraints
!Cname crl-number
id-ce 20 : crlNumber : X509v3 CRL Number
!Cname crl-reason
id-ce 21 : CRLReason : X509v3 CRL Reason Code
!Cname invalidity-date
id-ce 24 : invalidityDate : Invalidity Date
!Cname delta-crl
id-ce 27 : deltaCRL : X509v3 Delta CRL Indicator
!Cname issuing-distribution-point
id-ce 28 : issuingDistributionPoint : X509v3 Issuing Distribution Point
!Cname certificate-issuer
id-ce 29 : certificateIssuer : X509v3 Certificate Issuer
!Cname name-constraints
id-ce 30 : nameConstraints : X509v3 Name Constraints
!Cname crl-distribution-points
id-ce 31 : crlDistributionPoints : X509v3 CRL Distribution Points
!Cname certificate-policies
id-ce 32 : certificatePolicies : X509v3 Certificate Policies
!Cname any-policy
certificate-policies 0 : anyPolicy : X509v3 Any Policy
!Cname policy-mappings
id-ce 33 : policyMappings : X509v3 Policy Mappings
!Cname authority-key-identifier
id-ce 35 : authorityKeyIdentifier : X509v3 Authority Key Identifier
!Cname policy-constraints
id-ce 36 : policyConstraints : X509v3 Policy Constraints
!Cname ext-key-usage
id-ce 37 : extendedKeyUsage : X509v3 Extended Key Usage
!Cname freshest-crl
id-ce 46 : freshestCRL : X509v3 Freshest CRL
!Cname inhibit-any-policy
id-ce 54 : inhibitAnyPolicy : X509v3 Inhibit Any Policy
!Cname target-information
id-ce 55 : targetInformation : X509v3 AC Targeting
!Cname no-rev-avail
id-ce 56 : noRevAvail : X509v3 No Revocation Available
# From RFC5280
ext-key-usage 0 : anyExtendedKeyUsage : Any Extended Key Usage
!Cname netscape
2 16 840 1 113730 : Netscape : Netscape Communications Corp.
!Cname netscape-cert-extension
netscape 1 : nsCertExt : Netscape Certificate Extension
!Cname netscape-data-type
netscape 2 : nsDataType : Netscape Data Type
!Cname netscape-cert-type
netscape-cert-extension 1 : nsCertType : Netscape Cert Type
!Cname netscape-base-url
netscape-cert-extension 2 : nsBaseUrl : Netscape Base Url
!Cname netscape-revocation-url
netscape-cert-extension 3 : nsRevocationUrl : Netscape Revocation Url
!Cname netscape-ca-revocation-url
netscape-cert-extension 4 : nsCaRevocationUrl : Netscape CA Revocation Url
!Cname netscape-renewal-url
netscape-cert-extension 7 : nsRenewalUrl : Netscape Renewal Url
!Cname netscape-ca-policy-url
netscape-cert-extension 8 : nsCaPolicyUrl : Netscape CA Policy Url
!Cname netscape-ssl-server-name
netscape-cert-extension 12 : nsSslServerName : Netscape SSL Server Name
!Cname netscape-comment
netscape-cert-extension 13 : nsComment : Netscape Comment
!Cname netscape-cert-sequence
netscape-data-type 5 : nsCertSequence : Netscape Certificate Sequence
!Cname ns-sgc
netscape 4 1 : nsSGC : Netscape Server Gated Crypto
# iso(1)
iso 3 : ORG : org
org 6 : DOD : dod
dod 1 : IANA : iana
!Alias internet iana
internet 1 : directory : Directory
internet 2 : mgmt : Management
internet 3 : experimental : Experimental
internet 4 : private : Private
internet 5 : security : Security
internet 6 : snmpv2 : SNMPv2
# Documents refer to "internet 7" as "mail". This however leads to ambiguities
# with RFC2798, Section 9.1.3, where "mail" is defined as the short name for
# rfc822Mailbox. The short name is therefore here left out for a reason.
# Subclasses of "mail", e.g. "MIME MHS" don't constitute a problem, as
# references are realized via long name "Mail" (with capital M).
internet 7 : : Mail
Private 1 : enterprises : Enterprises
# RFC 2247
Enterprises 1466 344 : dcobject : dcObject
# RFC 1495
Mail 1 : mime-mhs : MIME MHS
mime-mhs 1 : mime-mhs-headings : mime-mhs-headings
mime-mhs 2 : mime-mhs-bodies : mime-mhs-bodies
mime-mhs-headings 1 : id-hex-partial-message : id-hex-partial-message
mime-mhs-headings 2 : id-hex-multipart-message : id-hex-multipart-message
# RFC 3274
!Cname zlib-compression
id-smime-alg 8 : ZLIB : zlib compression
# AES aka Rijndael
!Alias csor 2 16 840 1 101 3
!Alias nistAlgorithms csor 4
!Alias aes nistAlgorithms 1
aes 1 : AES-128-ECB : aes-128-ecb
aes 2 : AES-128-CBC : aes-128-cbc
!Cname aes-128-ofb128
aes 3 : AES-128-OFB : aes-128-ofb
!Cname aes-128-cfb128
aes 4 : AES-128-CFB : aes-128-cfb
aes 5 : id-aes128-wrap
aes 6 : id-aes128-GCM : aes-128-gcm
aes 7 : id-aes128-CCM : aes-128-ccm
aes 8 : id-aes128-wrap-pad
aes 21 : AES-192-ECB : aes-192-ecb
aes 22 : AES-192-CBC : aes-192-cbc
!Cname aes-192-ofb128
aes 23 : AES-192-OFB : aes-192-ofb
!Cname aes-192-cfb128
aes 24 : AES-192-CFB : aes-192-cfb
aes 25 : id-aes192-wrap
aes 26 : id-aes192-GCM : aes-192-gcm
aes 27 : id-aes192-CCM : aes-192-ccm
aes 28 : id-aes192-wrap-pad
aes 41 : AES-256-ECB : aes-256-ecb
aes 42 : AES-256-CBC : aes-256-cbc
!Cname aes-256-ofb128
aes 43 : AES-256-OFB : aes-256-ofb
!Cname aes-256-cfb128
aes 44 : AES-256-CFB : aes-256-cfb
aes 45 : id-aes256-wrap
aes 46 : id-aes256-GCM : aes-256-gcm
aes 47 : id-aes256-CCM : aes-256-ccm
aes 48 : id-aes256-wrap-pad
ieee-siswg 0 1 1 : AES-128-XTS : aes-128-xts
ieee-siswg 0 1 2 : AES-256-XTS : aes-256-xts
# There are no OIDs for these modes...
: AES-128-CFB1 : aes-128-cfb1
: AES-192-CFB1 : aes-192-cfb1
: AES-256-CFB1 : aes-256-cfb1
: AES-128-CFB8 : aes-128-cfb8
: AES-192-CFB8 : aes-192-cfb8
: AES-256-CFB8 : aes-256-cfb8
: AES-128-CTR : aes-128-ctr
: AES-192-CTR : aes-192-ctr
: AES-256-CTR : aes-256-ctr
: AES-128-OCB : aes-128-ocb
: AES-192-OCB : aes-192-ocb
: AES-256-OCB : aes-256-ocb
: DES-CFB1 : des-cfb1
: DES-CFB8 : des-cfb8
: DES-EDE3-CFB1 : des-ede3-cfb1
: DES-EDE3-CFB8 : des-ede3-cfb8
# OIDs for SHA224, SHA256, SHA385 and SHA512, according to x9.84 and
# http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html
# "Middle" names are specified to be id-sha256, id-sha384, etc., but
# we adhere to unprefixed capitals for backward compatibility...
!Alias nist_hashalgs nistAlgorithms 2
nist_hashalgs 1 : SHA256 : sha256
nist_hashalgs 2 : SHA384 : sha384
nist_hashalgs 3 : SHA512 : sha512
nist_hashalgs 4 : SHA224 : sha224
nist_hashalgs 5 : SHA512-224 : sha512-224
nist_hashalgs 6 : SHA512-256 : sha512-256
nist_hashalgs 7 : SHA3-224 : sha3-224
nist_hashalgs 8 : SHA3-256 : sha3-256
nist_hashalgs 9 : SHA3-384 : sha3-384
nist_hashalgs 10 : SHA3-512 : sha3-512
nist_hashalgs 11 : SHAKE128 : shake128
nist_hashalgs 12 : SHAKE256 : shake256
nist_hashalgs 13 : id-hmacWithSHA3-224 : hmac-sha3-224
nist_hashalgs 14 : id-hmacWithSHA3-256 : hmac-sha3-256
nist_hashalgs 15 : id-hmacWithSHA3-384 : hmac-sha3-384
nist_hashalgs 16 : id-hmacWithSHA3-512 : hmac-sha3-512
# Below two are incomplete OIDs, to be uncommented when we figure out
# how to handle them...
# nist_hashalgs 17 : id-shake128-len : shake128-len
# nist_hashalgs 18 : id-shake256-len : shake256-len
# OIDs for dsa-with-sha224 and dsa-with-sha256
!Alias dsa_with_sha2 nistAlgorithms 3
dsa_with_sha2 1 : dsa_with_SHA224
dsa_with_sha2 2 : dsa_with_SHA256
# Above two belong below, but kept as they are for backward compatibility
!Alias sigAlgs nistAlgorithms 3
sigAlgs 3 : id-dsa-with-sha384 : dsa_with_SHA384
sigAlgs 4 : id-dsa-with-sha512 : dsa_with_SHA512
sigAlgs 5 : id-dsa-with-sha3-224 : dsa_with_SHA3-224
sigAlgs 6 : id-dsa-with-sha3-256 : dsa_with_SHA3-256
sigAlgs 7 : id-dsa-with-sha3-384 : dsa_with_SHA3-384
sigAlgs 8 : id-dsa-with-sha3-512 : dsa_with_SHA3-512
sigAlgs 9 : id-ecdsa-with-sha3-224 : ecdsa_with_SHA3-224
sigAlgs 10 : id-ecdsa-with-sha3-256 : ecdsa_with_SHA3-256
sigAlgs 11 : id-ecdsa-with-sha3-384 : ecdsa_with_SHA3-384
sigAlgs 12 : id-ecdsa-with-sha3-512 : ecdsa_with_SHA3-512
sigAlgs 13 : id-rsassa-pkcs1-v1_5-with-sha3-224 : RSA-SHA3-224
sigAlgs 14 : id-rsassa-pkcs1-v1_5-with-sha3-256 : RSA-SHA3-256
sigAlgs 15 : id-rsassa-pkcs1-v1_5-with-sha3-384 : RSA-SHA3-384
sigAlgs 16 : id-rsassa-pkcs1-v1_5-with-sha3-512 : RSA-SHA3-512
# Hold instruction CRL entry extension
!Cname hold-instruction-code
id-ce 23 : holdInstructionCode : Hold Instruction Code
!Alias holdInstruction X9-57 2
!Cname hold-instruction-none
holdInstruction 1 : holdInstructionNone : Hold Instruction None
!Cname hold-instruction-call-issuer
holdInstruction 2 : holdInstructionCallIssuer : Hold Instruction Call Issuer
!Cname hold-instruction-reject
holdInstruction 3 : holdInstructionReject : Hold Instruction Reject
# OID's from ITU-T. Most of this is defined in RFC 1274. A couple of
# them are also mentioned in RFC 2247
itu-t 9 : data
data 2342 : pss
pss 19200300 : ucl
ucl 100 : pilot
pilot 1 : : pilotAttributeType
pilot 3 : : pilotAttributeSyntax
pilot 4 : : pilotObjectClass
pilot 10 : : pilotGroups
pilotAttributeSyntax 4 : : iA5StringSyntax
pilotAttributeSyntax 5 : : caseIgnoreIA5StringSyntax
pilotObjectClass 3 : : pilotObject
pilotObjectClass 4 : : pilotPerson
pilotObjectClass 5 : account
pilotObjectClass 6 : document
pilotObjectClass 7 : room
pilotObjectClass 9 : : documentSeries
pilotObjectClass 13 : domain : Domain
pilotObjectClass 14 : : rFC822localPart
pilotObjectClass 15 : : dNSDomain
pilotObjectClass 17 : : domainRelatedObject
pilotObjectClass 18 : : friendlyCountry
pilotObjectClass 19 : : simpleSecurityObject
pilotObjectClass 20 : : pilotOrganization
pilotObjectClass 21 : : pilotDSA
pilotObjectClass 22 : : qualityLabelledData
pilotAttributeType 1 : UID : userId
pilotAttributeType 2 : : textEncodedORAddress
pilotAttributeType 3 : mail : rfc822Mailbox
pilotAttributeType 4 : info
pilotAttributeType 5 : : favouriteDrink
pilotAttributeType 6 : : roomNumber
pilotAttributeType 7 : photo
pilotAttributeType 8 : : userClass
pilotAttributeType 9 : host
pilotAttributeType 10 : manager
pilotAttributeType 11 : : documentIdentifier
pilotAttributeType 12 : : documentTitle
pilotAttributeType 13 : : documentVersion
pilotAttributeType 14 : : documentAuthor
pilotAttributeType 15 : : documentLocation
pilotAttributeType 20 : : homeTelephoneNumber
pilotAttributeType 21 : secretary
pilotAttributeType 22 : : otherMailbox
pilotAttributeType 23 : : lastModifiedTime
pilotAttributeType 24 : : lastModifiedBy
pilotAttributeType 25 : DC : domainComponent
pilotAttributeType 26 : : aRecord
pilotAttributeType 27 : : pilotAttributeType27
pilotAttributeType 28 : : mXRecord
pilotAttributeType 29 : : nSRecord
pilotAttributeType 30 : : sOARecord
pilotAttributeType 31 : : cNAMERecord
pilotAttributeType 37 : : associatedDomain
pilotAttributeType 38 : : associatedName
pilotAttributeType 39 : : homePostalAddress
pilotAttributeType 40 : : personalTitle
pilotAttributeType 41 : : mobileTelephoneNumber
pilotAttributeType 42 : : pagerTelephoneNumber
pilotAttributeType 43 : : friendlyCountryName
pilotAttributeType 44 : uid : uniqueIdentifier
pilotAttributeType 45 : : organizationalStatus
pilotAttributeType 46 : : janetMailbox
pilotAttributeType 47 : : mailPreferenceOption
pilotAttributeType 48 : : buildingName
pilotAttributeType 49 : : dSAQuality
pilotAttributeType 50 : : singleLevelQuality
pilotAttributeType 51 : : subtreeMinimumQuality
pilotAttributeType 52 : : subtreeMaximumQuality
pilotAttributeType 53 : : personalSignature
pilotAttributeType 54 : : dITRedirect
pilotAttributeType 55 : audio
pilotAttributeType 56 : : documentPublisher
international-organizations 42 : id-set : Secure Electronic Transactions
id-set 0 : set-ctype : content types
id-set 1 : set-msgExt : message extensions
id-set 3 : set-attr
id-set 5 : set-policy
id-set 7 : set-certExt : certificate extensions
id-set 8 : set-brand
set-ctype 0 : setct-PANData
set-ctype 1 : setct-PANToken
set-ctype 2 : setct-PANOnly
set-ctype 3 : setct-OIData
set-ctype 4 : setct-PI
set-ctype 5 : setct-PIData
set-ctype 6 : setct-PIDataUnsigned
set-ctype 7 : setct-HODInput
set-ctype 8 : setct-AuthResBaggage
set-ctype 9 : setct-AuthRevReqBaggage
set-ctype 10 : setct-AuthRevResBaggage
set-ctype 11 : setct-CapTokenSeq
set-ctype 12 : setct-PInitResData
set-ctype 13 : setct-PI-TBS
set-ctype 14 : setct-PResData
set-ctype 16 : setct-AuthReqTBS
set-ctype 17 : setct-AuthResTBS
set-ctype 18 : setct-AuthResTBSX
set-ctype 19 : setct-AuthTokenTBS
set-ctype 20 : setct-CapTokenData
set-ctype 21 : setct-CapTokenTBS
set-ctype 22 : setct-AcqCardCodeMsg
set-ctype 23 : setct-AuthRevReqTBS
set-ctype 24 : setct-AuthRevResData
set-ctype 25 : setct-AuthRevResTBS
set-ctype 26 : setct-CapReqTBS
set-ctype 27 : setct-CapReqTBSX
set-ctype 28 : setct-CapResData
set-ctype 29 : setct-CapRevReqTBS
set-ctype 30 : setct-CapRevReqTBSX
set-ctype 31 : setct-CapRevResData
set-ctype 32 : setct-CredReqTBS
set-ctype 33 : setct-CredReqTBSX
set-ctype 34 : setct-CredResData
set-ctype 35 : setct-CredRevReqTBS
set-ctype 36 : setct-CredRevReqTBSX
set-ctype 37 : setct-CredRevResData
set-ctype 38 : setct-PCertReqData
set-ctype 39 : setct-PCertResTBS
set-ctype 40 : setct-BatchAdminReqData
set-ctype 41 : setct-BatchAdminResData
set-ctype 42 : setct-CardCInitResTBS
set-ctype 43 : setct-MeAqCInitResTBS
set-ctype 44 : setct-RegFormResTBS
set-ctype 45 : setct-CertReqData
set-ctype 46 : setct-CertReqTBS
set-ctype 47 : setct-CertResData
set-ctype 48 : setct-CertInqReqTBS
set-ctype 49 : setct-ErrorTBS
set-ctype 50 : setct-PIDualSignedTBE
set-ctype 51 : setct-PIUnsignedTBE
set-ctype 52 : setct-AuthReqTBE
set-ctype 53 : setct-AuthResTBE
set-ctype 54 : setct-AuthResTBEX
set-ctype 55 : setct-AuthTokenTBE
set-ctype 56 : setct-CapTokenTBE
set-ctype 57 : setct-CapTokenTBEX
set-ctype 58 : setct-AcqCardCodeMsgTBE
set-ctype 59 : setct-AuthRevReqTBE
set-ctype 60 : setct-AuthRevResTBE
set-ctype 61 : setct-AuthRevResTBEB
set-ctype 62 : setct-CapReqTBE
set-ctype 63 : setct-CapReqTBEX
set-ctype 64 : setct-CapResTBE
set-ctype 65 : setct-CapRevReqTBE
set-ctype 66 : setct-CapRevReqTBEX
set-ctype 67 : setct-CapRevResTBE
set-ctype 68 : setct-CredReqTBE
set-ctype 69 : setct-CredReqTBEX
set-ctype 70 : setct-CredResTBE
set-ctype 71 : setct-CredRevReqTBE
set-ctype 72 : setct-CredRevReqTBEX
set-ctype 73 : setct-CredRevResTBE
set-ctype 74 : setct-BatchAdminReqTBE
set-ctype 75 : setct-BatchAdminResTBE
set-ctype 76 : setct-RegFormReqTBE
set-ctype 77 : setct-CertReqTBE
set-ctype 78 : setct-CertReqTBEX
set-ctype 79 : setct-CertResTBE
set-ctype 80 : setct-CRLNotificationTBS
set-ctype 81 : setct-CRLNotificationResTBS
set-ctype 82 : setct-BCIDistributionTBS
set-msgExt 1 : setext-genCrypt : generic cryptogram
set-msgExt 3 : setext-miAuth : merchant initiated auth
set-msgExt 4 : setext-pinSecure
set-msgExt 5 : setext-pinAny
set-msgExt 7 : setext-track2
set-msgExt 8 : setext-cv : additional verification
set-policy 0 : set-policy-root
set-certExt 0 : setCext-hashedRoot
set-certExt 1 : setCext-certType
set-certExt 2 : setCext-merchData
set-certExt 3 : setCext-cCertRequired
set-certExt 4 : setCext-tunneling
set-certExt 5 : setCext-setExt
set-certExt 6 : setCext-setQualf
set-certExt 7 : setCext-PGWYcapabilities
set-certExt 8 : setCext-TokenIdentifier
set-certExt 9 : setCext-Track2Data
set-certExt 10 : setCext-TokenType
set-certExt 11 : setCext-IssuerCapabilities
set-attr 0 : setAttr-Cert
set-attr 1 : setAttr-PGWYcap : payment gateway capabilities
set-attr 2 : setAttr-TokenType
set-attr 3 : setAttr-IssCap : issuer capabilities
setAttr-Cert 0 : set-rootKeyThumb
setAttr-Cert 1 : set-addPolicy
setAttr-TokenType 1 : setAttr-Token-EMV
setAttr-TokenType 2 : setAttr-Token-B0Prime
setAttr-IssCap 3 : setAttr-IssCap-CVM
setAttr-IssCap 4 : setAttr-IssCap-T2
setAttr-IssCap 5 : setAttr-IssCap-Sig
setAttr-IssCap-CVM 1 : setAttr-GenCryptgrm : generate cryptogram
setAttr-IssCap-T2 1 : setAttr-T2Enc : encrypted track 2
setAttr-IssCap-T2 2 : setAttr-T2cleartxt : cleartext track 2
setAttr-IssCap-Sig 1 : setAttr-TokICCsig : ICC or token signature
setAttr-IssCap-Sig 2 : setAttr-SecDevSig : secure device signature
set-brand 1 : set-brand-IATA-ATA
set-brand 30 : set-brand-Diners
set-brand 34 : set-brand-AmericanExpress
set-brand 35 : set-brand-JCB
set-brand 4 : set-brand-Visa
set-brand 5 : set-brand-MasterCard
set-brand 6011 : set-brand-Novus
rsadsi 3 10 : DES-CDMF : des-cdmf
rsadsi 1 1 6 : rsaOAEPEncryptionSET
: Oakley-EC2N-3 : ipsec3
: Oakley-EC2N-4 : ipsec4
iso 0 10118 3 0 55 : whirlpool
# GOST OIDs
member-body 643 2 2 : cryptopro
member-body 643 2 9 : cryptocom
member-body 643 7 1 : id-tc26
cryptopro 3 : id-GostR3411-94-with-GostR3410-2001 : GOST R 34.11-94 with GOST R 34.10-2001
cryptopro 4 : id-GostR3411-94-with-GostR3410-94 : GOST R 34.11-94 with GOST R 34.10-94
!Cname id-GostR3411-94
cryptopro 9 : md_gost94 : GOST R 34.11-94
cryptopro 10 : id-HMACGostR3411-94 : HMAC GOST 34.11-94
!Cname id-GostR3410-2001
cryptopro 19 : gost2001 : GOST R 34.10-2001
!Cname id-GostR3410-94
cryptopro 20 : gost94 : GOST R 34.10-94
!Cname id-Gost28147-89
cryptopro 21 : gost89 : GOST 28147-89
: gost89-cnt
: gost89-cnt-12
: gost89-cbc
: gost89-ecb
: gost89-ctr
!Cname id-Gost28147-89-MAC
cryptopro 22 : gost-mac : GOST 28147-89 MAC
: gost-mac-12
!Cname id-GostR3411-94-prf
cryptopro 23 : prf-gostr3411-94 : GOST R 34.11-94 PRF
cryptopro 98 : id-GostR3410-2001DH : GOST R 34.10-2001 DH
cryptopro 99 : id-GostR3410-94DH : GOST R 34.10-94 DH
cryptopro 14 1 : id-Gost28147-89-CryptoPro-KeyMeshing
cryptopro 14 0 : id-Gost28147-89-None-KeyMeshing
# GOST parameter set OIDs
cryptopro 30 0 : id-GostR3411-94-TestParamSet
cryptopro 30 1 : id-GostR3411-94-CryptoProParamSet
cryptopro 31 0 : id-Gost28147-89-TestParamSet
cryptopro 31 1 : id-Gost28147-89-CryptoPro-A-ParamSet
cryptopro 31 2 : id-Gost28147-89-CryptoPro-B-ParamSet
cryptopro 31 3 : id-Gost28147-89-CryptoPro-C-ParamSet
cryptopro 31 4 : id-Gost28147-89-CryptoPro-D-ParamSet
cryptopro 31 5 : id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet
cryptopro 31 6 : id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet
cryptopro 31 7 : id-Gost28147-89-CryptoPro-RIC-1-ParamSet
cryptopro 32 0 : id-GostR3410-94-TestParamSet
cryptopro 32 2 : id-GostR3410-94-CryptoPro-A-ParamSet
cryptopro 32 3 : id-GostR3410-94-CryptoPro-B-ParamSet
cryptopro 32 4 : id-GostR3410-94-CryptoPro-C-ParamSet
cryptopro 32 5 : id-GostR3410-94-CryptoPro-D-ParamSet
cryptopro 33 1 : id-GostR3410-94-CryptoPro-XchA-ParamSet
cryptopro 33 2 : id-GostR3410-94-CryptoPro-XchB-ParamSet
cryptopro 33 3 : id-GostR3410-94-CryptoPro-XchC-ParamSet
cryptopro 35 0 : id-GostR3410-2001-TestParamSet
cryptopro 35 1 : id-GostR3410-2001-CryptoPro-A-ParamSet
cryptopro 35 2 : id-GostR3410-2001-CryptoPro-B-ParamSet
cryptopro 35 3 : id-GostR3410-2001-CryptoPro-C-ParamSet
cryptopro 36 0 : id-GostR3410-2001-CryptoPro-XchA-ParamSet
cryptopro 36 1 : id-GostR3410-2001-CryptoPro-XchB-ParamSet
id-GostR3410-94 1 : id-GostR3410-94-a
id-GostR3410-94 2 : id-GostR3410-94-aBis
id-GostR3410-94 3 : id-GostR3410-94-b
id-GostR3410-94 4 : id-GostR3410-94-bBis
# Cryptocom LTD GOST OIDs
cryptocom 1 6 1 : id-Gost28147-89-cc : GOST 28147-89 Cryptocom ParamSet
!Cname id-GostR3410-94-cc
cryptocom 1 5 3 : gost94cc : GOST 34.10-94 Cryptocom
!Cname id-GostR3410-2001-cc
cryptocom 1 5 4 : gost2001cc : GOST 34.10-2001 Cryptocom
cryptocom 1 3 3 : id-GostR3411-94-with-GostR3410-94-cc : GOST R 34.11-94 with GOST R 34.10-94 Cryptocom
cryptocom 1 3 4 : id-GostR3411-94-with-GostR3410-2001-cc : GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom
cryptocom 1 8 1 : id-GostR3410-2001-ParamSet-cc : GOST R 3410-2001 Parameter Set Cryptocom
# TC26 GOST OIDs
id-tc26 1 : id-tc26-algorithms
id-tc26-algorithms 1 : id-tc26-sign
!Cname id-GostR3410-2012-256
id-tc26-sign 1 : gost2012_256: GOST R 34.10-2012 with 256 bit modulus
!Cname id-GostR3410-2012-512
id-tc26-sign 2 : gost2012_512: GOST R 34.10-2012 with 512 bit modulus
id-tc26-algorithms 2 : id-tc26-digest
!Cname id-GostR3411-2012-256
id-tc26-digest 2 : md_gost12_256: GOST R 34.11-2012 with 256 bit hash
!Cname id-GostR3411-2012-512
id-tc26-digest 3 : md_gost12_512: GOST R 34.11-2012 with 512 bit hash
id-tc26-algorithms 3 : id-tc26-signwithdigest
id-tc26-signwithdigest 2: id-tc26-signwithdigest-gost3410-2012-256: GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)
id-tc26-signwithdigest 3: id-tc26-signwithdigest-gost3410-2012-512: GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)
id-tc26-algorithms 4 : id-tc26-mac
id-tc26-mac 1 : id-tc26-hmac-gost-3411-2012-256 : HMAC GOST 34.11-2012 256 bit
id-tc26-mac 2 : id-tc26-hmac-gost-3411-2012-512 : HMAC GOST 34.11-2012 512 bit
id-tc26-algorithms 5 : id-tc26-cipher
id-tc26-cipher 1 : id-tc26-cipher-gostr3412-2015-magma
id-tc26-cipher-gostr3412-2015-magma 1 : id-tc26-cipher-gostr3412-2015-magma-ctracpkm
id-tc26-cipher-gostr3412-2015-magma 2 : id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac
id-tc26-cipher 2 : id-tc26-cipher-gostr3412-2015-kuznyechik
id-tc26-cipher-gostr3412-2015-kuznyechik 1 : id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm
id-tc26-cipher-gostr3412-2015-kuznyechik 2 : id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac
id-tc26-algorithms 6 : id-tc26-agreement
id-tc26-agreement 1 : id-tc26-agreement-gost-3410-2012-256
id-tc26-agreement 2 : id-tc26-agreement-gost-3410-2012-512
id-tc26-algorithms 7 : id-tc26-wrap
id-tc26-wrap 1 : id-tc26-wrap-gostr3412-2015-magma
id-tc26-wrap-gostr3412-2015-magma 1 : id-tc26-wrap-gostr3412-2015-magma-kexp15
id-tc26-wrap 2 : id-tc26-wrap-gostr3412-2015-kuznyechik
-id-tc26-wrap-gostr3412-2015-magma 1 : id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15
+id-tc26-wrap-gostr3412-2015-kuznyechik 1 : id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15
id-tc26 2 : id-tc26-constants
id-tc26-constants 1 : id-tc26-sign-constants
id-tc26-sign-constants 1: id-tc26-gost-3410-2012-256-constants
id-tc26-gost-3410-2012-256-constants 1 : id-tc26-gost-3410-2012-256-paramSetA: GOST R 34.10-2012 (256 bit) ParamSet A
id-tc26-gost-3410-2012-256-constants 2 : id-tc26-gost-3410-2012-256-paramSetB: GOST R 34.10-2012 (256 bit) ParamSet B
id-tc26-gost-3410-2012-256-constants 3 : id-tc26-gost-3410-2012-256-paramSetC: GOST R 34.10-2012 (256 bit) ParamSet C
id-tc26-gost-3410-2012-256-constants 4 : id-tc26-gost-3410-2012-256-paramSetD: GOST R 34.10-2012 (256 bit) ParamSet D
id-tc26-sign-constants 2: id-tc26-gost-3410-2012-512-constants
id-tc26-gost-3410-2012-512-constants 0 : id-tc26-gost-3410-2012-512-paramSetTest: GOST R 34.10-2012 (512 bit) testing parameter set
id-tc26-gost-3410-2012-512-constants 1 : id-tc26-gost-3410-2012-512-paramSetA: GOST R 34.10-2012 (512 bit) ParamSet A
id-tc26-gost-3410-2012-512-constants 2 : id-tc26-gost-3410-2012-512-paramSetB: GOST R 34.10-2012 (512 bit) ParamSet B
id-tc26-gost-3410-2012-512-constants 3 : id-tc26-gost-3410-2012-512-paramSetC: GOST R 34.10-2012 (512 bit) ParamSet C
id-tc26-constants 2 : id-tc26-digest-constants
id-tc26-constants 5 : id-tc26-cipher-constants
id-tc26-cipher-constants 1 : id-tc26-gost-28147-constants
id-tc26-gost-28147-constants 1 : id-tc26-gost-28147-param-Z : GOST 28147-89 TC26 parameter set
member-body 643 3 131 1 1 : INN : INN
member-body 643 100 1 : OGRN : OGRN
member-body 643 100 3 : SNILS : SNILS
member-body 643 100 111 : subjectSignTool : Signing Tool of Subject
member-body 643 100 112 : issuerSignTool : Signing Tool of Issuer
#GOST R34.13-2015 Grasshopper "Kuznechik"
: grasshopper-ecb
: grasshopper-ctr
: grasshopper-ofb
: grasshopper-cbc
: grasshopper-cfb
: grasshopper-mac
#GOST R34.13-2015 Magma
: magma-ecb
: magma-ctr
: magma-ofb
: magma-cbc
: magma-cfb
: magma-mac
# Definitions for Camellia cipher - CBC MODE
1 2 392 200011 61 1 1 1 2 : CAMELLIA-128-CBC : camellia-128-cbc
1 2 392 200011 61 1 1 1 3 : CAMELLIA-192-CBC : camellia-192-cbc
1 2 392 200011 61 1 1 1 4 : CAMELLIA-256-CBC : camellia-256-cbc
1 2 392 200011 61 1 1 3 2 : id-camellia128-wrap
1 2 392 200011 61 1 1 3 3 : id-camellia192-wrap
1 2 392 200011 61 1 1 3 4 : id-camellia256-wrap
# Definitions for Camellia cipher - ECB, CFB, OFB MODE
!Alias ntt-ds 0 3 4401 5
!Alias camellia ntt-ds 3 1 9
camellia 1 : CAMELLIA-128-ECB : camellia-128-ecb
!Cname camellia-128-ofb128
camellia 3 : CAMELLIA-128-OFB : camellia-128-ofb
!Cname camellia-128-cfb128
camellia 4 : CAMELLIA-128-CFB : camellia-128-cfb
camellia 6 : CAMELLIA-128-GCM : camellia-128-gcm
camellia 7 : CAMELLIA-128-CCM : camellia-128-ccm
camellia 9 : CAMELLIA-128-CTR : camellia-128-ctr
camellia 10 : CAMELLIA-128-CMAC : camellia-128-cmac
camellia 21 : CAMELLIA-192-ECB : camellia-192-ecb
!Cname camellia-192-ofb128
camellia 23 : CAMELLIA-192-OFB : camellia-192-ofb
!Cname camellia-192-cfb128
camellia 24 : CAMELLIA-192-CFB : camellia-192-cfb
camellia 26 : CAMELLIA-192-GCM : camellia-192-gcm
camellia 27 : CAMELLIA-192-CCM : camellia-192-ccm
camellia 29 : CAMELLIA-192-CTR : camellia-192-ctr
camellia 30 : CAMELLIA-192-CMAC : camellia-192-cmac
camellia 41 : CAMELLIA-256-ECB : camellia-256-ecb
!Cname camellia-256-ofb128
camellia 43 : CAMELLIA-256-OFB : camellia-256-ofb
!Cname camellia-256-cfb128
camellia 44 : CAMELLIA-256-CFB : camellia-256-cfb
camellia 46 : CAMELLIA-256-GCM : camellia-256-gcm
camellia 47 : CAMELLIA-256-CCM : camellia-256-ccm
camellia 49 : CAMELLIA-256-CTR : camellia-256-ctr
camellia 50 : CAMELLIA-256-CMAC : camellia-256-cmac
# There are no OIDs for these modes...
: CAMELLIA-128-CFB1 : camellia-128-cfb1
: CAMELLIA-192-CFB1 : camellia-192-cfb1
: CAMELLIA-256-CFB1 : camellia-256-cfb1
: CAMELLIA-128-CFB8 : camellia-128-cfb8
: CAMELLIA-192-CFB8 : camellia-192-cfb8
: CAMELLIA-256-CFB8 : camellia-256-cfb8
# Definitions for ARIA cipher
!Alias aria 1 2 410 200046 1 1
aria 1 : ARIA-128-ECB : aria-128-ecb
aria 2 : ARIA-128-CBC : aria-128-cbc
!Cname aria-128-cfb128
aria 3 : ARIA-128-CFB : aria-128-cfb
!Cname aria-128-ofb128
aria 4 : ARIA-128-OFB : aria-128-ofb
aria 5 : ARIA-128-CTR : aria-128-ctr
aria 6 : ARIA-192-ECB : aria-192-ecb
aria 7 : ARIA-192-CBC : aria-192-cbc
!Cname aria-192-cfb128
aria 8 : ARIA-192-CFB : aria-192-cfb
!Cname aria-192-ofb128
aria 9 : ARIA-192-OFB : aria-192-ofb
aria 10 : ARIA-192-CTR : aria-192-ctr
aria 11 : ARIA-256-ECB : aria-256-ecb
aria 12 : ARIA-256-CBC : aria-256-cbc
!Cname aria-256-cfb128
aria 13 : ARIA-256-CFB : aria-256-cfb
!Cname aria-256-ofb128
aria 14 : ARIA-256-OFB : aria-256-ofb
aria 15 : ARIA-256-CTR : aria-256-ctr
# There are no OIDs for these ARIA modes...
: ARIA-128-CFB1 : aria-128-cfb1
: ARIA-192-CFB1 : aria-192-cfb1
: ARIA-256-CFB1 : aria-256-cfb1
: ARIA-128-CFB8 : aria-128-cfb8
: ARIA-192-CFB8 : aria-192-cfb8
: ARIA-256-CFB8 : aria-256-cfb8
aria 37 : ARIA-128-CCM : aria-128-ccm
aria 38 : ARIA-192-CCM : aria-192-ccm
aria 39 : ARIA-256-CCM : aria-256-ccm
aria 34 : ARIA-128-GCM : aria-128-gcm
aria 35 : ARIA-192-GCM : aria-192-gcm
aria 36 : ARIA-256-GCM : aria-256-gcm
# Definitions for SEED cipher - ECB, CBC, OFB mode
member-body 410 200004 : KISA : kisa
kisa 1 3 : SEED-ECB : seed-ecb
kisa 1 4 : SEED-CBC : seed-cbc
!Cname seed-cfb128
kisa 1 5 : SEED-CFB : seed-cfb
!Cname seed-ofb128
kisa 1 6 : SEED-OFB : seed-ofb
# Definitions for SM4 cipher
sm-scheme 104 1 : SM4-ECB : sm4-ecb
sm-scheme 104 2 : SM4-CBC : sm4-cbc
!Cname sm4-ofb128
sm-scheme 104 3 : SM4-OFB : sm4-ofb
!Cname sm4-cfb128
sm-scheme 104 4 : SM4-CFB : sm4-cfb
sm-scheme 104 5 : SM4-CFB1 : sm4-cfb1
sm-scheme 104 6 : SM4-CFB8 : sm4-cfb8
sm-scheme 104 7 : SM4-CTR : sm4-ctr
# There is no OID that just denotes "HMAC" oddly enough...
: HMAC : hmac
# Nor CMAC either
: CMAC : cmac
# Synthetic composite ciphersuites
: RC4-HMAC-MD5 : rc4-hmac-md5
: AES-128-CBC-HMAC-SHA1 : aes-128-cbc-hmac-sha1
: AES-192-CBC-HMAC-SHA1 : aes-192-cbc-hmac-sha1
: AES-256-CBC-HMAC-SHA1 : aes-256-cbc-hmac-sha1
: AES-128-CBC-HMAC-SHA256 : aes-128-cbc-hmac-sha256
: AES-192-CBC-HMAC-SHA256 : aes-192-cbc-hmac-sha256
: AES-256-CBC-HMAC-SHA256 : aes-256-cbc-hmac-sha256
: ChaCha20-Poly1305 : chacha20-poly1305
: ChaCha20 : chacha20
ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH
# RFC 5639 curve OIDs (see http://www.ietf.org/rfc/rfc5639.txt)
# versionOne OBJECT IDENTIFIER ::= {
# iso(1) identified-organization(3) teletrust(36) algorithm(3)
# signature-algorithm(3) ecSign(2) ecStdCurvesAndGeneration(8)
# ellipticCurve(1) 1 }
1 3 36 3 3 2 8 1 1 1 : brainpoolP160r1
1 3 36 3 3 2 8 1 1 2 : brainpoolP160t1
1 3 36 3 3 2 8 1 1 3 : brainpoolP192r1
1 3 36 3 3 2 8 1 1 4 : brainpoolP192t1
1 3 36 3 3 2 8 1 1 5 : brainpoolP224r1
1 3 36 3 3 2 8 1 1 6 : brainpoolP224t1
1 3 36 3 3 2 8 1 1 7 : brainpoolP256r1
1 3 36 3 3 2 8 1 1 8 : brainpoolP256t1
1 3 36 3 3 2 8 1 1 9 : brainpoolP320r1
1 3 36 3 3 2 8 1 1 10 : brainpoolP320t1
1 3 36 3 3 2 8 1 1 11 : brainpoolP384r1
1 3 36 3 3 2 8 1 1 12 : brainpoolP384t1
1 3 36 3 3 2 8 1 1 13 : brainpoolP512r1
1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1
# ECDH schemes from RFC5753
!Alias x9-63-scheme 1 3 133 16 840 63 0
!Alias secg-scheme certicom-arc 1
x9-63-scheme 2 : dhSinglePass-stdDH-sha1kdf-scheme
secg-scheme 11 0 : dhSinglePass-stdDH-sha224kdf-scheme
secg-scheme 11 1 : dhSinglePass-stdDH-sha256kdf-scheme
secg-scheme 11 2 : dhSinglePass-stdDH-sha384kdf-scheme
secg-scheme 11 3 : dhSinglePass-stdDH-sha512kdf-scheme
x9-63-scheme 3 : dhSinglePass-cofactorDH-sha1kdf-scheme
secg-scheme 14 0 : dhSinglePass-cofactorDH-sha224kdf-scheme
secg-scheme 14 1 : dhSinglePass-cofactorDH-sha256kdf-scheme
secg-scheme 14 2 : dhSinglePass-cofactorDH-sha384kdf-scheme
secg-scheme 14 3 : dhSinglePass-cofactorDH-sha512kdf-scheme
# NIDs for use with lookup tables.
: dh-std-kdf
: dh-cofactor-kdf
# RFC 6962 Extension OIDs (see http://www.ietf.org/rfc/rfc6962.txt)
1 3 6 1 4 1 11129 2 4 2 : ct_precert_scts : CT Precertificate SCTs
1 3 6 1 4 1 11129 2 4 3 : ct_precert_poison : CT Precertificate Poison
1 3 6 1 4 1 11129 2 4 4 : ct_precert_signer : CT Precertificate Signer
1 3 6 1 4 1 11129 2 4 5 : ct_cert_scts : CT Certificate SCTs
# CABForum EV SSL Certificate Guidelines
# (see https://cabforum.org/extended-validation/)
# OIDs for Subject Jurisdiction of Incorporation or Registration
1 3 6 1 4 1 311 60 2 1 1 : jurisdictionL : jurisdictionLocalityName
1 3 6 1 4 1 311 60 2 1 2 : jurisdictionST : jurisdictionStateOrProvinceName
1 3 6 1 4 1 311 60 2 1 3 : jurisdictionC : jurisdictionCountryName
# SCRYPT algorithm
!Cname id-scrypt
1 3 6 1 4 1 11591 4 11 : id-scrypt : scrypt
# NID for TLS1 PRF
: TLS1-PRF : tls1-prf
# NID for HKDF
: HKDF : hkdf
# RFC 4556
1 3 6 1 5 2 3 : id-pkinit
id-pkinit 4 : pkInitClientAuth : PKINIT Client Auth
id-pkinit 5 : pkInitKDC : Signing KDC Response
# From RFC8410
1 3 101 110 : X25519
1 3 101 111 : X448
1 3 101 112 : ED25519
1 3 101 113 : ED448
# NIDs for cipher key exchange
: KxRSA : kx-rsa
: KxECDHE : kx-ecdhe
: KxDHE : kx-dhe
: KxECDHE-PSK : kx-ecdhe-psk
: KxDHE-PSK : kx-dhe-psk
: KxRSA_PSK : kx-rsa-psk
: KxPSK : kx-psk
: KxSRP : kx-srp
: KxGOST : kx-gost
: KxANY : kx-any
# NIDs for cipher authentication
: AuthRSA : auth-rsa
: AuthECDSA : auth-ecdsa
: AuthPSK : auth-psk
: AuthDSS : auth-dss
: AuthGOST01 : auth-gost01
: AuthGOST12 : auth-gost12
: AuthSRP : auth-srp
: AuthNULL : auth-null
: AuthANY : auth-any
# NID for Poly1305
: Poly1305 : poly1305
# NID for SipHash
: SipHash : siphash
# NIDs for RFC7919 DH parameters
: ffdhe2048
: ffdhe3072
: ffdhe4096
: ffdhe6144
: ffdhe8192
# OIDs for DSTU-4145/DSTU-7564 (http://zakon2.rada.gov.ua/laws/show/z0423-17)
# DSTU OIDs
member-body 804 : ISO-UA
ISO-UA 2 1 1 1 : ua-pki
ua-pki 1 1 1 : dstu28147 : DSTU Gost 28147-2009
dstu28147 2 : dstu28147-ofb : DSTU Gost 28147-2009 OFB mode
dstu28147 3 : dstu28147-cfb : DSTU Gost 28147-2009 CFB mode
dstu28147 5 : dstu28147-wrap : DSTU Gost 28147-2009 key wrap
ua-pki 1 1 2 : hmacWithDstu34311 : HMAC DSTU Gost 34311-95
ua-pki 1 2 1 : dstu34311 : DSTU Gost 34311-95
ua-pki 1 3 1 1 : dstu4145le : DSTU 4145-2002 little endian
dstu4145le 1 1 : dstu4145be : DSTU 4145-2002 big endian
# 1.2.804. 2.1.1.1 1.3.1.1 .2.6
# UA ua-pki 4145 le
# DSTU named curves
dstu4145le 2 0 : uacurve0 : DSTU curve 0
dstu4145le 2 1 : uacurve1 : DSTU curve 1
dstu4145le 2 2 : uacurve2 : DSTU curve 2
dstu4145le 2 3 : uacurve3 : DSTU curve 3
dstu4145le 2 4 : uacurve4 : DSTU curve 4
dstu4145le 2 5 : uacurve5 : DSTU curve 5
dstu4145le 2 6 : uacurve6 : DSTU curve 6
dstu4145le 2 7 : uacurve7 : DSTU curve 7
dstu4145le 2 8 : uacurve8 : DSTU curve 8
dstu4145le 2 9 : uacurve9 : DSTU curve 9
diff --git a/crypto/ocsp/ocsp_ext.c b/crypto/ocsp/ocsp_ext.c
index 27ee21245944..3ab5308a12bb 100755
--- a/crypto/ocsp/ocsp_ext.c
+++ b/crypto/ocsp/ocsp_ext.c
@@ -1,472 +1,472 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/ocsp.h>
#include "ocsp_lcl.h"
#include <openssl/rand.h>
#include <openssl/x509v3.h>
/* Standard wrapper functions for extensions */
/* OCSP request extensions */
int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x)
{
return X509v3_get_ext_count(x->tbsRequest.requestExtensions);
}
int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos)
{
return (X509v3_get_ext_by_NID
(x->tbsRequest.requestExtensions, nid, lastpos));
}
int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj,
int lastpos)
{
return (X509v3_get_ext_by_OBJ
(x->tbsRequest.requestExtensions, obj, lastpos));
}
int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos)
{
return (X509v3_get_ext_by_critical
(x->tbsRequest.requestExtensions, crit, lastpos));
}
X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc)
{
return X509v3_get_ext(x->tbsRequest.requestExtensions, loc);
}
X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc)
{
return X509v3_delete_ext(x->tbsRequest.requestExtensions, loc);
}
void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit, int *idx)
{
return X509V3_get_d2i(x->tbsRequest.requestExtensions, nid, crit, idx);
}
int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
unsigned long flags)
{
return X509V3_add1_i2d(&x->tbsRequest.requestExtensions, nid, value,
crit, flags);
}
int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc)
{
return (X509v3_add_ext(&(x->tbsRequest.requestExtensions), ex, loc) !=
NULL);
}
/* Single extensions */
int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x)
{
return X509v3_get_ext_count(x->singleRequestExtensions);
}
int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos)
{
return X509v3_get_ext_by_NID(x->singleRequestExtensions, nid, lastpos);
}
int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj,
int lastpos)
{
return X509v3_get_ext_by_OBJ(x->singleRequestExtensions, obj, lastpos);
}
int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos)
{
return (X509v3_get_ext_by_critical
(x->singleRequestExtensions, crit, lastpos));
}
X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc)
{
return X509v3_get_ext(x->singleRequestExtensions, loc);
}
X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc)
{
return X509v3_delete_ext(x->singleRequestExtensions, loc);
}
void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx)
{
return X509V3_get_d2i(x->singleRequestExtensions, nid, crit, idx);
}
int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
unsigned long flags)
{
return X509V3_add1_i2d(&x->singleRequestExtensions, nid, value, crit,
flags);
}
int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc)
{
return (X509v3_add_ext(&(x->singleRequestExtensions), ex, loc) != NULL);
}
/* OCSP Basic response */
int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x)
{
return X509v3_get_ext_count(x->tbsResponseData.responseExtensions);
}
int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos)
{
return (X509v3_get_ext_by_NID
(x->tbsResponseData.responseExtensions, nid, lastpos));
}
int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj,
int lastpos)
{
return (X509v3_get_ext_by_OBJ
(x->tbsResponseData.responseExtensions, obj, lastpos));
}
int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit,
int lastpos)
{
return (X509v3_get_ext_by_critical
(x->tbsResponseData.responseExtensions, crit, lastpos));
}
X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc)
{
return X509v3_get_ext(x->tbsResponseData.responseExtensions, loc);
}
X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc)
{
return X509v3_delete_ext(x->tbsResponseData.responseExtensions, loc);
}
void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit,
int *idx)
{
return X509V3_get_d2i(x->tbsResponseData.responseExtensions, nid, crit,
idx);
}
int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value,
int crit, unsigned long flags)
{
return X509V3_add1_i2d(&x->tbsResponseData.responseExtensions, nid,
value, crit, flags);
}
int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc)
{
return (X509v3_add_ext(&(x->tbsResponseData.responseExtensions), ex, loc)
!= NULL);
}
/* OCSP single response extensions */
int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x)
{
return X509v3_get_ext_count(x->singleExtensions);
}
int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos)
{
return X509v3_get_ext_by_NID(x->singleExtensions, nid, lastpos);
}
int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj,
int lastpos)
{
return X509v3_get_ext_by_OBJ(x->singleExtensions, obj, lastpos);
}
int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit,
int lastpos)
{
return X509v3_get_ext_by_critical(x->singleExtensions, crit, lastpos);
}
X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc)
{
return X509v3_get_ext(x->singleExtensions, loc);
}
X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc)
{
return X509v3_delete_ext(x->singleExtensions, loc);
}
void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit,
int *idx)
{
return X509V3_get_d2i(x->singleExtensions, nid, crit, idx);
}
int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value,
int crit, unsigned long flags)
{
return X509V3_add1_i2d(&x->singleExtensions, nid, value, crit, flags);
}
int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc)
{
return (X509v3_add_ext(&(x->singleExtensions), ex, loc) != NULL);
}
/* also CRL Entry Extensions */
/* Nonce handling functions */
/*
* Add a nonce to an extension stack. A nonce can be specified or if NULL a
* random nonce will be generated. Note: OpenSSL 0.9.7d and later create an
* OCTET STRING containing the nonce, previous versions used the raw nonce.
*/
static int ocsp_add1_nonce(STACK_OF(X509_EXTENSION) **exts,
unsigned char *val, int len)
{
unsigned char *tmpval;
ASN1_OCTET_STRING os;
int ret = 0;
if (len <= 0)
len = OCSP_DEFAULT_NONCE_LENGTH;
/*
* Create the OCTET STRING manually by writing out the header and
* appending the content octets. This avoids an extra memory allocation
* operation in some cases. Applications should *NOT* do this because it
* relies on library internals.
*/
os.length = ASN1_object_size(0, len, V_ASN1_OCTET_STRING);
if (os.length < 0)
return 0;
os.data = OPENSSL_malloc(os.length);
if (os.data == NULL)
goto err;
tmpval = os.data;
ASN1_put_object(&tmpval, 0, len, V_ASN1_OCTET_STRING, V_ASN1_UNIVERSAL);
if (val)
memcpy(tmpval, val, len);
else if (RAND_bytes(tmpval, len) <= 0)
goto err;
if (!X509V3_add1_i2d(exts, NID_id_pkix_OCSP_Nonce,
&os, 0, X509V3_ADD_REPLACE))
goto err;
ret = 1;
err:
OPENSSL_free(os.data);
return ret;
}
/* Add nonce to an OCSP request */
int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len)
{
return ocsp_add1_nonce(&req->tbsRequest.requestExtensions, val, len);
}
/* Same as above but for a response */
int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len)
{
return ocsp_add1_nonce(&resp->tbsResponseData.responseExtensions, val,
len);
}
/*-
* Check nonce validity in a request and response.
* Return value reflects result:
* 1: nonces present and equal.
* 2: nonces both absent.
* 3: nonce present in response only.
* 0: nonces both present and not equal.
* -1: nonce in request only.
*
* For most responders clients can check return > 0.
* If responder doesn't handle nonces return != 0 may be
* necessary. return == 0 is always an error.
*/
int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs)
{
/*
* Since we are only interested in the presence or absence of
* the nonce and comparing its value there is no need to use
* the X509V3 routines: this way we can avoid them allocating an
* ASN1_OCTET_STRING structure for the value which would be
* freed immediately anyway.
*/
int req_idx, resp_idx;
X509_EXTENSION *req_ext, *resp_ext;
req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
resp_idx = OCSP_BASICRESP_get_ext_by_NID(bs, NID_id_pkix_OCSP_Nonce, -1);
/* Check both absent */
if ((req_idx < 0) && (resp_idx < 0))
return 2;
/* Check in request only */
if ((req_idx >= 0) && (resp_idx < 0))
return -1;
/* Check in response but not request */
if ((req_idx < 0) && (resp_idx >= 0))
return 3;
/*
* Otherwise nonce in request and response so retrieve the extensions
*/
req_ext = OCSP_REQUEST_get_ext(req, req_idx);
resp_ext = OCSP_BASICRESP_get_ext(bs, resp_idx);
if (ASN1_OCTET_STRING_cmp(X509_EXTENSION_get_data(req_ext),
X509_EXTENSION_get_data(resp_ext)))
return 0;
return 1;
}
/*
* Copy the nonce value (if any) from an OCSP request to a response.
*/
int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req)
{
X509_EXTENSION *req_ext;
int req_idx;
/* Check for nonce in request */
req_idx = OCSP_REQUEST_get_ext_by_NID(req, NID_id_pkix_OCSP_Nonce, -1);
/* If no nonce that's OK */
if (req_idx < 0)
return 2;
req_ext = OCSP_REQUEST_get_ext(req, req_idx);
return OCSP_BASICRESP_add_ext(resp, req_ext, -1);
}
X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim)
{
X509_EXTENSION *x = NULL;
OCSP_CRLID *cid = NULL;
if ((cid = OCSP_CRLID_new()) == NULL)
goto err;
if (url) {
if ((cid->crlUrl = ASN1_IA5STRING_new()) == NULL)
goto err;
if (!(ASN1_STRING_set(cid->crlUrl, url, -1)))
goto err;
}
if (n) {
if ((cid->crlNum = ASN1_INTEGER_new()) == NULL)
goto err;
if (!(ASN1_INTEGER_set(cid->crlNum, *n)))
goto err;
}
if (tim) {
if ((cid->crlTime = ASN1_GENERALIZEDTIME_new()) == NULL)
goto err;
if (!(ASN1_GENERALIZEDTIME_set_string(cid->crlTime, tim)))
goto err;
}
x = X509V3_EXT_i2d(NID_id_pkix_OCSP_CrlID, 0, cid);
err:
OCSP_CRLID_free(cid);
return x;
}
/* AcceptableResponses ::= SEQUENCE OF OBJECT IDENTIFIER */
X509_EXTENSION *OCSP_accept_responses_new(char **oids)
{
int nid;
STACK_OF(ASN1_OBJECT) *sk = NULL;
ASN1_OBJECT *o = NULL;
X509_EXTENSION *x = NULL;
if ((sk = sk_ASN1_OBJECT_new_null()) == NULL)
goto err;
while (oids && *oids) {
if ((nid = OBJ_txt2nid(*oids)) != NID_undef && (o = OBJ_nid2obj(nid)))
sk_ASN1_OBJECT_push(sk, o);
oids++;
}
x = X509V3_EXT_i2d(NID_id_pkix_OCSP_acceptableResponses, 0, sk);
err:
sk_ASN1_OBJECT_pop_free(sk, ASN1_OBJECT_free);
return x;
}
/* ArchiveCutoff ::= GeneralizedTime */
X509_EXTENSION *OCSP_archive_cutoff_new(char *tim)
{
X509_EXTENSION *x = NULL;
ASN1_GENERALIZEDTIME *gt = NULL;
if ((gt = ASN1_GENERALIZEDTIME_new()) == NULL)
goto err;
if (!(ASN1_GENERALIZEDTIME_set_string(gt, tim)))
goto err;
x = X509V3_EXT_i2d(NID_id_pkix_OCSP_archiveCutoff, 0, gt);
err:
ASN1_GENERALIZEDTIME_free(gt);
return x;
}
/*
* per ACCESS_DESCRIPTION parameter are oids, of which there are currently
* two--NID_ad_ocsp, NID_id_ad_caIssuers--and GeneralName value. This method
* forces NID_ad_ocsp and uniformResourceLocator [6] IA5String.
*/
X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls)
{
X509_EXTENSION *x = NULL;
ASN1_IA5STRING *ia5 = NULL;
OCSP_SERVICELOC *sloc = NULL;
ACCESS_DESCRIPTION *ad = NULL;
if ((sloc = OCSP_SERVICELOC_new()) == NULL)
goto err;
+ X509_NAME_free(sloc->issuer);
if ((sloc->issuer = X509_NAME_dup(issuer)) == NULL)
goto err;
if (urls && *urls
&& (sloc->locator = sk_ACCESS_DESCRIPTION_new_null()) == NULL)
goto err;
while (urls && *urls) {
if ((ad = ACCESS_DESCRIPTION_new()) == NULL)
goto err;
if ((ad->method = OBJ_nid2obj(NID_ad_OCSP)) == NULL)
goto err;
- if ((ad->location = GENERAL_NAME_new()) == NULL)
- goto err;
if ((ia5 = ASN1_IA5STRING_new()) == NULL)
goto err;
if (!ASN1_STRING_set((ASN1_STRING *)ia5, *urls, -1))
goto err;
+ /* ad->location is allocated inside ACCESS_DESCRIPTION_new */
ad->location->type = GEN_URI;
ad->location->d.ia5 = ia5;
ia5 = NULL;
if (!sk_ACCESS_DESCRIPTION_push(sloc->locator, ad))
goto err;
ad = NULL;
urls++;
}
x = X509V3_EXT_i2d(NID_id_pkix_OCSP_serviceLocator, 0, sloc);
err:
ASN1_IA5STRING_free(ia5);
ACCESS_DESCRIPTION_free(ad);
OCSP_SERVICELOC_free(sloc);
return x;
}
diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c
index 8edd70ac8dd5..b8b91cc9eb3f 100755
--- a/crypto/ocsp/ocsp_lib.c
+++ b/crypto/ocsp/ocsp_lib.c
@@ -1,222 +1,222 @@
/*
- * Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/ocsp.h>
#include "ocsp_lcl.h"
#include <openssl/asn1t.h>
/* Convert a certificate and its issuer to an OCSP_CERTID */
OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject,
const X509 *issuer)
{
X509_NAME *iname;
const ASN1_INTEGER *serial;
ASN1_BIT_STRING *ikey;
if (!dgst)
dgst = EVP_sha1();
if (subject) {
iname = X509_get_issuer_name(subject);
serial = X509_get0_serialNumber(subject);
} else {
iname = X509_get_subject_name(issuer);
serial = NULL;
}
ikey = X509_get0_pubkey_bitstr(issuer);
return OCSP_cert_id_new(dgst, iname, ikey, serial);
}
OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
const X509_NAME *issuerName,
const ASN1_BIT_STRING *issuerKey,
const ASN1_INTEGER *serialNumber)
{
int nid;
unsigned int i;
X509_ALGOR *alg;
OCSP_CERTID *cid = NULL;
unsigned char md[EVP_MAX_MD_SIZE];
if ((cid = OCSP_CERTID_new()) == NULL)
goto err;
alg = &cid->hashAlgorithm;
ASN1_OBJECT_free(alg->algorithm);
if ((nid = EVP_MD_type(dgst)) == NID_undef) {
OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_UNKNOWN_NID);
goto err;
}
if ((alg->algorithm = OBJ_nid2obj(nid)) == NULL)
goto err;
if ((alg->parameter = ASN1_TYPE_new()) == NULL)
goto err;
alg->parameter->type = V_ASN1_NULL;
if (!X509_NAME_digest(issuerName, dgst, md, &i))
goto digerr;
if (!(ASN1_OCTET_STRING_set(&cid->issuerNameHash, md, i)))
goto err;
/* Calculate the issuerKey hash, excluding tag and length */
if (!EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst, NULL))
goto err;
if (!(ASN1_OCTET_STRING_set(&cid->issuerKeyHash, md, i)))
goto err;
if (serialNumber) {
if (ASN1_STRING_copy(&cid->serialNumber, serialNumber) == 0)
goto err;
}
return cid;
digerr:
OCSPerr(OCSP_F_OCSP_CERT_ID_NEW, OCSP_R_DIGEST_ERR);
err:
OCSP_CERTID_free(cid);
return NULL;
}
-int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
+int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
{
int ret;
ret = OBJ_cmp(a->hashAlgorithm.algorithm, b->hashAlgorithm.algorithm);
if (ret)
return ret;
ret = ASN1_OCTET_STRING_cmp(&a->issuerNameHash, &b->issuerNameHash);
if (ret)
return ret;
return ASN1_OCTET_STRING_cmp(&a->issuerKeyHash, &b->issuerKeyHash);
}
-int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b)
+int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b)
{
int ret;
ret = OCSP_id_issuer_cmp(a, b);
if (ret)
return ret;
return ASN1_INTEGER_cmp(&a->serialNumber, &b->serialNumber);
}
/*
* Parse a URL and split it up into host, port and path components and
* whether it is SSL.
*/
int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
int *pssl)
{
char *p, *buf;
char *host, *port;
*phost = NULL;
*pport = NULL;
*ppath = NULL;
/* dup the buffer since we are going to mess with it */
buf = OPENSSL_strdup(url);
if (!buf)
goto mem_err;
/* Check for initial colon */
p = strchr(buf, ':');
if (!p)
goto parse_err;
*(p++) = '\0';
if (strcmp(buf, "http") == 0) {
*pssl = 0;
port = "80";
} else if (strcmp(buf, "https") == 0) {
*pssl = 1;
port = "443";
} else
goto parse_err;
/* Check for double slash */
if ((p[0] != '/') || (p[1] != '/'))
goto parse_err;
p += 2;
host = p;
/* Check for trailing part of path */
p = strchr(p, '/');
if (!p)
*ppath = OPENSSL_strdup("/");
else {
*ppath = OPENSSL_strdup(p);
/* Set start of path to 0 so hostname is valid */
*p = '\0';
}
if (!*ppath)
goto mem_err;
p = host;
if (host[0] == '[') {
/* ipv6 literal */
host++;
p = strchr(host, ']');
if (!p)
goto parse_err;
*p = '\0';
p++;
}
/* Look for optional ':' for port number */
if ((p = strchr(p, ':'))) {
*p = 0;
port = p + 1;
}
*pport = OPENSSL_strdup(port);
if (!*pport)
goto mem_err;
*phost = OPENSSL_strdup(host);
if (!*phost)
goto mem_err;
OPENSSL_free(buf);
return 1;
mem_err:
OCSPerr(OCSP_F_OCSP_PARSE_URL, ERR_R_MALLOC_FAILURE);
goto err;
parse_err:
OCSPerr(OCSP_F_OCSP_PARSE_URL, OCSP_R_ERROR_PARSING_URL);
err:
OPENSSL_free(buf);
OPENSSL_free(*ppath);
*ppath = NULL;
OPENSSL_free(*pport);
*pport = NULL;
OPENSSL_free(*phost);
*phost = NULL;
return 0;
}
IMPLEMENT_ASN1_DUP_FUNCTION(OCSP_CERTID)
diff --git a/crypto/pem/pem_sign.c b/crypto/pem/pem_sign.c
index 9662eb14dbc9..7e7b32ebf7d0 100644
--- a/crypto/pem/pem_sign.c
+++ b/crypto/pem/pem_sign.c
@@ -1,50 +1,50 @@
/*
- * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/x509.h>
#include <openssl/pem.h>
int PEM_SignInit(EVP_MD_CTX *ctx, EVP_MD *type)
{
return EVP_DigestInit_ex(ctx, type, NULL);
}
int PEM_SignUpdate(EVP_MD_CTX *ctx, unsigned char *data, unsigned int count)
{
return EVP_DigestUpdate(ctx, data, count);
}
int PEM_SignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
unsigned int *siglen, EVP_PKEY *pkey)
{
unsigned char *m;
int i, ret = 0;
unsigned int m_len;
- m = OPENSSL_malloc(EVP_PKEY_size(pkey) + 2);
+ m = OPENSSL_malloc(EVP_PKEY_size(pkey));
if (m == NULL) {
PEMerr(PEM_F_PEM_SIGNFINAL, ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_SignFinal(ctx, m, &m_len, pkey) <= 0)
goto err;
i = EVP_EncodeBlock(sigret, m, m_len);
*siglen = i;
ret = 1;
err:
/* ctx has been zeroed by EVP_SignFinal() */
OPENSSL_free(m);
return ret;
}
diff --git a/crypto/poly1305/build.info b/crypto/poly1305/build.info
index 631b32b8e099..4e4dcca521f6 100644
--- a/crypto/poly1305/build.info
+++ b/crypto/poly1305/build.info
@@ -1,24 +1,25 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
poly1305_pmeth.c \
poly1305_ameth.c \
poly1305.c {- $target{poly1305_asm_src} -}
GENERATE[poly1305-sparcv9.S]=asm/poly1305-sparcv9.pl $(PERLASM_SCHEME)
INCLUDE[poly1305-sparcv9.o]=..
GENERATE[poly1305-x86.s]=asm/poly1305-x86.pl \
$(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
GENERATE[poly1305-x86_64.s]=asm/poly1305-x86_64.pl $(PERLASM_SCHEME)
GENERATE[poly1305-ppc.s]=asm/poly1305-ppc.pl $(PERLASM_SCHEME)
GENERATE[poly1305-ppcfp.s]=asm/poly1305-ppcfp.pl $(PERLASM_SCHEME)
GENERATE[poly1305-armv4.S]=asm/poly1305-armv4.pl $(PERLASM_SCHEME)
INCLUDE[poly1305-armv4.o]=..
GENERATE[poly1305-armv8.S]=asm/poly1305-armv8.pl $(PERLASM_SCHEME)
INCLUDE[poly1305-armv8.o]=..
GENERATE[poly1305-mips.S]=asm/poly1305-mips.pl $(PERLASM_SCHEME)
INCLUDE[poly1305-mips.o]=..
+GENERATE[poly1305-s390x.S]=asm/poly1305-s390x.pl $(PERLASM_SCHEME)
BEGINRAW[Makefile(unix)]
{- $builddir -}/poly1305-%.S: {- $sourcedir -}/asm/poly1305-%.pl
CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
ENDRAW[Makefile(unix)]
diff --git a/crypto/ppccap.c b/crypto/ppccap.c
index afb9e31b0028..a59485207b16 100644
--- a/crypto/ppccap.c
+++ b/crypto/ppccap.c
@@ -1,408 +1,409 @@
/*
* Copyright 2009-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <signal.h>
#include <unistd.h>
#if defined(__linux) || defined(_AIX)
# include <sys/utsname.h>
#endif
#if defined(_AIX53) /* defined even on post-5.3 */
# include <sys/systemcfg.h>
# if !defined(__power_set)
# define __power_set(a) (_system_configuration.implementation & (a))
# endif
#endif
#if defined(__APPLE__) && defined(__MACH__)
# include <sys/types.h>
# include <sys/sysctl.h>
#endif
#include <openssl/crypto.h>
#include <openssl/bn.h>
#include <internal/cryptlib.h>
#include <internal/chacha.h>
#include "bn/bn_lcl.h"
#include "ppc_arch.h"
unsigned int OPENSSL_ppccap_P = 0;
static sigset_t all_masked;
#ifdef OPENSSL_BN_ASM_MONT
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, int num)
{
int bn_mul_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, int num);
int bn_mul4x_mont_int(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
const BN_ULONG *np, const BN_ULONG *n0, int num);
if (num < 4)
return 0;
if ((num & 3) == 0)
return bn_mul4x_mont_int(rp, ap, bp, np, n0, num);
/*
* There used to be [optional] call to bn_mul_mont_fpu64 here,
* but above subroutine is faster on contemporary processors.
* Formulation means that there might be old processors where
* FPU code path would be faster, POWER6 perhaps, but there was
* no opportunity to figure it out...
*/
return bn_mul_mont_int(rp, ap, bp, np, n0, num);
}
#endif
void sha256_block_p8(void *ctx, const void *inp, size_t len);
void sha256_block_ppc(void *ctx, const void *inp, size_t len);
void sha256_block_data_order(void *ctx, const void *inp, size_t len);
void sha256_block_data_order(void *ctx, const void *inp, size_t len)
{
OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha256_block_p8(ctx, inp, len) :
sha256_block_ppc(ctx, inp, len);
}
void sha512_block_p8(void *ctx, const void *inp, size_t len);
void sha512_block_ppc(void *ctx, const void *inp, size_t len);
void sha512_block_data_order(void *ctx, const void *inp, size_t len);
void sha512_block_data_order(void *ctx, const void *inp, size_t len)
{
OPENSSL_ppccap_P & PPC_CRYPTO207 ? sha512_block_p8(ctx, inp, len) :
sha512_block_ppc(ctx, inp, len);
}
#ifndef OPENSSL_NO_CHACHA
void ChaCha20_ctr32_int(unsigned char *out, const unsigned char *inp,
size_t len, const unsigned int key[8],
const unsigned int counter[4]);
void ChaCha20_ctr32_vmx(unsigned char *out, const unsigned char *inp,
size_t len, const unsigned int key[8],
const unsigned int counter[4]);
void ChaCha20_ctr32_vsx(unsigned char *out, const unsigned char *inp,
size_t len, const unsigned int key[8],
const unsigned int counter[4]);
void ChaCha20_ctr32(unsigned char *out, const unsigned char *inp,
size_t len, const unsigned int key[8],
const unsigned int counter[4])
{
OPENSSL_ppccap_P & PPC_CRYPTO207
? ChaCha20_ctr32_vsx(out, inp, len, key, counter)
: OPENSSL_ppccap_P & PPC_ALTIVEC
? ChaCha20_ctr32_vmx(out, inp, len, key, counter)
: ChaCha20_ctr32_int(out, inp, len, key, counter);
}
#endif
#ifndef OPENSSL_NO_POLY1305
void poly1305_init_int(void *ctx, const unsigned char key[16]);
void poly1305_blocks(void *ctx, const unsigned char *inp, size_t len,
unsigned int padbit);
void poly1305_emit(void *ctx, unsigned char mac[16],
const unsigned int nonce[4]);
void poly1305_init_fpu(void *ctx, const unsigned char key[16]);
void poly1305_blocks_fpu(void *ctx, const unsigned char *inp, size_t len,
unsigned int padbit);
void poly1305_emit_fpu(void *ctx, unsigned char mac[16],
const unsigned int nonce[4]);
int poly1305_init(void *ctx, const unsigned char key[16], void *func[2]);
int poly1305_init(void *ctx, const unsigned char key[16], void *func[2])
{
if (sizeof(size_t) == 4 && (OPENSSL_ppccap_P & PPC_FPU)) {
poly1305_init_fpu(ctx, key);
func[0] = (void*)(uintptr_t)poly1305_blocks_fpu;
func[1] = (void*)(uintptr_t)poly1305_emit_fpu;
} else {
poly1305_init_int(ctx, key);
func[0] = (void*)(uintptr_t)poly1305_blocks;
func[1] = (void*)(uintptr_t)poly1305_emit;
}
return 1;
}
#endif
#ifdef ECP_NISTZ256_ASM
void ecp_nistz256_mul_mont(unsigned long res[4], const unsigned long a[4],
const unsigned long b[4]);
void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4]);
void ecp_nistz256_to_mont(unsigned long res[4], const unsigned long in[4])
{
static const unsigned long RR[] = { 0x0000000000000003U,
0xfffffffbffffffffU,
0xfffffffffffffffeU,
0x00000004fffffffdU };
ecp_nistz256_mul_mont(res, in, RR);
}
void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4]);
void ecp_nistz256_from_mont(unsigned long res[4], const unsigned long in[4])
{
static const unsigned long one[] = { 1, 0, 0, 0 };
ecp_nistz256_mul_mont(res, in, one);
}
#endif
static sigjmp_buf ill_jmp;
static void ill_handler(int sig)
{
siglongjmp(ill_jmp, sig);
}
void OPENSSL_fpu_probe(void);
void OPENSSL_ppc64_probe(void);
void OPENSSL_altivec_probe(void);
void OPENSSL_crypto207_probe(void);
void OPENSSL_madd300_probe(void);
long OPENSSL_rdtsc_mftb(void);
long OPENSSL_rdtsc_mfspr268(void);
uint32_t OPENSSL_rdtsc(void)
{
if (OPENSSL_ppccap_P & PPC_MFTB)
return OPENSSL_rdtsc_mftb();
else if (OPENSSL_ppccap_P & PPC_MFSPR268)
return OPENSSL_rdtsc_mfspr268();
else
return 0;
}
size_t OPENSSL_instrument_bus_mftb(unsigned int *, size_t);
size_t OPENSSL_instrument_bus_mfspr268(unsigned int *, size_t);
size_t OPENSSL_instrument_bus(unsigned int *out, size_t cnt)
{
if (OPENSSL_ppccap_P & PPC_MFTB)
return OPENSSL_instrument_bus_mftb(out, cnt);
else if (OPENSSL_ppccap_P & PPC_MFSPR268)
return OPENSSL_instrument_bus_mfspr268(out, cnt);
else
return 0;
}
size_t OPENSSL_instrument_bus2_mftb(unsigned int *, size_t, size_t);
size_t OPENSSL_instrument_bus2_mfspr268(unsigned int *, size_t, size_t);
size_t OPENSSL_instrument_bus2(unsigned int *out, size_t cnt, size_t max)
{
if (OPENSSL_ppccap_P & PPC_MFTB)
return OPENSSL_instrument_bus2_mftb(out, cnt, max);
else if (OPENSSL_ppccap_P & PPC_MFSPR268)
return OPENSSL_instrument_bus2_mfspr268(out, cnt, max);
else
return 0;
}
#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 16)
# include <sys/auxv.h>
# define OSSL_IMPLEMENT_GETAUXVAL
# endif
#endif
/* I wish <sys/auxv.h> was universally available */
#define HWCAP 16 /* AT_HWCAP */
#define HWCAP_PPC64 (1U << 30)
#define HWCAP_ALTIVEC (1U << 28)
#define HWCAP_FPU (1U << 27)
#define HWCAP_POWER6_EXT (1U << 9)
#define HWCAP_VSX (1U << 7)
#define HWCAP2 26 /* AT_HWCAP2 */
#define HWCAP_VEC_CRYPTO (1U << 25)
#define HWCAP_ARCH_3_00 (1U << 23)
# if defined(__GNUC__) && __GNUC__>=2
__attribute__ ((constructor))
# endif
void OPENSSL_cpuid_setup(void)
{
char *e;
struct sigaction ill_oact, ill_act;
sigset_t oset;
static int trigger = 0;
if (trigger)
return;
trigger = 1;
if ((e = getenv("OPENSSL_ppccap"))) {
OPENSSL_ppccap_P = strtoul(e, NULL, 0);
return;
}
OPENSSL_ppccap_P = 0;
#if defined(_AIX)
OPENSSL_ppccap_P |= PPC_FPU;
if (sizeof(size_t) == 4) {
struct utsname uts;
# if defined(_SC_AIX_KERNEL_BITMODE)
if (sysconf(_SC_AIX_KERNEL_BITMODE) != 64)
return;
# endif
if (uname(&uts) != 0 || atoi(uts.version) < 6)
return;
}
# if defined(__power_set)
/*
* Value used in __power_set is a single-bit 1<<n one denoting
* specific processor class. Incidentally 0xffffffff<<n can be
* used to denote specific processor and its successors.
*/
if (sizeof(size_t) == 4) {
/* In 32-bit case PPC_FPU64 is always fastest [if option] */
if (__power_set(0xffffffffU<<13)) /* POWER5 and later */
OPENSSL_ppccap_P |= PPC_FPU64;
} else {
/* In 64-bit case PPC_FPU64 is fastest only on POWER6 */
if (__power_set(0x1U<<14)) /* POWER6 */
OPENSSL_ppccap_P |= PPC_FPU64;
}
if (__power_set(0xffffffffU<<14)) /* POWER6 and later */
OPENSSL_ppccap_P |= PPC_ALTIVEC;
if (__power_set(0xffffffffU<<16)) /* POWER8 and later */
OPENSSL_ppccap_P |= PPC_CRYPTO207;
if (__power_set(0xffffffffU<<17)) /* POWER9 and later */
OPENSSL_ppccap_P |= PPC_MADD300;
return;
# endif
#endif
#if defined(__APPLE__) && defined(__MACH__)
OPENSSL_ppccap_P |= PPC_FPU;
{
int val;
size_t len = sizeof(val);
if (sysctlbyname("hw.optional.64bitops", &val, &len, NULL, 0) == 0) {
if (val)
OPENSSL_ppccap_P |= PPC_FPU64;
}
len = sizeof(val);
if (sysctlbyname("hw.optional.altivec", &val, &len, NULL, 0) == 0) {
if (val)
OPENSSL_ppccap_P |= PPC_ALTIVEC;
}
return;
}
#endif
#ifdef OSSL_IMPLEMENT_GETAUXVAL
{
unsigned long hwcap = getauxval(HWCAP);
+ unsigned long hwcap2 = getauxval(HWCAP2);
if (hwcap & HWCAP_FPU) {
OPENSSL_ppccap_P |= PPC_FPU;
if (sizeof(size_t) == 4) {
/* In 32-bit case PPC_FPU64 is always fastest [if option] */
if (hwcap & HWCAP_PPC64)
OPENSSL_ppccap_P |= PPC_FPU64;
} else {
/* In 64-bit case PPC_FPU64 is fastest only on POWER6 */
if (hwcap & HWCAP_POWER6_EXT)
OPENSSL_ppccap_P |= PPC_FPU64;
}
}
if (hwcap & HWCAP_ALTIVEC) {
OPENSSL_ppccap_P |= PPC_ALTIVEC;
- if ((hwcap & HWCAP_VSX) && (getauxval(HWCAP2) & HWCAP_VEC_CRYPTO))
+ if ((hwcap & HWCAP_VSX) && (hwcap2 & HWCAP_VEC_CRYPTO))
OPENSSL_ppccap_P |= PPC_CRYPTO207;
}
- if (hwcap & HWCAP_ARCH_3_00) {
+ if (hwcap2 & HWCAP_ARCH_3_00) {
OPENSSL_ppccap_P |= PPC_MADD300;
}
}
#endif
sigfillset(&all_masked);
sigdelset(&all_masked, SIGILL);
sigdelset(&all_masked, SIGTRAP);
#ifdef SIGEMT
sigdelset(&all_masked, SIGEMT);
#endif
sigdelset(&all_masked, SIGFPE);
sigdelset(&all_masked, SIGBUS);
sigdelset(&all_masked, SIGSEGV);
memset(&ill_act, 0, sizeof(ill_act));
ill_act.sa_handler = ill_handler;
ill_act.sa_mask = all_masked;
sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
sigaction(SIGILL, &ill_act, &ill_oact);
#ifndef OSSL_IMPLEMENT_GETAUXVAL
if (sigsetjmp(ill_jmp,1) == 0) {
OPENSSL_fpu_probe();
OPENSSL_ppccap_P |= PPC_FPU;
if (sizeof(size_t) == 4) {
# ifdef __linux
struct utsname uts;
if (uname(&uts) == 0 && strcmp(uts.machine, "ppc64") == 0)
# endif
if (sigsetjmp(ill_jmp, 1) == 0) {
OPENSSL_ppc64_probe();
OPENSSL_ppccap_P |= PPC_FPU64;
}
} else {
/*
* Wanted code detecting POWER6 CPU and setting PPC_FPU64
*/
}
}
if (sigsetjmp(ill_jmp, 1) == 0) {
OPENSSL_altivec_probe();
OPENSSL_ppccap_P |= PPC_ALTIVEC;
if (sigsetjmp(ill_jmp, 1) == 0) {
OPENSSL_crypto207_probe();
OPENSSL_ppccap_P |= PPC_CRYPTO207;
}
}
if (sigsetjmp(ill_jmp, 1) == 0) {
OPENSSL_madd300_probe();
OPENSSL_ppccap_P |= PPC_MADD300;
}
#endif
if (sigsetjmp(ill_jmp, 1) == 0) {
OPENSSL_rdtsc_mftb();
OPENSSL_ppccap_P |= PPC_MFTB;
} else if (sigsetjmp(ill_jmp, 1) == 0) {
OPENSSL_rdtsc_mfspr268();
OPENSSL_ppccap_P |= PPC_MFSPR268;
}
sigaction(SIGILL, &ill_oact, NULL);
sigprocmask(SIG_SETMASK, &oset, NULL);
}
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index a13282181d6d..abbe0a8ba30f 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -1,1159 +1,1159 @@
/*
- * Copyright 2011-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2011-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "rand_lcl.h"
#include "internal/thread_once.h"
#include "internal/rand_int.h"
#include "internal/cryptlib_int.h"
/*
* Support framework for NIST SP 800-90A DRBG
*
* See manual page RAND_DRBG(7) for a general overview.
*
* The OpenSSL model is to have new and free functions, and that new
* does all initialization. That is not the NIST model, which has
* instantiation and un-instantiate, and re-use within a new/free
* lifecycle. (No doubt this comes from the desire to support hardware
* DRBG, where allocation of resources on something like an HSM is
* a much bigger deal than just re-setting an allocated resource.)
*/
/*
* The three shared DRBG instances
*
* There are three shared DRBG instances: <master>, <public>, and <private>.
*/
/*
* The <master> DRBG
*
* Not used directly by the application, only for reseeding the two other
* DRBGs. It reseeds itself by pulling either randomness from os entropy
* sources or by consuming randomness which was added by RAND_add().
*
* The <master> DRBG is a global instance which is accessed concurrently by
* all threads. The necessary locking is managed automatically by its child
* DRBG instances during reseeding.
*/
static RAND_DRBG *master_drbg;
/*
* The <public> DRBG
*
* Used by default for generating random bytes using RAND_bytes().
*
* The <public> DRBG is thread-local, i.e., there is one instance per thread.
*/
static CRYPTO_THREAD_LOCAL public_drbg;
/*
* The <private> DRBG
*
* Used by default for generating private keys using RAND_priv_bytes()
*
* The <private> DRBG is thread-local, i.e., there is one instance per thread.
*/
static CRYPTO_THREAD_LOCAL private_drbg;
/* NIST SP 800-90A DRBG recommends the use of a personalization string. */
static const char ossl_pers_string[] = "OpenSSL NIST SP 800-90A DRBG";
static CRYPTO_ONCE rand_drbg_init = CRYPTO_ONCE_STATIC_INIT;
static int rand_drbg_type = RAND_DRBG_TYPE;
static unsigned int rand_drbg_flags = RAND_DRBG_FLAGS;
static unsigned int master_reseed_interval = MASTER_RESEED_INTERVAL;
static unsigned int slave_reseed_interval = SLAVE_RESEED_INTERVAL;
static time_t master_reseed_time_interval = MASTER_RESEED_TIME_INTERVAL;
static time_t slave_reseed_time_interval = SLAVE_RESEED_TIME_INTERVAL;
/* A logical OR of all used DRBG flag bits (currently there is only one) */
static const unsigned int rand_drbg_used_flags =
RAND_DRBG_FLAG_CTR_NO_DF;
static RAND_DRBG *drbg_setup(RAND_DRBG *parent);
static RAND_DRBG *rand_drbg_new(int secure,
int type,
unsigned int flags,
RAND_DRBG *parent);
/*
* Set/initialize |drbg| to be of type |type|, with optional |flags|.
*
* If |type| and |flags| are zero, use the defaults
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_set(RAND_DRBG *drbg, int type, unsigned int flags)
{
int ret = 1;
if (type == 0 && flags == 0) {
type = rand_drbg_type;
flags = rand_drbg_flags;
}
/* If set is called multiple times - clear the old one */
if (drbg->type != 0 && (type != drbg->type || flags != drbg->flags)) {
drbg->meth->uninstantiate(drbg);
rand_pool_free(drbg->adin_pool);
drbg->adin_pool = NULL;
}
drbg->state = DRBG_UNINITIALISED;
drbg->flags = flags;
drbg->type = type;
switch (type) {
default:
drbg->type = 0;
drbg->flags = 0;
drbg->meth = NULL;
RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_UNSUPPORTED_DRBG_TYPE);
return 0;
case 0:
/* Uninitialized; that's okay. */
drbg->meth = NULL;
return 1;
case NID_aes_128_ctr:
case NID_aes_192_ctr:
case NID_aes_256_ctr:
ret = drbg_ctr_init(drbg);
break;
}
if (ret == 0) {
drbg->state = DRBG_ERROR;
RANDerr(RAND_F_RAND_DRBG_SET, RAND_R_ERROR_INITIALISING_DRBG);
}
return ret;
}
/*
* Set/initialize default |type| and |flag| for new drbg instances.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_set_defaults(int type, unsigned int flags)
{
int ret = 1;
switch (type) {
default:
RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_TYPE);
return 0;
case NID_aes_128_ctr:
case NID_aes_192_ctr:
case NID_aes_256_ctr:
break;
}
if ((flags & ~rand_drbg_used_flags) != 0) {
RANDerr(RAND_F_RAND_DRBG_SET_DEFAULTS, RAND_R_UNSUPPORTED_DRBG_FLAGS);
return 0;
}
rand_drbg_type = type;
rand_drbg_flags = flags;
return ret;
}
/*
* Allocate memory and initialize a new DRBG. The DRBG is allocated on
* the secure heap if |secure| is nonzero and the secure heap is enabled.
* The |parent|, if not NULL, will be used as random source for reseeding.
*
* Returns a pointer to the new DRBG instance on success, NULL on failure.
*/
static RAND_DRBG *rand_drbg_new(int secure,
int type,
unsigned int flags,
RAND_DRBG *parent)
{
- RAND_DRBG *drbg = secure ?
- OPENSSL_secure_zalloc(sizeof(*drbg)) : OPENSSL_zalloc(sizeof(*drbg));
+ RAND_DRBG *drbg = secure ? OPENSSL_secure_zalloc(sizeof(*drbg))
+ : OPENSSL_zalloc(sizeof(*drbg));
if (drbg == NULL) {
RANDerr(RAND_F_RAND_DRBG_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
drbg->secure = secure && CRYPTO_secure_allocated(drbg);
drbg->fork_count = rand_fork_count;
drbg->parent = parent;
if (parent == NULL) {
drbg->get_entropy = rand_drbg_get_entropy;
drbg->cleanup_entropy = rand_drbg_cleanup_entropy;
#ifndef RAND_DRBG_GET_RANDOM_NONCE
drbg->get_nonce = rand_drbg_get_nonce;
drbg->cleanup_nonce = rand_drbg_cleanup_nonce;
#endif
drbg->reseed_interval = master_reseed_interval;
drbg->reseed_time_interval = master_reseed_time_interval;
} else {
drbg->get_entropy = rand_drbg_get_entropy;
drbg->cleanup_entropy = rand_drbg_cleanup_entropy;
/*
* Do not provide nonce callbacks, the child DRBGs will
* obtain their nonce using random bits from the parent.
*/
drbg->reseed_interval = slave_reseed_interval;
drbg->reseed_time_interval = slave_reseed_time_interval;
}
if (RAND_DRBG_set(drbg, type, flags) == 0)
goto err;
if (parent != NULL) {
rand_drbg_lock(parent);
if (drbg->strength > parent->strength) {
/*
* We currently don't support the algorithm from NIST SP 800-90C
* 10.1.2 to use a weaker DRBG as source
*/
rand_drbg_unlock(parent);
RANDerr(RAND_F_RAND_DRBG_NEW, RAND_R_PARENT_STRENGTH_TOO_WEAK);
goto err;
}
rand_drbg_unlock(parent);
}
return drbg;
err:
RAND_DRBG_free(drbg);
return NULL;
}
RAND_DRBG *RAND_DRBG_new(int type, unsigned int flags, RAND_DRBG *parent)
{
return rand_drbg_new(0, type, flags, parent);
}
RAND_DRBG *RAND_DRBG_secure_new(int type, unsigned int flags, RAND_DRBG *parent)
{
return rand_drbg_new(1, type, flags, parent);
}
/*
* Uninstantiate |drbg| and free all memory.
*/
void RAND_DRBG_free(RAND_DRBG *drbg)
{
if (drbg == NULL)
return;
if (drbg->meth != NULL)
drbg->meth->uninstantiate(drbg);
rand_pool_free(drbg->adin_pool);
CRYPTO_THREAD_lock_free(drbg->lock);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_DRBG, drbg, &drbg->ex_data);
if (drbg->secure)
OPENSSL_secure_clear_free(drbg, sizeof(*drbg));
else
OPENSSL_clear_free(drbg, sizeof(*drbg));
}
/*
* Instantiate |drbg|, after it has been initialized. Use |pers| and
* |perslen| as prediction-resistance input.
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_instantiate(RAND_DRBG *drbg,
const unsigned char *pers, size_t perslen)
{
unsigned char *nonce = NULL, *entropy = NULL;
size_t noncelen = 0, entropylen = 0;
size_t min_entropy = drbg->strength;
size_t min_entropylen = drbg->min_entropylen;
size_t max_entropylen = drbg->max_entropylen;
if (perslen > drbg->max_perslen) {
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
RAND_R_PERSONALISATION_STRING_TOO_LONG);
goto end;
}
if (drbg->meth == NULL) {
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
goto end;
}
if (drbg->state != DRBG_UNINITIALISED) {
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE,
drbg->state == DRBG_ERROR ? RAND_R_IN_ERROR_STATE
: RAND_R_ALREADY_INSTANTIATED);
goto end;
}
drbg->state = DRBG_ERROR;
/*
* NIST SP800-90Ar1 section 9.1 says you can combine getting the entropy
* and nonce in 1 call by increasing the entropy with 50% and increasing
* the minimum length to accomadate the length of the nonce.
* We do this in case a nonce is require and get_nonce is NULL.
*/
if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) {
min_entropy += drbg->strength / 2;
min_entropylen += drbg->min_noncelen;
max_entropylen += drbg->max_noncelen;
}
drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
if (drbg->reseed_next_counter) {
drbg->reseed_next_counter++;
if(!drbg->reseed_next_counter)
drbg->reseed_next_counter = 1;
}
if (drbg->get_entropy != NULL)
entropylen = drbg->get_entropy(drbg, &entropy, min_entropy,
min_entropylen, max_entropylen, 0);
if (entropylen < min_entropylen
|| entropylen > max_entropylen) {
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_ENTROPY);
goto end;
}
if (drbg->min_noncelen > 0 && drbg->get_nonce != NULL) {
noncelen = drbg->get_nonce(drbg, &nonce, drbg->strength / 2,
drbg->min_noncelen, drbg->max_noncelen);
if (noncelen < drbg->min_noncelen || noncelen > drbg->max_noncelen) {
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_RETRIEVING_NONCE);
goto end;
}
}
if (!drbg->meth->instantiate(drbg, entropy, entropylen,
nonce, noncelen, pers, perslen)) {
RANDerr(RAND_F_RAND_DRBG_INSTANTIATE, RAND_R_ERROR_INSTANTIATING_DRBG);
goto end;
}
drbg->state = DRBG_READY;
drbg->reseed_gen_counter = 1;
drbg->reseed_time = time(NULL);
tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
end:
if (entropy != NULL && drbg->cleanup_entropy != NULL)
drbg->cleanup_entropy(drbg, entropy, entropylen);
if (nonce != NULL && drbg->cleanup_nonce != NULL)
drbg->cleanup_nonce(drbg, nonce, noncelen);
if (drbg->state == DRBG_READY)
return 1;
return 0;
}
/*
* Uninstantiate |drbg|. Must be instantiated before it can be used.
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_uninstantiate(RAND_DRBG *drbg)
{
if (drbg->meth == NULL) {
drbg->state = DRBG_ERROR;
RANDerr(RAND_F_RAND_DRBG_UNINSTANTIATE,
RAND_R_NO_DRBG_IMPLEMENTATION_SELECTED);
return 0;
}
/* Clear the entire drbg->ctr struct, then reset some important
* members of the drbg->ctr struct (e.g. keysize, df_ks) to their
* initial values.
*/
drbg->meth->uninstantiate(drbg);
return RAND_DRBG_set(drbg, drbg->type, drbg->flags);
}
/*
* Reseed |drbg|, mixing in the specified data
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_reseed(RAND_DRBG *drbg,
const unsigned char *adin, size_t adinlen,
int prediction_resistance)
{
unsigned char *entropy = NULL;
size_t entropylen = 0;
if (drbg->state == DRBG_ERROR) {
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_IN_ERROR_STATE);
return 0;
}
if (drbg->state == DRBG_UNINITIALISED) {
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_NOT_INSTANTIATED);
return 0;
}
if (adin == NULL) {
adinlen = 0;
} else if (adinlen > drbg->max_adinlen) {
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
return 0;
}
drbg->state = DRBG_ERROR;
drbg->reseed_next_counter = tsan_load(&drbg->reseed_prop_counter);
if (drbg->reseed_next_counter) {
drbg->reseed_next_counter++;
if(!drbg->reseed_next_counter)
drbg->reseed_next_counter = 1;
}
if (drbg->get_entropy != NULL)
entropylen = drbg->get_entropy(drbg, &entropy, drbg->strength,
drbg->min_entropylen,
drbg->max_entropylen,
prediction_resistance);
if (entropylen < drbg->min_entropylen
|| entropylen > drbg->max_entropylen) {
RANDerr(RAND_F_RAND_DRBG_RESEED, RAND_R_ERROR_RETRIEVING_ENTROPY);
goto end;
}
if (!drbg->meth->reseed(drbg, entropy, entropylen, adin, adinlen))
goto end;
drbg->state = DRBG_READY;
drbg->reseed_gen_counter = 1;
drbg->reseed_time = time(NULL);
tsan_store(&drbg->reseed_prop_counter, drbg->reseed_next_counter);
end:
if (entropy != NULL && drbg->cleanup_entropy != NULL)
drbg->cleanup_entropy(drbg, entropy, entropylen);
if (drbg->state == DRBG_READY)
return 1;
return 0;
}
/*
* Restart |drbg|, using the specified entropy or additional input
*
* Tries its best to get the drbg instantiated by all means,
* regardless of its current state.
*
* Optionally, a |buffer| of |len| random bytes can be passed,
* which is assumed to contain at least |entropy| bits of entropy.
*
* If |entropy| > 0, the buffer content is used as entropy input.
*
* If |entropy| == 0, the buffer content is used as additional input
*
* Returns 1 on success, 0 on failure.
*
* This function is used internally only.
*/
int rand_drbg_restart(RAND_DRBG *drbg,
const unsigned char *buffer, size_t len, size_t entropy)
{
int reseeded = 0;
const unsigned char *adin = NULL;
size_t adinlen = 0;
if (drbg->seed_pool != NULL) {
RANDerr(RAND_F_RAND_DRBG_RESTART, ERR_R_INTERNAL_ERROR);
drbg->state = DRBG_ERROR;
rand_pool_free(drbg->seed_pool);
drbg->seed_pool = NULL;
return 0;
}
if (buffer != NULL) {
if (entropy > 0) {
if (drbg->max_entropylen < len) {
RANDerr(RAND_F_RAND_DRBG_RESTART,
RAND_R_ENTROPY_INPUT_TOO_LONG);
drbg->state = DRBG_ERROR;
return 0;
}
if (entropy > 8 * len) {
RANDerr(RAND_F_RAND_DRBG_RESTART, RAND_R_ENTROPY_OUT_OF_RANGE);
drbg->state = DRBG_ERROR;
return 0;
}
/* will be picked up by the rand_drbg_get_entropy() callback */
drbg->seed_pool = rand_pool_attach(buffer, len, entropy);
if (drbg->seed_pool == NULL)
return 0;
} else {
if (drbg->max_adinlen < len) {
RANDerr(RAND_F_RAND_DRBG_RESTART,
RAND_R_ADDITIONAL_INPUT_TOO_LONG);
drbg->state = DRBG_ERROR;
return 0;
}
adin = buffer;
adinlen = len;
}
}
/* repair error state */
if (drbg->state == DRBG_ERROR)
RAND_DRBG_uninstantiate(drbg);
/* repair uninitialized state */
if (drbg->state == DRBG_UNINITIALISED) {
/* reinstantiate drbg */
RAND_DRBG_instantiate(drbg,
(const unsigned char *) ossl_pers_string,
sizeof(ossl_pers_string) - 1);
/* already reseeded. prevent second reseeding below */
reseeded = (drbg->state == DRBG_READY);
}
/* refresh current state if entropy or additional input has been provided */
if (drbg->state == DRBG_READY) {
if (adin != NULL) {
/*
* mix in additional input without reseeding
*
* Similar to RAND_DRBG_reseed(), but the provided additional
* data |adin| is mixed into the current state without pulling
* entropy from the trusted entropy source using get_entropy().
* This is not a reseeding in the strict sense of NIST SP 800-90A.
*/
drbg->meth->reseed(drbg, adin, adinlen, NULL, 0);
} else if (reseeded == 0) {
/* do a full reseeding if it has not been done yet above */
RAND_DRBG_reseed(drbg, NULL, 0, 0);
}
}
rand_pool_free(drbg->seed_pool);
drbg->seed_pool = NULL;
return drbg->state == DRBG_READY;
}
/*
* Generate |outlen| bytes into the buffer at |out|. Reseed if we need
* to or if |prediction_resistance| is set. Additional input can be
* sent in |adin| and |adinlen|.
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success, 0 on failure.
*
*/
int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
int prediction_resistance,
const unsigned char *adin, size_t adinlen)
{
int reseed_required = 0;
if (drbg->state != DRBG_READY) {
/* try to recover from previous errors */
rand_drbg_restart(drbg, NULL, 0, 0);
if (drbg->state == DRBG_ERROR) {
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_IN_ERROR_STATE);
return 0;
}
if (drbg->state == DRBG_UNINITIALISED) {
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_NOT_INSTANTIATED);
return 0;
}
}
if (outlen > drbg->max_request) {
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_REQUEST_TOO_LARGE_FOR_DRBG);
return 0;
}
if (adinlen > drbg->max_adinlen) {
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_ADDITIONAL_INPUT_TOO_LONG);
return 0;
}
if (drbg->fork_count != rand_fork_count) {
drbg->fork_count = rand_fork_count;
reseed_required = 1;
}
if (drbg->reseed_interval > 0) {
if (drbg->reseed_gen_counter >= drbg->reseed_interval)
reseed_required = 1;
}
if (drbg->reseed_time_interval > 0) {
time_t now = time(NULL);
if (now < drbg->reseed_time
|| now - drbg->reseed_time >= drbg->reseed_time_interval)
reseed_required = 1;
}
if (drbg->parent != NULL) {
unsigned int reseed_counter = tsan_load(&drbg->reseed_prop_counter);
if (reseed_counter > 0
&& tsan_load(&drbg->parent->reseed_prop_counter)
!= reseed_counter)
reseed_required = 1;
}
if (reseed_required || prediction_resistance) {
if (!RAND_DRBG_reseed(drbg, adin, adinlen, prediction_resistance)) {
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_RESEED_ERROR);
return 0;
}
adin = NULL;
adinlen = 0;
}
if (!drbg->meth->generate(drbg, out, outlen, adin, adinlen)) {
drbg->state = DRBG_ERROR;
RANDerr(RAND_F_RAND_DRBG_GENERATE, RAND_R_GENERATE_ERROR);
return 0;
}
drbg->reseed_gen_counter++;
return 1;
}
/*
* Generates |outlen| random bytes and stores them in |out|. It will
* using the given |drbg| to generate the bytes.
*
* Requires that drbg->lock is already locked for write, if non-null.
*
* Returns 1 on success 0 on failure.
*/
int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
{
unsigned char *additional = NULL;
size_t additional_len;
size_t chunk;
size_t ret = 0;
if (drbg->adin_pool == NULL) {
if (drbg->type == 0)
goto err;
drbg->adin_pool = rand_pool_new(0, 0, drbg->max_adinlen);
if (drbg->adin_pool == NULL)
goto err;
}
additional_len = rand_drbg_get_additional_data(drbg->adin_pool,
&additional);
for ( ; outlen > 0; outlen -= chunk, out += chunk) {
chunk = outlen;
if (chunk > drbg->max_request)
chunk = drbg->max_request;
ret = RAND_DRBG_generate(drbg, out, chunk, 0, additional, additional_len);
if (!ret)
goto err;
}
ret = 1;
err:
if (additional != NULL)
rand_drbg_cleanup_additional_data(drbg->adin_pool, additional);
return ret;
}
/*
* Set the RAND_DRBG callbacks for obtaining entropy and nonce.
*
* Setting the callbacks is allowed only if the drbg has not been
* initialized yet. Otherwise, the operation will fail.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
RAND_DRBG_get_entropy_fn get_entropy,
RAND_DRBG_cleanup_entropy_fn cleanup_entropy,
RAND_DRBG_get_nonce_fn get_nonce,
RAND_DRBG_cleanup_nonce_fn cleanup_nonce)
{
if (drbg->state != DRBG_UNINITIALISED
|| drbg->parent != NULL)
return 0;
drbg->get_entropy = get_entropy;
drbg->cleanup_entropy = cleanup_entropy;
drbg->get_nonce = get_nonce;
drbg->cleanup_nonce = cleanup_nonce;
return 1;
}
/*
* Set the reseed interval.
*
* The drbg will reseed automatically whenever the number of generate
* requests exceeds the given reseed interval. If the reseed interval
* is 0, then this feature is disabled.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg, unsigned int interval)
{
if (interval > MAX_RESEED_INTERVAL)
return 0;
drbg->reseed_interval = interval;
return 1;
}
/*
* Set the reseed time interval.
*
* The drbg will reseed automatically whenever the time elapsed since
* the last reseeding exceeds the given reseed time interval. For safety,
* a reseeding will also occur if the clock has been reset to a smaller
* value.
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg, time_t interval)
{
if (interval > MAX_RESEED_TIME_INTERVAL)
return 0;
drbg->reseed_time_interval = interval;
return 1;
}
/*
* Set the default values for reseed (time) intervals of new DRBG instances
*
* The default values can be set independently for master DRBG instances
* (without a parent) and slave DRBG instances (with parent).
*
* Returns 1 on success, 0 on failure.
*/
int RAND_DRBG_set_reseed_defaults(
unsigned int _master_reseed_interval,
unsigned int _slave_reseed_interval,
time_t _master_reseed_time_interval,
time_t _slave_reseed_time_interval
)
{
if (_master_reseed_interval > MAX_RESEED_INTERVAL
|| _slave_reseed_interval > MAX_RESEED_INTERVAL)
return 0;
if (_master_reseed_time_interval > MAX_RESEED_TIME_INTERVAL
|| _slave_reseed_time_interval > MAX_RESEED_TIME_INTERVAL)
return 0;
master_reseed_interval = _master_reseed_interval;
slave_reseed_interval = _slave_reseed_interval;
master_reseed_time_interval = _master_reseed_time_interval;
slave_reseed_time_interval = _slave_reseed_time_interval;
return 1;
}
/*
* Locks the given drbg. Locking a drbg which does not have locking
* enabled is considered a successful no-op.
*
* Returns 1 on success, 0 on failure.
*/
int rand_drbg_lock(RAND_DRBG *drbg)
{
if (drbg->lock != NULL)
return CRYPTO_THREAD_write_lock(drbg->lock);
return 1;
}
/*
* Unlocks the given drbg. Unlocking a drbg which does not have locking
* enabled is considered a successful no-op.
*
* Returns 1 on success, 0 on failure.
*/
int rand_drbg_unlock(RAND_DRBG *drbg)
{
if (drbg->lock != NULL)
return CRYPTO_THREAD_unlock(drbg->lock);
return 1;
}
/*
* Enables locking for the given drbg
*
* Locking can only be enabled if the random generator
* is in the uninitialized state.
*
* Returns 1 on success, 0 on failure.
*/
int rand_drbg_enable_locking(RAND_DRBG *drbg)
{
if (drbg->state != DRBG_UNINITIALISED) {
RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
RAND_R_DRBG_ALREADY_INITIALIZED);
return 0;
}
if (drbg->lock == NULL) {
if (drbg->parent != NULL && drbg->parent->lock == NULL) {
RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
RAND_R_PARENT_LOCKING_NOT_ENABLED);
return 0;
}
drbg->lock = CRYPTO_THREAD_lock_new();
if (drbg->lock == NULL) {
RANDerr(RAND_F_RAND_DRBG_ENABLE_LOCKING,
RAND_R_FAILED_TO_CREATE_LOCK);
return 0;
}
}
return 1;
}
/*
* Get and set the EXDATA
*/
int RAND_DRBG_set_ex_data(RAND_DRBG *drbg, int idx, void *arg)
{
return CRYPTO_set_ex_data(&drbg->ex_data, idx, arg);
}
void *RAND_DRBG_get_ex_data(const RAND_DRBG *drbg, int idx)
{
return CRYPTO_get_ex_data(&drbg->ex_data, idx);
}
/*
* The following functions provide a RAND_METHOD that works on the
* global DRBG. They lock.
*/
/*
* Allocates a new global DRBG on the secure heap (if enabled) and
* initializes it with default settings.
*
* Returns a pointer to the new DRBG instance on success, NULL on failure.
*/
static RAND_DRBG *drbg_setup(RAND_DRBG *parent)
{
RAND_DRBG *drbg;
drbg = RAND_DRBG_secure_new(rand_drbg_type, rand_drbg_flags, parent);
if (drbg == NULL)
return NULL;
/* Only the master DRBG needs to have a lock */
if (parent == NULL && rand_drbg_enable_locking(drbg) == 0)
goto err;
/* enable seed propagation */
tsan_store(&drbg->reseed_prop_counter, 1);
/*
* Ignore instantiation error to support just-in-time instantiation.
*
* The state of the drbg will be checked in RAND_DRBG_generate() and
* an automatic recovery is attempted.
*/
(void)RAND_DRBG_instantiate(drbg,
(const unsigned char *) ossl_pers_string,
sizeof(ossl_pers_string) - 1);
return drbg;
err:
RAND_DRBG_free(drbg);
return NULL;
}
/*
* Initialize the global DRBGs on first use.
* Returns 1 on success, 0 on failure.
*/
DEFINE_RUN_ONCE_STATIC(do_rand_drbg_init)
{
/*
* ensure that libcrypto is initialized, otherwise the
* DRBG locks are not cleaned up properly
*/
if (!OPENSSL_init_crypto(0, NULL))
return 0;
if (!CRYPTO_THREAD_init_local(&private_drbg, NULL))
return 0;
if (!CRYPTO_THREAD_init_local(&public_drbg, NULL))
goto err1;
master_drbg = drbg_setup(NULL);
if (master_drbg == NULL)
goto err2;
return 1;
err2:
CRYPTO_THREAD_cleanup_local(&public_drbg);
err1:
CRYPTO_THREAD_cleanup_local(&private_drbg);
return 0;
}
/* Clean up the global DRBGs before exit */
void rand_drbg_cleanup_int(void)
{
if (master_drbg != NULL) {
RAND_DRBG_free(master_drbg);
master_drbg = NULL;
CRYPTO_THREAD_cleanup_local(&private_drbg);
CRYPTO_THREAD_cleanup_local(&public_drbg);
}
}
void drbg_delete_thread_state(void)
{
RAND_DRBG *drbg;
drbg = CRYPTO_THREAD_get_local(&public_drbg);
CRYPTO_THREAD_set_local(&public_drbg, NULL);
RAND_DRBG_free(drbg);
drbg = CRYPTO_THREAD_get_local(&private_drbg);
CRYPTO_THREAD_set_local(&private_drbg, NULL);
RAND_DRBG_free(drbg);
}
/* Implements the default OpenSSL RAND_bytes() method */
static int drbg_bytes(unsigned char *out, int count)
{
int ret;
RAND_DRBG *drbg = RAND_DRBG_get0_public();
if (drbg == NULL)
return 0;
ret = RAND_DRBG_bytes(drbg, out, count);
return ret;
}
/*
* Calculates the minimum length of a full entropy buffer
* which is necessary to seed (i.e. instantiate) the DRBG
* successfully.
*/
size_t rand_drbg_seedlen(RAND_DRBG *drbg)
{
/*
* If no os entropy source is available then RAND_seed(buffer, bufsize)
* is expected to succeed if and only if the buffer length satisfies
* the following requirements, which follow from the calculations
* in RAND_DRBG_instantiate().
*/
size_t min_entropy = drbg->strength;
size_t min_entropylen = drbg->min_entropylen;
/*
* Extra entropy for the random nonce in the absence of a
* get_nonce callback, see comment in RAND_DRBG_instantiate().
*/
if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) {
min_entropy += drbg->strength / 2;
min_entropylen += drbg->min_noncelen;
}
/*
* Convert entropy requirement from bits to bytes
* (dividing by 8 without rounding upwards, because
* all entropy requirements are divisible by 8).
*/
min_entropy >>= 3;
/* Return a value that satisfies both requirements */
return min_entropy > min_entropylen ? min_entropy : min_entropylen;
}
/* Implements the default OpenSSL RAND_add() method */
static int drbg_add(const void *buf, int num, double randomness)
{
int ret = 0;
RAND_DRBG *drbg = RAND_DRBG_get0_master();
size_t buflen;
size_t seedlen;
if (drbg == NULL)
return 0;
if (num < 0 || randomness < 0.0)
return 0;
rand_drbg_lock(drbg);
seedlen = rand_drbg_seedlen(drbg);
buflen = (size_t)num;
if (buflen < seedlen || randomness < (double) seedlen) {
#if defined(OPENSSL_RAND_SEED_NONE)
/*
* If no os entropy source is available, a reseeding will fail
* inevitably. So we use a trick to mix the buffer contents into
* the DRBG state without forcing a reseeding: we generate a
* dummy random byte, using the buffer content as additional data.
* Note: This won't work with RAND_DRBG_FLAG_CTR_NO_DF.
*/
unsigned char dummy[1];
ret = RAND_DRBG_generate(drbg, dummy, sizeof(dummy), 0, buf, buflen);
rand_drbg_unlock(drbg);
return ret;
#else
/*
* If an os entropy source is avaible then we declare the buffer content
* as additional data by setting randomness to zero and trigger a regular
* reseeding.
*/
randomness = 0.0;
#endif
}
if (randomness > (double)seedlen) {
/*
* The purpose of this check is to bound |randomness| by a
* relatively small value in order to prevent an integer
* overflow when multiplying by 8 in the rand_drbg_restart()
* call below. Note that randomness is measured in bytes,
* not bits, so this value corresponds to eight times the
* security strength.
*/
randomness = (double)seedlen;
}
ret = rand_drbg_restart(drbg, buf, buflen, (size_t)(8 * randomness));
rand_drbg_unlock(drbg);
return ret;
}
/* Implements the default OpenSSL RAND_seed() method */
static int drbg_seed(const void *buf, int num)
{
return drbg_add(buf, num, num);
}
/* Implements the default OpenSSL RAND_status() method */
static int drbg_status(void)
{
int ret;
RAND_DRBG *drbg = RAND_DRBG_get0_master();
if (drbg == NULL)
return 0;
rand_drbg_lock(drbg);
ret = drbg->state == DRBG_READY ? 1 : 0;
rand_drbg_unlock(drbg);
return ret;
}
/*
* Get the master DRBG.
* Returns pointer to the DRBG on success, NULL on failure.
*
*/
RAND_DRBG *RAND_DRBG_get0_master(void)
{
if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
return NULL;
return master_drbg;
}
/*
* Get the public DRBG.
* Returns pointer to the DRBG on success, NULL on failure.
*/
RAND_DRBG *RAND_DRBG_get0_public(void)
{
RAND_DRBG *drbg;
if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
return NULL;
drbg = CRYPTO_THREAD_get_local(&public_drbg);
if (drbg == NULL) {
if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND))
return NULL;
drbg = drbg_setup(master_drbg);
CRYPTO_THREAD_set_local(&public_drbg, drbg);
}
return drbg;
}
/*
* Get the private DRBG.
* Returns pointer to the DRBG on success, NULL on failure.
*/
RAND_DRBG *RAND_DRBG_get0_private(void)
{
RAND_DRBG *drbg;
if (!RUN_ONCE(&rand_drbg_init, do_rand_drbg_init))
return NULL;
drbg = CRYPTO_THREAD_get_local(&private_drbg);
if (drbg == NULL) {
if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_RAND))
return NULL;
drbg = drbg_setup(master_drbg);
CRYPTO_THREAD_set_local(&private_drbg, drbg);
}
return drbg;
}
RAND_METHOD rand_meth = {
drbg_seed,
drbg_bytes,
NULL,
drbg_add,
drbg_bytes,
drbg_status
};
RAND_METHOD *RAND_OpenSSL(void)
{
return &rand_meth;
}
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index d8639c4a03f3..108b4f51634d 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -1,859 +1,859 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/opensslconf.h>
#include "internal/rand_int.h"
#include <openssl/engine.h>
#include "internal/thread_once.h"
#include "rand_lcl.h"
#include "e_os.h"
#ifndef OPENSSL_NO_ENGINE
/* non-NULL if default_RAND_meth is ENGINE-provided */
static ENGINE *funct_ref;
static CRYPTO_RWLOCK *rand_engine_lock;
#endif
static CRYPTO_RWLOCK *rand_meth_lock;
static const RAND_METHOD *default_RAND_meth;
static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
int rand_fork_count;
static CRYPTO_RWLOCK *rand_nonce_lock;
static int rand_nonce_count;
static int rand_inited = 0;
#ifdef OPENSSL_RAND_SEED_RDTSC
/*
* IMPORTANT NOTE: It is not currently possible to use this code
* because we are not sure about the amount of randomness it provides.
* Some SP900 tests have been run, but there is internal skepticism.
* So for now this code is not used.
*/
# error "RDTSC enabled? Should not be possible!"
/*
* Acquire entropy from high-speed clock
*
* Since we get some randomness from the low-order bits of the
* high-speed clock, it can help.
*
* Returns the total entropy count, if it exceeds the requested
* entropy count. Otherwise, returns an entropy count of 0.
*/
size_t rand_acquire_entropy_from_tsc(RAND_POOL *pool)
{
unsigned char c;
int i;
if ((OPENSSL_ia32cap_P[0] & (1 << 4)) != 0) {
for (i = 0; i < TSC_READ_COUNT; i++) {
c = (unsigned char)(OPENSSL_rdtsc() & 0xFF);
rand_pool_add(pool, &c, 1, 4);
}
}
return rand_pool_entropy_available(pool);
}
#endif
#ifdef OPENSSL_RAND_SEED_RDCPU
size_t OPENSSL_ia32_rdseed_bytes(unsigned char *buf, size_t len);
size_t OPENSSL_ia32_rdrand_bytes(unsigned char *buf, size_t len);
extern unsigned int OPENSSL_ia32cap_P[];
/*
* Acquire entropy using Intel-specific cpu instructions
*
* Uses the RDSEED instruction if available, otherwise uses
* RDRAND if available.
*
* For the differences between RDSEED and RDRAND, and why RDSEED
* is the preferred choice, see https://goo.gl/oK3KcN
*
* Returns the total entropy count, if it exceeds the requested
* entropy count. Otherwise, returns an entropy count of 0.
*/
size_t rand_acquire_entropy_from_cpu(RAND_POOL *pool)
{
size_t bytes_needed;
unsigned char *buffer;
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
if (bytes_needed > 0) {
buffer = rand_pool_add_begin(pool, bytes_needed);
if (buffer != NULL) {
/* Whichever comes first, use RDSEED, RDRAND or nothing */
if ((OPENSSL_ia32cap_P[2] & (1 << 18)) != 0) {
if (OPENSSL_ia32_rdseed_bytes(buffer, bytes_needed)
== bytes_needed) {
rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
}
} else if ((OPENSSL_ia32cap_P[1] & (1 << (62 - 32))) != 0) {
if (OPENSSL_ia32_rdrand_bytes(buffer, bytes_needed)
== bytes_needed) {
rand_pool_add_end(pool, bytes_needed, 8 * bytes_needed);
}
} else {
rand_pool_add_end(pool, 0, 0);
}
}
}
return rand_pool_entropy_available(pool);
}
#endif
/*
* Implements the get_entropy() callback (see RAND_DRBG_set_callbacks())
*
* If the DRBG has a parent, then the required amount of entropy input
* is fetched using the parent's RAND_DRBG_generate().
*
* Otherwise, the entropy is polled from the system entropy sources
* using rand_pool_acquire_entropy().
*
* If a random pool has been added to the DRBG using RAND_add(), then
* its entropy will be used up first.
*/
size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
unsigned char **pout,
int entropy, size_t min_len, size_t max_len,
int prediction_resistance)
{
size_t ret = 0;
size_t entropy_available = 0;
RAND_POOL *pool;
- if (drbg->parent && drbg->strength > drbg->parent->strength) {
+ if (drbg->parent != NULL && drbg->strength > drbg->parent->strength) {
/*
* We currently don't support the algorithm from NIST SP 800-90C
* 10.1.2 to use a weaker DRBG as source
*/
RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY, RAND_R_PARENT_STRENGTH_TOO_WEAK);
return 0;
}
if (drbg->seed_pool != NULL) {
pool = drbg->seed_pool;
pool->entropy_requested = entropy;
} else {
pool = rand_pool_new(entropy, min_len, max_len);
if (pool == NULL)
return 0;
}
- if (drbg->parent) {
+ if (drbg->parent != NULL) {
size_t bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
unsigned char *buffer = rand_pool_add_begin(pool, bytes_needed);
if (buffer != NULL) {
size_t bytes = 0;
/*
* Get random from parent, include our state as additional input.
* Our lock is already held, but we need to lock our parent before
* generating bits from it. (Note: taking the lock will be a no-op
* if locking if drbg->parent->lock == NULL.)
*/
rand_drbg_lock(drbg->parent);
if (RAND_DRBG_generate(drbg->parent,
buffer, bytes_needed,
prediction_resistance,
NULL, 0) != 0)
bytes = bytes_needed;
drbg->reseed_next_counter
= tsan_load(&drbg->parent->reseed_prop_counter);
rand_drbg_unlock(drbg->parent);
rand_pool_add_end(pool, bytes, 8 * bytes);
entropy_available = rand_pool_entropy_available(pool);
}
} else {
if (prediction_resistance) {
/*
* We don't have any entropy sources that comply with the NIST
* standard to provide prediction resistance (see NIST SP 800-90C,
* Section 5.4).
*/
RANDerr(RAND_F_RAND_DRBG_GET_ENTROPY,
RAND_R_PREDICTION_RESISTANCE_NOT_SUPPORTED);
goto err;
}
/* Get entropy by polling system entropy sources. */
entropy_available = rand_pool_acquire_entropy(pool);
}
if (entropy_available > 0) {
ret = rand_pool_length(pool);
*pout = rand_pool_detach(pool);
}
err:
if (drbg->seed_pool == NULL)
rand_pool_free(pool);
return ret;
}
/*
* Implements the cleanup_entropy() callback (see RAND_DRBG_set_callbacks())
*
*/
void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
unsigned char *out, size_t outlen)
{
if (drbg->seed_pool == NULL)
OPENSSL_secure_clear_free(out, outlen);
}
/*
* Implements the get_nonce() callback (see RAND_DRBG_set_callbacks())
*
*/
size_t rand_drbg_get_nonce(RAND_DRBG *drbg,
unsigned char **pout,
int entropy, size_t min_len, size_t max_len)
{
size_t ret = 0;
RAND_POOL *pool;
struct {
void * instance;
int count;
- } data = { 0 };
+ } data = { NULL, 0 };
pool = rand_pool_new(0, min_len, max_len);
if (pool == NULL)
return 0;
if (rand_pool_add_nonce_data(pool) == 0)
goto err;
data.instance = drbg;
CRYPTO_atomic_add(&rand_nonce_count, 1, &data.count, rand_nonce_lock);
if (rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0) == 0)
goto err;
ret = rand_pool_length(pool);
*pout = rand_pool_detach(pool);
err:
rand_pool_free(pool);
return ret;
}
/*
* Implements the cleanup_nonce() callback (see RAND_DRBG_set_callbacks())
*
*/
void rand_drbg_cleanup_nonce(RAND_DRBG *drbg,
unsigned char *out, size_t outlen)
{
OPENSSL_secure_clear_free(out, outlen);
}
/*
* Generate additional data that can be used for the drbg. The data does
* not need to contain entropy, but it's useful if it contains at least
* some bits that are unpredictable.
*
* Returns 0 on failure.
*
* On success it allocates a buffer at |*pout| and returns the length of
* the data. The buffer should get freed using OPENSSL_secure_clear_free().
*/
size_t rand_drbg_get_additional_data(RAND_POOL *pool, unsigned char **pout)
{
size_t ret = 0;
if (rand_pool_add_additional_data(pool) == 0)
goto err;
ret = rand_pool_length(pool);
*pout = rand_pool_detach(pool);
err:
return ret;
}
void rand_drbg_cleanup_additional_data(RAND_POOL *pool, unsigned char *out)
{
rand_pool_reattach(pool, out);
}
void rand_fork(void)
{
rand_fork_count++;
}
DEFINE_RUN_ONCE_STATIC(do_rand_init)
{
#ifndef OPENSSL_NO_ENGINE
rand_engine_lock = CRYPTO_THREAD_lock_new();
if (rand_engine_lock == NULL)
return 0;
#endif
rand_meth_lock = CRYPTO_THREAD_lock_new();
if (rand_meth_lock == NULL)
goto err1;
rand_nonce_lock = CRYPTO_THREAD_lock_new();
if (rand_nonce_lock == NULL)
goto err2;
if (!rand_pool_init())
goto err3;
rand_inited = 1;
return 1;
err3:
CRYPTO_THREAD_lock_free(rand_nonce_lock);
rand_nonce_lock = NULL;
err2:
CRYPTO_THREAD_lock_free(rand_meth_lock);
rand_meth_lock = NULL;
err1:
#ifndef OPENSSL_NO_ENGINE
CRYPTO_THREAD_lock_free(rand_engine_lock);
rand_engine_lock = NULL;
#endif
return 0;
}
void rand_cleanup_int(void)
{
const RAND_METHOD *meth = default_RAND_meth;
if (!rand_inited)
return;
if (meth != NULL && meth->cleanup != NULL)
meth->cleanup();
RAND_set_rand_method(NULL);
rand_pool_cleanup();
#ifndef OPENSSL_NO_ENGINE
CRYPTO_THREAD_lock_free(rand_engine_lock);
rand_engine_lock = NULL;
#endif
CRYPTO_THREAD_lock_free(rand_meth_lock);
rand_meth_lock = NULL;
CRYPTO_THREAD_lock_free(rand_nonce_lock);
rand_nonce_lock = NULL;
rand_inited = 0;
}
/*
* RAND_close_seed_files() ensures that any seed file decriptors are
* closed after use.
*/
void RAND_keep_random_devices_open(int keep)
{
if (RUN_ONCE(&rand_init, do_rand_init))
rand_pool_keep_random_devices_open(keep);
}
/*
* RAND_poll() reseeds the default RNG using random input
*
* The random input is obtained from polling various entropy
* sources which depend on the operating system and are
* configurable via the --with-rand-seed configure option.
*/
int RAND_poll(void)
{
int ret = 0;
RAND_POOL *pool = NULL;
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth == RAND_OpenSSL()) {
/* fill random pool and seed the master DRBG */
RAND_DRBG *drbg = RAND_DRBG_get0_master();
if (drbg == NULL)
return 0;
rand_drbg_lock(drbg);
ret = rand_drbg_restart(drbg, NULL, 0, 0);
rand_drbg_unlock(drbg);
return ret;
} else {
/* fill random pool and seed the current legacy RNG */
pool = rand_pool_new(RAND_DRBG_STRENGTH,
- RAND_DRBG_STRENGTH / 8,
+ (RAND_DRBG_STRENGTH + 7) / 8,
RAND_POOL_MAX_LENGTH);
if (pool == NULL)
return 0;
if (rand_pool_acquire_entropy(pool) == 0)
goto err;
if (meth->add == NULL
|| meth->add(rand_pool_buffer(pool),
rand_pool_length(pool),
(rand_pool_entropy(pool) / 8.0)) == 0)
goto err;
ret = 1;
}
err:
rand_pool_free(pool);
return ret;
}
/*
* Allocate memory and initialize a new random pool
*/
RAND_POOL *rand_pool_new(int entropy_requested, size_t min_len, size_t max_len)
{
RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool));
if (pool == NULL) {
RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
pool->min_len = min_len;
pool->max_len = (max_len > RAND_POOL_MAX_LENGTH) ?
RAND_POOL_MAX_LENGTH : max_len;
pool->buffer = OPENSSL_secure_zalloc(pool->max_len);
if (pool->buffer == NULL) {
RANDerr(RAND_F_RAND_POOL_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
pool->entropy_requested = entropy_requested;
return pool;
err:
OPENSSL_free(pool);
return NULL;
}
/*
* Attach new random pool to the given buffer
*
* This function is intended to be used only for feeding random data
* provided by RAND_add() and RAND_seed() into the <master> DRBG.
*/
RAND_POOL *rand_pool_attach(const unsigned char *buffer, size_t len,
size_t entropy)
{
RAND_POOL *pool = OPENSSL_zalloc(sizeof(*pool));
if (pool == NULL) {
RANDerr(RAND_F_RAND_POOL_ATTACH, ERR_R_MALLOC_FAILURE);
return NULL;
}
/*
* The const needs to be cast away, but attached buffers will not be
* modified (in contrary to allocated buffers which are zeroed and
* freed in the end).
*/
pool->buffer = (unsigned char *) buffer;
pool->len = len;
pool->attached = 1;
pool->min_len = pool->max_len = pool->len;
pool->entropy = entropy;
return pool;
}
/*
* Free |pool|, securely erasing its buffer.
*/
void rand_pool_free(RAND_POOL *pool)
{
if (pool == NULL)
return;
/*
* Although it would be advisable from a cryptographical viewpoint,
* we are not allowed to clear attached buffers, since they are passed
* to rand_pool_attach() as `const unsigned char*`.
* (see corresponding comment in rand_pool_attach()).
*/
if (!pool->attached)
OPENSSL_secure_clear_free(pool->buffer, pool->max_len);
OPENSSL_free(pool);
}
/*
* Return the |pool|'s buffer to the caller (readonly).
*/
const unsigned char *rand_pool_buffer(RAND_POOL *pool)
{
return pool->buffer;
}
/*
* Return the |pool|'s entropy to the caller.
*/
size_t rand_pool_entropy(RAND_POOL *pool)
{
return pool->entropy;
}
/*
* Return the |pool|'s buffer length to the caller.
*/
size_t rand_pool_length(RAND_POOL *pool)
{
return pool->len;
}
/*
* Detach the |pool| buffer and return it to the caller.
* It's the responsibility of the caller to free the buffer
* using OPENSSL_secure_clear_free() or to re-attach it
* again to the pool using rand_pool_reattach().
*/
unsigned char *rand_pool_detach(RAND_POOL *pool)
{
unsigned char *ret = pool->buffer;
pool->buffer = NULL;
pool->entropy = 0;
return ret;
}
/*
* Re-attach the |pool| buffer. It is only allowed to pass
* the |buffer| which was previously detached from the same pool.
*/
void rand_pool_reattach(RAND_POOL *pool, unsigned char *buffer)
{
pool->buffer = buffer;
OPENSSL_cleanse(pool->buffer, pool->len);
pool->len = 0;
}
/*
* If |entropy_factor| bits contain 1 bit of entropy, how many bytes does one
* need to obtain at least |bits| bits of entropy?
*/
#define ENTROPY_TO_BYTES(bits, entropy_factor) \
(((bits) * (entropy_factor) + 7) / 8)
/*
* Checks whether the |pool|'s entropy is available to the caller.
* This is the case when entropy count and buffer length are high enough.
* Returns
*
* |entropy| if the entropy count and buffer size is large enough
* 0 otherwise
*/
size_t rand_pool_entropy_available(RAND_POOL *pool)
{
if (pool->entropy < pool->entropy_requested)
return 0;
if (pool->len < pool->min_len)
return 0;
return pool->entropy;
}
/*
* Returns the (remaining) amount of entropy needed to fill
* the random pool.
*/
size_t rand_pool_entropy_needed(RAND_POOL *pool)
{
if (pool->entropy < pool->entropy_requested)
return pool->entropy_requested - pool->entropy;
return 0;
}
/*
* Returns the number of bytes needed to fill the pool, assuming
* the input has 1 / |entropy_factor| entropy bits per data bit.
* In case of an error, 0 is returned.
*/
size_t rand_pool_bytes_needed(RAND_POOL *pool, unsigned int entropy_factor)
{
size_t bytes_needed;
size_t entropy_needed = rand_pool_entropy_needed(pool);
if (entropy_factor < 1) {
RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_ARGUMENT_OUT_OF_RANGE);
return 0;
}
bytes_needed = ENTROPY_TO_BYTES(entropy_needed, entropy_factor);
if (bytes_needed > pool->max_len - pool->len) {
/* not enough space left */
RANDerr(RAND_F_RAND_POOL_BYTES_NEEDED, RAND_R_RANDOM_POOL_OVERFLOW);
return 0;
}
if (pool->len < pool->min_len &&
bytes_needed < pool->min_len - pool->len)
/* to meet the min_len requirement */
bytes_needed = pool->min_len - pool->len;
return bytes_needed;
}
/* Returns the remaining number of bytes available */
size_t rand_pool_bytes_remaining(RAND_POOL *pool)
{
return pool->max_len - pool->len;
}
/*
* Add random bytes to the random pool.
*
* It is expected that the |buffer| contains |len| bytes of
* random input which contains at least |entropy| bits of
* randomness.
*
* Returns 1 if the added amount is adequate, otherwise 0
*/
int rand_pool_add(RAND_POOL *pool,
const unsigned char *buffer, size_t len, size_t entropy)
{
if (len > pool->max_len - pool->len) {
RANDerr(RAND_F_RAND_POOL_ADD, RAND_R_ENTROPY_INPUT_TOO_LONG);
return 0;
}
if (pool->buffer == NULL) {
RANDerr(RAND_F_RAND_POOL_ADD, ERR_R_INTERNAL_ERROR);
return 0;
}
if (len > 0) {
memcpy(pool->buffer + pool->len, buffer, len);
pool->len += len;
pool->entropy += entropy;
}
return 1;
}
/*
* Start to add random bytes to the random pool in-place.
*
* Reserves the next |len| bytes for adding random bytes in-place
* and returns a pointer to the buffer.
* The caller is allowed to copy up to |len| bytes into the buffer.
* If |len| == 0 this is considered a no-op and a NULL pointer
* is returned without producing an error message.
*
* After updating the buffer, rand_pool_add_end() needs to be called
* to finish the udpate operation (see next comment).
*/
unsigned char *rand_pool_add_begin(RAND_POOL *pool, size_t len)
{
if (len == 0)
return NULL;
if (len > pool->max_len - pool->len) {
RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, RAND_R_RANDOM_POOL_OVERFLOW);
return NULL;
}
if (pool->buffer == NULL) {
RANDerr(RAND_F_RAND_POOL_ADD_BEGIN, ERR_R_INTERNAL_ERROR);
- return 0;
+ return NULL;
}
return pool->buffer + pool->len;
}
/*
* Finish to add random bytes to the random pool in-place.
*
* Finishes an in-place update of the random pool started by
* rand_pool_add_begin() (see previous comment).
* It is expected that |len| bytes of random input have been added
* to the buffer which contain at least |entropy| bits of randomness.
* It is allowed to add less bytes than originally reserved.
*/
int rand_pool_add_end(RAND_POOL *pool, size_t len, size_t entropy)
{
if (len > pool->max_len - pool->len) {
RANDerr(RAND_F_RAND_POOL_ADD_END, RAND_R_RANDOM_POOL_OVERFLOW);
return 0;
}
if (len > 0) {
pool->len += len;
pool->entropy += entropy;
}
return 1;
}
int RAND_set_rand_method(const RAND_METHOD *meth)
{
if (!RUN_ONCE(&rand_init, do_rand_init))
return 0;
CRYPTO_THREAD_write_lock(rand_meth_lock);
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(funct_ref);
funct_ref = NULL;
#endif
default_RAND_meth = meth;
CRYPTO_THREAD_unlock(rand_meth_lock);
return 1;
}
const RAND_METHOD *RAND_get_rand_method(void)
{
const RAND_METHOD *tmp_meth = NULL;
if (!RUN_ONCE(&rand_init, do_rand_init))
return NULL;
CRYPTO_THREAD_write_lock(rand_meth_lock);
if (default_RAND_meth == NULL) {
#ifndef OPENSSL_NO_ENGINE
ENGINE *e;
/* If we have an engine that can do RAND, use it. */
if ((e = ENGINE_get_default_RAND()) != NULL
&& (tmp_meth = ENGINE_get_RAND(e)) != NULL) {
funct_ref = e;
default_RAND_meth = tmp_meth;
} else {
ENGINE_finish(e);
default_RAND_meth = &rand_meth;
}
#else
default_RAND_meth = &rand_meth;
#endif
}
tmp_meth = default_RAND_meth;
CRYPTO_THREAD_unlock(rand_meth_lock);
return tmp_meth;
}
#ifndef OPENSSL_NO_ENGINE
int RAND_set_rand_engine(ENGINE *engine)
{
const RAND_METHOD *tmp_meth = NULL;
if (!RUN_ONCE(&rand_init, do_rand_init))
return 0;
if (engine != NULL) {
if (!ENGINE_init(engine))
return 0;
tmp_meth = ENGINE_get_RAND(engine);
if (tmp_meth == NULL) {
ENGINE_finish(engine);
return 0;
}
}
CRYPTO_THREAD_write_lock(rand_engine_lock);
/* This function releases any prior ENGINE so call it first */
RAND_set_rand_method(tmp_meth);
funct_ref = engine;
CRYPTO_THREAD_unlock(rand_engine_lock);
return 1;
}
#endif
void RAND_seed(const void *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth->seed != NULL)
meth->seed(buf, num);
}
void RAND_add(const void *buf, int num, double randomness)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth->add != NULL)
meth->add(buf, num, randomness);
}
/*
* This function is not part of RAND_METHOD, so if we're not using
* the default method, then just call RAND_bytes(). Otherwise make
* sure we're instantiated and use the private DRBG.
*/
int RAND_priv_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
RAND_DRBG *drbg;
int ret;
if (meth != RAND_OpenSSL())
return RAND_bytes(buf, num);
drbg = RAND_DRBG_get0_private();
if (drbg == NULL)
return 0;
ret = RAND_DRBG_bytes(drbg, buf, num);
return ret;
}
int RAND_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth->bytes != NULL)
return meth->bytes(buf, num);
RANDerr(RAND_F_RAND_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED);
return -1;
}
#if OPENSSL_API_COMPAT < 0x10100000L
int RAND_pseudo_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth->pseudorand != NULL)
return meth->pseudorand(buf, num);
return -1;
}
#endif
int RAND_status(void)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth->status != NULL)
return meth->status();
return 0;
}
diff --git a/crypto/rand/rand_unix.c b/crypto/rand/rand_unix.c
index 9cbc9ade77fa..4710dbb2d101 100644
--- a/crypto/rand/rand_unix.c
+++ b/crypto/rand/rand_unix.c
@@ -1,707 +1,730 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include "e_os.h"
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/rand.h>
#include "rand_lcl.h"
#include "internal/rand_int.h"
#include <stdio.h>
#include "internal/dso.h"
#if defined(__linux)
-# include <sys/syscall.h>
+# include <asm/unistd.h>
#endif
#if defined(__FreeBSD__)
# include <sys/types.h>
# include <sys/sysctl.h>
# include <sys/param.h>
#endif
#if defined(__OpenBSD__) || defined(__NetBSD__)
# include <sys/param.h>
#endif
#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
# include <sys/time.h>
static uint64_t get_time_stamp(void);
static uint64_t get_timer_bits(void);
/* Macro to convert two thirty two bit values into a sixty four bit one */
# define TWO32TO64(a, b) ((((uint64_t)(a)) << 32) + (b))
/*
* Check for the existence and support of POSIX timers. The standard
* says that the _POSIX_TIMERS macro will have a positive value if they
* are available.
*
* However, we want an additional constraint: that the timer support does
* not require an extra library dependency. Early versions of glibc
* require -lrt to be specified on the link line to access the timers,
* so this needs to be checked for.
*
* It is worse because some libraries define __GLIBC__ but don't
* support the version testing macro (e.g. uClibc). This means
* an extra check is needed.
*
* The final condition is:
* "have posix timers and either not glibc or glibc without -lrt"
*
* The nested #if sequences are required to avoid using a parameterised
* macro that might be undefined.
*/
# undef OSSL_POSIX_TIMER_OKAY
# if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
# if defined(__GLIBC__)
# if defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 17)
# define OSSL_POSIX_TIMER_OKAY
# endif
# endif
# else
# define OSSL_POSIX_TIMER_OKAY
# endif
# endif
#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */
#if defined(OPENSSL_RAND_SEED_NONE)
/* none means none. this simplifies the following logic */
# undef OPENSSL_RAND_SEED_OS
# undef OPENSSL_RAND_SEED_GETRANDOM
# undef OPENSSL_RAND_SEED_LIBRANDOM
# undef OPENSSL_RAND_SEED_DEVRANDOM
# undef OPENSSL_RAND_SEED_RDTSC
# undef OPENSSL_RAND_SEED_RDCPU
# undef OPENSSL_RAND_SEED_EGD
#endif
#if (defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)) && \
!defined(OPENSSL_RAND_SEED_NONE)
# error "UEFI and VXWorks only support seeding NONE"
#endif
#if defined(OPENSSL_SYS_VXWORKS)
/* empty implementation */
int rand_pool_init(void)
{
return 1;
}
void rand_pool_cleanup(void)
{
}
void rand_pool_keep_random_devices_open(int keep)
{
}
size_t rand_pool_acquire_entropy(RAND_POOL *pool)
{
return rand_pool_entropy_available(pool);
}
#endif
#if !(defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) \
|| defined(OPENSSL_SYS_VMS) || defined(OPENSSL_SYS_VXWORKS) \
|| defined(OPENSSL_SYS_UEFI))
# if defined(OPENSSL_SYS_VOS)
# ifndef OPENSSL_RAND_SEED_OS
# error "Unsupported seeding method configured; must be os"
# endif
# if defined(OPENSSL_SYS_VOS_HPPA) && defined(OPENSSL_SYS_VOS_IA32)
# error "Unsupported HP-PA and IA32 at the same time."
# endif
# if !defined(OPENSSL_SYS_VOS_HPPA) && !defined(OPENSSL_SYS_VOS_IA32)
# error "Must have one of HP-PA or IA32"
# endif
/*
* The following algorithm repeatedly samples the real-time clock (RTC) to
* generate a sequence of unpredictable data. The algorithm relies upon the
* uneven execution speed of the code (due to factors such as cache misses,
* interrupts, bus activity, and scheduling) and upon the rather large
* relative difference between the speed of the clock and the rate at which
* it can be read. If it is ported to an environment where execution speed
* is more constant or where the RTC ticks at a much slower rate, or the
* clock can be read with fewer instructions, it is likely that the results
* would be far more predictable. This should only be used for legacy
* platforms.
*
* As a precaution, we assume only 2 bits of entropy per byte.
*/
size_t rand_pool_acquire_entropy(RAND_POOL *pool)
{
short int code;
int i, k;
size_t bytes_needed;
struct timespec ts;
unsigned char v;
# ifdef OPENSSL_SYS_VOS_HPPA
long duration;
extern void s$sleep(long *_duration, short int *_code);
# else
long long duration;
extern void s$sleep2(long long *_duration, short int *_code);
# endif
bytes_needed = rand_pool_bytes_needed(pool, 4 /*entropy_factor*/);
for (i = 0; i < bytes_needed; i++) {
/*
* burn some cpu; hope for interrupts, cache collisions, bus
* interference, etc.
*/
for (k = 0; k < 99; k++)
ts.tv_nsec = random();
# ifdef OPENSSL_SYS_VOS_HPPA
/* sleep for 1/1024 of a second (976 us). */
duration = 1;
s$sleep(&duration, &code);
# else
/* sleep for 1/65536 of a second (15 us). */
duration = 1;
s$sleep2(&duration, &code);
# endif
/* Get wall clock time, take 8 bits. */
clock_gettime(CLOCK_REALTIME, &ts);
v = (unsigned char)(ts.tv_nsec & 0xFF);
rand_pool_add(pool, arg, &v, sizeof(v) , 2);
}
return rand_pool_entropy_available(pool);
}
void rand_pool_cleanup(void)
{
}
void rand_pool_keep_random_devices_open(int keep)
{
}
# else
# if defined(OPENSSL_RAND_SEED_EGD) && \
(defined(OPENSSL_NO_EGD) || !defined(DEVRANDOM_EGD))
# error "Seeding uses EGD but EGD is turned off or no device given"
# endif
# if defined(OPENSSL_RAND_SEED_DEVRANDOM) && !defined(DEVRANDOM)
# error "Seeding uses urandom but DEVRANDOM is not configured"
# endif
# if defined(OPENSSL_RAND_SEED_OS)
# if !defined(DEVRANDOM)
# error "OS seeding requires DEVRANDOM to be configured"
# endif
# define OPENSSL_RAND_SEED_GETRANDOM
# define OPENSSL_RAND_SEED_DEVRANDOM
# endif
# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
# error "librandom not (yet) supported"
# endif
# if (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
/*
* sysctl_random(): Use sysctl() to read a random number from the kernel
* Returns the number of bytes returned in buf on success, -1 on failure.
*/
static ssize_t sysctl_random(char *buf, size_t buflen)
{
int mib[2];
size_t done = 0;
size_t len;
/*
* Note: sign conversion between size_t and ssize_t is safe even
* without a range check, see comment in syscall_random()
*/
/*
* On FreeBSD old implementations returned longs, newer versions support
* variable sizes up to 256 byte. The code below would not work properly
* when the sysctl returns long and we want to request something not a
* multiple of longs, which should never be the case.
*/
if (!ossl_assert(buflen % sizeof(long) == 0)) {
errno = EINVAL;
return -1;
}
/*
* On NetBSD before 4.0 KERN_ARND was an alias for KERN_URND, and only
* filled in an int, leaving the rest uninitialized. Since NetBSD 4.0
* it returns a variable number of bytes with the current version supporting
* up to 256 bytes.
* Just return an error on older NetBSD versions.
*/
#if defined(__NetBSD__) && __NetBSD_Version__ < 400000000
errno = ENOSYS;
return -1;
#endif
mib[0] = CTL_KERN;
mib[1] = KERN_ARND;
do {
len = buflen;
if (sysctl(mib, 2, buf, &len, NULL, 0) == -1)
return done > 0 ? done : -1;
done += len;
buf += len;
buflen -= len;
} while (buflen > 0);
return done;
}
# endif
# if defined(OPENSSL_RAND_SEED_GETRANDOM)
/*
* syscall_random(): Try to get random data using a system call
* returns the number of bytes returned in buf, or < 0 on error.
*/
static ssize_t syscall_random(void *buf, size_t buflen)
{
/*
* Note: 'buflen' equals the size of the buffer which is used by the
* get_entropy() callback of the RAND_DRBG. It is roughly bounded by
*
* 2 * RAND_POOL_FACTOR * (RAND_DRBG_STRENGTH / 8) = 2^14
*
* which is way below the OSSL_SSIZE_MAX limit. Therefore sign conversion
* between size_t and ssize_t is safe even without a range check.
*/
/*
* Do runtime detection to find getentropy().
*
* Known OSs that should support this:
* - Darwin since 16 (OSX 10.12, IOS 10.0).
* - Solaris since 11.3
* - OpenBSD since 5.6
* - Linux since 3.17 with glibc 2.25
* - FreeBSD since 12.0 (1200061)
*/
# if defined(__GNUC__) && __GNUC__>=2 && defined(__ELF__) && !defined(__hpux)
extern int getentropy(void *buffer, size_t length) __attribute__((weak));
if (getentropy != NULL)
return getentropy(buf, buflen) == 0 ? (ssize_t)buflen : -1;
# else
union {
void *p;
int (*f)(void *buffer, size_t length);
} p_getentropy;
/*
* We could cache the result of the lookup, but we normally don't
* call this function often.
*/
ERR_set_mark();
p_getentropy.p = DSO_global_lookup("getentropy");
ERR_pop_to_mark();
if (p_getentropy.p != NULL)
return p_getentropy.f(buf, buflen) == 0 ? (ssize_t)buflen : -1;
# endif
/* Linux supports this since version 3.17 */
-# if defined(__linux) && defined(SYS_getrandom)
- return syscall(SYS_getrandom, buf, buflen, 0);
+# if defined(__linux) && defined(__NR_getrandom)
+ return syscall(__NR_getrandom, buf, buflen, 0);
# elif (defined(__FreeBSD__) || defined(__NetBSD__)) && defined(KERN_ARND)
return sysctl_random(buf, buflen);
# else
errno = ENOSYS;
return -1;
# endif
}
# endif /* defined(OPENSSL_RAND_SEED_GETRANDOM) */
# if defined(OPENSSL_RAND_SEED_DEVRANDOM)
static const char *random_device_paths[] = { DEVRANDOM };
static struct random_device {
int fd;
dev_t dev;
ino_t ino;
mode_t mode;
dev_t rdev;
} random_devices[OSSL_NELEM(random_device_paths)];
static int keep_random_devices_open = 1;
/*
* Verify that the file descriptor associated with the random source is
* still valid. The rationale for doing this is the fact that it is not
* uncommon for daemons to close all open file handles when daemonizing.
* So the handle might have been closed or even reused for opening
* another file.
*/
static int check_random_device(struct random_device * rd)
{
struct stat st;
return rd->fd != -1
&& fstat(rd->fd, &st) != -1
&& rd->dev == st.st_dev
&& rd->ino == st.st_ino
&& ((rd->mode ^ st.st_mode) & ~(S_IRWXU | S_IRWXG | S_IRWXO)) == 0
&& rd->rdev == st.st_rdev;
}
/*
* Open a random device if required and return its file descriptor or -1 on error
*/
static int get_random_device(size_t n)
{
struct stat st;
struct random_device * rd = &random_devices[n];
/* reuse existing file descriptor if it is (still) valid */
if (check_random_device(rd))
return rd->fd;
/* open the random device ... */
if ((rd->fd = open(random_device_paths[n], O_RDONLY)) == -1)
return rd->fd;
/* ... and cache its relevant stat(2) data */
if (fstat(rd->fd, &st) != -1) {
rd->dev = st.st_dev;
rd->ino = st.st_ino;
rd->mode = st.st_mode;
rd->rdev = st.st_rdev;
} else {
close(rd->fd);
rd->fd = -1;
}
return rd->fd;
}
/*
* Close a random device making sure it is a random device
*/
static void close_random_device(size_t n)
{
struct random_device * rd = &random_devices[n];
if (check_random_device(rd))
close(rd->fd);
rd->fd = -1;
}
int rand_pool_init(void)
{
size_t i;
for (i = 0; i < OSSL_NELEM(random_devices); i++)
random_devices[i].fd = -1;
return 1;
}
void rand_pool_cleanup(void)
{
size_t i;
for (i = 0; i < OSSL_NELEM(random_devices); i++)
close_random_device(i);
}
void rand_pool_keep_random_devices_open(int keep)
{
if (!keep)
rand_pool_cleanup();
keep_random_devices_open = keep;
}
# else /* !defined(OPENSSL_RAND_SEED_DEVRANDOM) */
int rand_pool_init(void)
{
return 1;
}
void rand_pool_cleanup(void)
{
}
void rand_pool_keep_random_devices_open(int keep)
{
}
# endif /* defined(OPENSSL_RAND_SEED_DEVRANDOM) */
/*
* Try the various seeding methods in turn, exit when successful.
*
* TODO(DRBG): If more than one entropy source is available, is it
* preferable to stop as soon as enough entropy has been collected
* (as favored by @rsalz) or should one rather be defensive and add
* more entropy than requested and/or from different sources?
*
* Currently, the user can select multiple entropy sources in the
* configure step, yet in practice only the first available source
* will be used. A more flexible solution has been requested, but
* currently it is not clear how this can be achieved without
* overengineering the problem. There are many parameters which
* could be taken into account when selecting the order and amount
* of input from the different entropy sources (trust, quality,
* possibility of blocking).
*/
size_t rand_pool_acquire_entropy(RAND_POOL *pool)
{
# if defined(OPENSSL_RAND_SEED_NONE)
return rand_pool_entropy_available(pool);
# else
size_t bytes_needed;
size_t entropy_available = 0;
unsigned char *buffer;
# if defined(OPENSSL_RAND_SEED_GETRANDOM)
{
ssize_t bytes;
/* Maximum allowed number of consecutive unsuccessful attempts */
int attempts = 3;
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
while (bytes_needed != 0 && attempts-- > 0) {
buffer = rand_pool_add_begin(pool, bytes_needed);
bytes = syscall_random(buffer, bytes_needed);
if (bytes > 0) {
rand_pool_add_end(pool, bytes, 8 * bytes);
bytes_needed -= bytes;
attempts = 3; /* reset counter after successful attempt */
} else if (bytes < 0 && errno != EINTR) {
break;
}
}
}
entropy_available = rand_pool_entropy_available(pool);
if (entropy_available > 0)
return entropy_available;
# endif
# if defined(OPENSSL_RAND_SEED_LIBRANDOM)
{
/* Not yet implemented. */
}
# endif
# if defined(OPENSSL_RAND_SEED_DEVRANDOM)
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
{
size_t i;
+#ifdef DEVRANDOM_WAIT
+ static int wait_done = 0;
+
+ /*
+ * On some implementations reading from /dev/urandom is possible
+ * before it is initialized. Therefore we wait for /dev/random
+ * to be readable to make sure /dev/urandom is initialized.
+ */
+ if (!wait_done && bytes_needed > 0) {
+ int f = open(DEVRANDOM_WAIT, O_RDONLY);
+
+ if (f >= 0) {
+ fd_set fds;
+
+ FD_ZERO(&fds);
+ FD_SET(f, &fds);
+ while (select(f+1, &fds, NULL, NULL, NULL) < 0
+ && errno == EINTR);
+ close(f);
+ }
+ wait_done = 1;
+ }
+#endif
for (i = 0; bytes_needed > 0 && i < OSSL_NELEM(random_device_paths); i++) {
ssize_t bytes = 0;
/* Maximum allowed number of consecutive unsuccessful attempts */
int attempts = 3;
const int fd = get_random_device(i);
if (fd == -1)
continue;
while (bytes_needed != 0 && attempts-- > 0) {
buffer = rand_pool_add_begin(pool, bytes_needed);
bytes = read(fd, buffer, bytes_needed);
if (bytes > 0) {
rand_pool_add_end(pool, bytes, 8 * bytes);
bytes_needed -= bytes;
attempts = 3; /* reset counter after successful attempt */
} else if (bytes < 0 && errno != EINTR) {
break;
}
}
if (bytes < 0 || !keep_random_devices_open)
close_random_device(i);
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
}
entropy_available = rand_pool_entropy_available(pool);
if (entropy_available > 0)
return entropy_available;
}
# endif
# if defined(OPENSSL_RAND_SEED_RDTSC)
entropy_available = rand_acquire_entropy_from_tsc(pool);
if (entropy_available > 0)
return entropy_available;
# endif
# if defined(OPENSSL_RAND_SEED_RDCPU)
entropy_available = rand_acquire_entropy_from_cpu(pool);
if (entropy_available > 0)
return entropy_available;
# endif
# if defined(OPENSSL_RAND_SEED_EGD)
bytes_needed = rand_pool_bytes_needed(pool, 1 /*entropy_factor*/);
if (bytes_needed > 0) {
static const char *paths[] = { DEVRANDOM_EGD, NULL };
int i;
for (i = 0; paths[i] != NULL; i++) {
buffer = rand_pool_add_begin(pool, bytes_needed);
if (buffer != NULL) {
size_t bytes = 0;
int num = RAND_query_egd_bytes(paths[i],
buffer, (int)bytes_needed);
if (num == (int)bytes_needed)
bytes = bytes_needed;
rand_pool_add_end(pool, bytes, 8 * bytes);
entropy_available = rand_pool_entropy_available(pool);
}
if (entropy_available > 0)
return entropy_available;
}
}
# endif
return rand_pool_entropy_available(pool);
# endif
}
# endif
#endif
#if defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__)
int rand_pool_add_nonce_data(RAND_POOL *pool)
{
struct {
pid_t pid;
CRYPTO_THREAD_ID tid;
uint64_t time;
} data = { 0 };
/*
* Add process id, thread id, and a high resolution timestamp to
* ensure that the nonce is unique with high probability for
* different process instances.
*/
data.pid = getpid();
data.tid = CRYPTO_THREAD_get_current_id();
data.time = get_time_stamp();
return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
}
int rand_pool_add_additional_data(RAND_POOL *pool)
{
struct {
CRYPTO_THREAD_ID tid;
uint64_t time;
} data = { 0 };
/*
* Add some noise from the thread id and a high resolution timer.
* The thread id adds a little randomness if the drbg is accessed
* concurrently (which is the case for the <master> drbg).
*/
data.tid = CRYPTO_THREAD_get_current_id();
data.time = get_timer_bits();
return rand_pool_add(pool, (unsigned char *)&data, sizeof(data), 0);
}
/*
* Get the current time with the highest possible resolution
*
* The time stamp is added to the nonce, so it is optimized for not repeating.
* The current time is ideal for this purpose, provided the computer's clock
* is synchronized.
*/
static uint64_t get_time_stamp(void)
{
# if defined(OSSL_POSIX_TIMER_OKAY)
{
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
return TWO32TO64(ts.tv_sec, ts.tv_nsec);
}
# endif
# if defined(__unix__) \
|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) == 0)
return TWO32TO64(tv.tv_sec, tv.tv_usec);
}
# endif
return time(NULL);
}
/*
* Get an arbitrary timer value of the highest possible resolution
*
* The timer value is added as random noise to the additional data,
* which is not considered a trusted entropy sourec, so any result
* is acceptable.
*/
static uint64_t get_timer_bits(void)
{
uint64_t res = OPENSSL_rdtsc();
if (res != 0)
return res;
# if defined(__sun) || defined(__hpux)
return gethrtime();
# elif defined(_AIX)
{
timebasestruct_t t;
read_wall_time(&t, TIMEBASE_SZ);
return TWO32TO64(t.tb_high, t.tb_low);
}
# elif defined(OSSL_POSIX_TIMER_OKAY)
{
struct timespec ts;
# ifdef CLOCK_BOOTTIME
# define CLOCK_TYPE CLOCK_BOOTTIME
# elif defined(_POSIX_MONOTONIC_CLOCK)
# define CLOCK_TYPE CLOCK_MONOTONIC
# else
# define CLOCK_TYPE CLOCK_REALTIME
# endif
if (clock_gettime(CLOCK_TYPE, &ts) == 0)
return TWO32TO64(ts.tv_sec, ts.tv_nsec);
}
# endif
# if defined(__unix__) \
|| (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L)
{
struct timeval tv;
if (gettimeofday(&tv, NULL) == 0)
return TWO32TO64(tv.tv_sec, tv.tv_usec);
}
# endif
return time(NULL);
}
#endif /* defined(OPENSSL_SYS_UNIX) || defined(__DJGPP__) */
diff --git a/crypto/rand/randfile.c b/crypto/rand/randfile.c
index 1b737d1ba2ba..ba121eefbf09 100644
--- a/crypto/rand/randfile.c
+++ b/crypto/rand/randfile.c
@@ -1,314 +1,314 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <openssl/rand_drbg.h>
#include <openssl/buffer.h>
#ifdef OPENSSL_SYS_VMS
# include <unixio.h>
#endif
#include <sys/types.h>
#ifndef OPENSSL_NO_POSIX_IO
# include <sys/stat.h>
# include <fcntl.h>
# ifdef _WIN32
# include <windows.h>
# include <io.h>
# define stat _stat
# define chmod _chmod
# define open _open
# define fdopen _fdopen
# define fstat _fstat
# define fileno _fileno
# endif
#endif
/*
* Following should not be needed, and we could have been stricter
* and demand S_IS*. But some systems just don't comply... Formally
* below macros are "anatomically incorrect", because normally they
* would look like ((m) & MASK == TYPE), but since MASK availability
* is as questionable, we settle for this poor-man fallback...
*/
# if !defined(S_ISREG)
# define S_ISREG(m) ((m) & S_IFREG)
# endif
#define RAND_BUF_SIZE 1024
#define RFILE ".rnd"
#ifdef OPENSSL_SYS_VMS
/*
* __FILE_ptr32 is a type provided by DEC C headers (types.h specifically)
* to make sure the FILE* is a 32-bit pointer no matter what. We know that
* stdio functions return this type (a study of stdio.h proves it).
*
* This declaration is a nasty hack to get around vms' extension to fopen for
* passing in sharing options being disabled by /STANDARD=ANSI89
*/
static __FILE_ptr32 (*const vms_fopen)(const char *, const char *, ...) =
(__FILE_ptr32 (*)(const char *, const char *, ...))fopen;
# define VMS_OPEN_ATTRS \
"shr=get,put,upd,del","ctx=bin,stm","rfm=stm","rat=none","mrs=0"
# define openssl_fopen(fname, mode) vms_fopen((fname), (mode), VMS_OPEN_ATTRS)
#endif
/*
* Note that these functions are intended for seed files only. Entropy
* devices and EGD sockets are handled in rand_unix.c If |bytes| is
* -1 read the complete file; otherwise read the specified amount.
*/
int RAND_load_file(const char *file, long bytes)
{
/*
* The load buffer size exceeds the chunk size by the comfortable amount
* of 'RAND_DRBG_STRENGTH' bytes (not bits!). This is done on purpose
* to avoid calling RAND_add() with a small final chunk. Instead, such
* a small final chunk will be added together with the previous chunk
* (unless it's the only one).
*/
#define RAND_LOAD_BUF_SIZE (RAND_BUF_SIZE + RAND_DRBG_STRENGTH)
unsigned char buf[RAND_LOAD_BUF_SIZE];
#ifndef OPENSSL_NO_POSIX_IO
struct stat sb;
#endif
int i, n, ret = 0;
FILE *in;
if (bytes == 0)
return 0;
if ((in = openssl_fopen(file, "rb")) == NULL) {
RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_CANNOT_OPEN_FILE);
ERR_add_error_data(2, "Filename=", file);
return -1;
}
#ifndef OPENSSL_NO_POSIX_IO
if (fstat(fileno(in), &sb) < 0) {
RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_INTERNAL_ERROR);
ERR_add_error_data(2, "Filename=", file);
fclose(in);
return -1;
}
if (bytes < 0) {
if (S_ISREG(sb.st_mode))
bytes = sb.st_size;
else
bytes = RAND_DRBG_STRENGTH;
}
#endif
/*
* On VMS, setbuf() will only take 32-bit pointers, and a compilation
* with /POINTER_SIZE=64 will give off a MAYLOSEDATA2 warning here.
* However, we trust that the C RTL will never give us a FILE pointer
* above the first 4 GB of memory, so we simply turn off the warning
* temporarily.
*/
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma environment save
# pragma message disable maylosedata2
#endif
/*
* Don't buffer, because even if |file| is regular file, we have
* no control over the buffer, so why would we want a copy of its
* contents lying around?
*/
setbuf(in, NULL);
#if defined(OPENSSL_SYS_VMS) && defined(__DECC)
# pragma environment restore
#endif
for ( ; ; ) {
if (bytes > 0)
n = (bytes <= RAND_LOAD_BUF_SIZE) ? (int)bytes : RAND_BUF_SIZE;
else
n = RAND_LOAD_BUF_SIZE;
i = fread(buf, 1, n, in);
#ifdef EINTR
if (ferror(in) && errno == EINTR){
clearerr(in);
if (i == 0)
continue;
}
#endif
if (i == 0)
break;
RAND_add(buf, i, (double)i);
ret += i;
/* If given a bytecount, and we did it, break. */
if (bytes > 0 && (bytes -= i) <= 0)
break;
}
OPENSSL_cleanse(buf, sizeof(buf));
fclose(in);
if (!RAND_status()) {
RANDerr(RAND_F_RAND_LOAD_FILE, RAND_R_RESEED_ERROR);
ERR_add_error_data(2, "Filename=", file);
return -1;
}
return ret;
}
int RAND_write_file(const char *file)
{
unsigned char buf[RAND_BUF_SIZE];
int ret = -1;
FILE *out = NULL;
#ifndef OPENSSL_NO_POSIX_IO
struct stat sb;
if (stat(file, &sb) >= 0 && !S_ISREG(sb.st_mode)) {
RANDerr(RAND_F_RAND_WRITE_FILE, RAND_R_NOT_A_REGULAR_FILE);
ERR_add_error_data(2, "Filename=", file);
return -1;
}
#endif
/* Collect enough random data. */
if (RAND_priv_bytes(buf, (int)sizeof(buf)) != 1)
return -1;
#if defined(O_CREAT) && !defined(OPENSSL_NO_POSIX_IO) && \
!defined(OPENSSL_SYS_VMS) && !defined(OPENSSL_SYS_WINDOWS)
{
# ifndef O_BINARY
# define O_BINARY 0
# endif
/*
* chmod(..., 0600) is too late to protect the file, permissions
* should be restrictive from the start
*/
int fd = open(file, O_WRONLY | O_CREAT | O_BINARY, 0600);
if (fd != -1)
out = fdopen(fd, "wb");
}
#endif
#ifdef OPENSSL_SYS_VMS
/*
* VMS NOTE: Prior versions of this routine created a _new_ version of
* the rand file for each call into this routine, then deleted all
* existing versions named ;-1, and finally renamed the current version
* as ';1'. Under concurrent usage, this resulted in an RMS race
* condition in rename() which could orphan files (see vms message help
* for RMS$_REENT). With the fopen() calls below, openssl/VMS now shares
* the top-level version of the rand file. Note that there may still be
* conditions where the top-level rand file is locked. If so, this code
* will then create a new version of the rand file. Without the delete
* and rename code, this can result in ascending file versions that stop
* at version 32767, and this routine will then return an error. The
* remedy for this is to recode the calling application to avoid
* concurrent use of the rand file, or synchronize usage at the
* application level. Also consider whether or not you NEED a persistent
* rand file in a concurrent use situation.
*/
out = openssl_fopen(file, "rb+");
#endif
if (out == NULL)
out = openssl_fopen(file, "wb");
if (out == NULL) {
RANDerr(RAND_F_RAND_WRITE_FILE, RAND_R_CANNOT_OPEN_FILE);
ERR_add_error_data(2, "Filename=", file);
return -1;
}
#if !defined(NO_CHMOD) && !defined(OPENSSL_NO_POSIX_IO)
/*
* Yes it's late to do this (see above comment), but better than nothing.
*/
chmod(file, 0600);
#endif
ret = fwrite(buf, 1, RAND_BUF_SIZE, out);
fclose(out);
OPENSSL_cleanse(buf, RAND_BUF_SIZE);
return ret;
}
const char *RAND_file_name(char *buf, size_t size)
{
char *s = NULL;
size_t len;
int use_randfile = 1;
-#if defined(_WIN32) && defined(CP_UTF8)
+#if defined(_WIN32) && defined(CP_UTF8) && !defined(_WIN32_WCE)
DWORD envlen;
WCHAR *var;
/* Look up various environment variables. */
if ((envlen = GetEnvironmentVariableW(var = L"RANDFILE", NULL, 0)) == 0) {
use_randfile = 0;
if ((envlen = GetEnvironmentVariableW(var = L"HOME", NULL, 0)) == 0
&& (envlen = GetEnvironmentVariableW(var = L"USERPROFILE",
NULL, 0)) == 0)
envlen = GetEnvironmentVariableW(var = L"SYSTEMROOT", NULL, 0);
}
/* If we got a value, allocate space to hold it and then get it. */
if (envlen != 0) {
int sz;
WCHAR *val = _alloca(envlen * sizeof(WCHAR));
if (GetEnvironmentVariableW(var, val, envlen) < envlen
&& (sz = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0,
NULL, NULL)) != 0) {
s = _alloca(sz);
if (WideCharToMultiByte(CP_UTF8, 0, val, -1, s, sz,
NULL, NULL) == 0)
s = NULL;
}
}
#else
if ((s = ossl_safe_getenv("RANDFILE")) == NULL || *s == '\0') {
use_randfile = 0;
s = ossl_safe_getenv("HOME");
}
#endif
#ifdef DEFAULT_HOME
if (!use_randfile && s == NULL)
s = DEFAULT_HOME;
#endif
if (s == NULL || *s == '\0')
return NULL;
len = strlen(s);
if (use_randfile) {
if (len + 1 >= size)
return NULL;
strcpy(buf, s);
} else {
if (len + 1 + strlen(RFILE) + 1 >= size)
return NULL;
strcpy(buf, s);
#ifndef OPENSSL_SYS_VMS
strcat(buf, "/");
#endif
strcat(buf, RFILE);
}
return buf;
}
diff --git a/crypto/rc4/build.info b/crypto/rc4/build.info
index 46ee66b61c68..913942b5e980 100644
--- a/crypto/rc4/build.info
+++ b/crypto/rc4/build.info
@@ -1,18 +1,20 @@
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
{- $target{rc4_asm_src} -}
GENERATE[rc4-586.s]=asm/rc4-586.pl \
$(PERLASM_SCHEME) $(LIB_CFLAGS) $(LIB_CPPFLAGS) $(PROCESSOR)
DEPEND[rc4-586.s]=../perlasm/x86asm.pl
GENERATE[rc4-x86_64.s]=asm/rc4-x86_64.pl $(PERLASM_SCHEME)
GENERATE[rc4-md5-x86_64.s]=asm/rc4-md5-x86_64.pl $(PERLASM_SCHEME)
GENERATE[rc4-parisc.s]=asm/rc4-parisc.pl $(PERLASM_SCHEME)
+GENERATE[rc4-s390x.s]=asm/rc4-s390x.pl $(PERLASM_SCHEME)
+
BEGINRAW[Makefile]
# GNU make "catch all"
{- $builddir -}/rc4-%.s: {- $sourcedir -}/asm/rc4-%.pl
CC="$(CC)" $(PERL) $< $(PERLASM_SCHEME) $@
ENDRAW[Makefile]
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 75debb3e0a9d..ab5f61518bb1 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -1,1105 +1,1107 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/bn.h>
#include <openssl/cms.h>
#include "internal/asn1_int.h"
#include "internal/evp_int.h"
#include "rsa_locl.h"
#ifndef OPENSSL_NO_CMS
static int rsa_cms_sign(CMS_SignerInfo *si);
static int rsa_cms_verify(CMS_SignerInfo *si);
static int rsa_cms_decrypt(CMS_RecipientInfo *ri);
static int rsa_cms_encrypt(CMS_RecipientInfo *ri);
#endif
static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg);
/* Set any parameters associated with pkey */
static int rsa_param_encode(const EVP_PKEY *pkey,
ASN1_STRING **pstr, int *pstrtype)
{
const RSA *rsa = pkey->pkey.rsa;
*pstr = NULL;
/* If RSA it's just NULL type */
if (pkey->ameth->pkey_id != EVP_PKEY_RSA_PSS) {
*pstrtype = V_ASN1_NULL;
return 1;
}
/* If no PSS parameters we omit parameters entirely */
if (rsa->pss == NULL) {
*pstrtype = V_ASN1_UNDEF;
return 1;
}
/* Encode PSS parameters */
if (ASN1_item_pack(rsa->pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), pstr) == NULL)
return 0;
*pstrtype = V_ASN1_SEQUENCE;
return 1;
}
/* Decode any parameters and set them in RSA structure */
static int rsa_param_decode(RSA *rsa, const X509_ALGOR *alg)
{
const ASN1_OBJECT *algoid;
const void *algp;
int algptype;
X509_ALGOR_get0(&algoid, &algptype, &algp, alg);
if (OBJ_obj2nid(algoid) != EVP_PKEY_RSA_PSS)
return 1;
if (algptype == V_ASN1_UNDEF)
return 1;
if (algptype != V_ASN1_SEQUENCE) {
RSAerr(RSA_F_RSA_PARAM_DECODE, RSA_R_INVALID_PSS_PARAMETERS);
return 0;
}
rsa->pss = rsa_pss_decode(alg);
if (rsa->pss == NULL)
return 0;
return 1;
}
static int rsa_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
{
unsigned char *penc = NULL;
int penclen;
ASN1_STRING *str;
int strtype;
if (!rsa_param_encode(pkey, &str, &strtype))
return 0;
penclen = i2d_RSAPublicKey(pkey->pkey.rsa, &penc);
if (penclen <= 0)
return 0;
if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
strtype, str, penc, penclen))
return 1;
OPENSSL_free(penc);
return 0;
}
static int rsa_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
{
const unsigned char *p;
int pklen;
X509_ALGOR *alg;
RSA *rsa = NULL;
if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &alg, pubkey))
return 0;
if ((rsa = d2i_RSAPublicKey(NULL, &p, pklen)) == NULL) {
RSAerr(RSA_F_RSA_PUB_DECODE, ERR_R_RSA_LIB);
return 0;
}
if (!rsa_param_decode(rsa, alg)) {
RSA_free(rsa);
return 0;
}
if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa)) {
RSA_free(rsa);
return 0;
}
return 1;
}
static int rsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
{
if (BN_cmp(b->pkey.rsa->n, a->pkey.rsa->n) != 0
|| BN_cmp(b->pkey.rsa->e, a->pkey.rsa->e) != 0)
return 0;
return 1;
}
static int old_rsa_priv_decode(EVP_PKEY *pkey,
const unsigned char **pder, int derlen)
{
RSA *rsa;
if ((rsa = d2i_RSAPrivateKey(NULL, pder, derlen)) == NULL) {
RSAerr(RSA_F_OLD_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
return 0;
}
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
return 1;
}
static int old_rsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
{
return i2d_RSAPrivateKey(pkey->pkey.rsa, pder);
}
static int rsa_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
{
unsigned char *rk = NULL;
int rklen;
ASN1_STRING *str;
int strtype;
if (!rsa_param_encode(pkey, &str, &strtype))
return 0;
rklen = i2d_RSAPrivateKey(pkey->pkey.rsa, &rk);
if (rklen <= 0) {
RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(str);
return 0;
}
if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
strtype, str, rk, rklen)) {
RSAerr(RSA_F_RSA_PRIV_ENCODE, ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(str);
return 0;
}
return 1;
}
static int rsa_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
{
const unsigned char *p;
RSA *rsa;
int pklen;
const X509_ALGOR *alg;
if (!PKCS8_pkey_get0(NULL, &p, &pklen, &alg, p8))
return 0;
rsa = d2i_RSAPrivateKey(NULL, &p, pklen);
if (rsa == NULL) {
RSAerr(RSA_F_RSA_PRIV_DECODE, ERR_R_RSA_LIB);
return 0;
}
if (!rsa_param_decode(rsa, alg)) {
RSA_free(rsa);
return 0;
}
EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, rsa);
return 1;
}
static int int_rsa_size(const EVP_PKEY *pkey)
{
return RSA_size(pkey->pkey.rsa);
}
static int rsa_bits(const EVP_PKEY *pkey)
{
return BN_num_bits(pkey->pkey.rsa->n);
}
static int rsa_security_bits(const EVP_PKEY *pkey)
{
return RSA_security_bits(pkey->pkey.rsa);
}
static void int_rsa_free(EVP_PKEY *pkey)
{
RSA_free(pkey->pkey.rsa);
}
static X509_ALGOR *rsa_mgf1_decode(X509_ALGOR *alg)
{
if (OBJ_obj2nid(alg->algorithm) != NID_mgf1)
return NULL;
return ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(X509_ALGOR),
alg->parameter);
}
static int rsa_pss_param_print(BIO *bp, int pss_key, RSA_PSS_PARAMS *pss,
int indent)
{
int rv = 0;
X509_ALGOR *maskHash = NULL;
if (!BIO_indent(bp, indent, 128))
goto err;
if (pss_key) {
if (pss == NULL) {
if (BIO_puts(bp, "No PSS parameter restrictions\n") <= 0)
return 0;
return 1;
} else {
if (BIO_puts(bp, "PSS parameter restrictions:") <= 0)
return 0;
}
} else if (pss == NULL) {
if (BIO_puts(bp,"(INVALID PSS PARAMETERS)\n") <= 0)
return 0;
return 1;
}
if (BIO_puts(bp, "\n") <= 0)
goto err;
if (pss_key)
indent += 2;
if (!BIO_indent(bp, indent, 128))
goto err;
if (BIO_puts(bp, "Hash Algorithm: ") <= 0)
goto err;
if (pss->hashAlgorithm) {
if (i2a_ASN1_OBJECT(bp, pss->hashAlgorithm->algorithm) <= 0)
goto err;
} else if (BIO_puts(bp, "sha1 (default)") <= 0) {
goto err;
}
if (BIO_puts(bp, "\n") <= 0)
goto err;
if (!BIO_indent(bp, indent, 128))
goto err;
if (BIO_puts(bp, "Mask Algorithm: ") <= 0)
goto err;
if (pss->maskGenAlgorithm) {
if (i2a_ASN1_OBJECT(bp, pss->maskGenAlgorithm->algorithm) <= 0)
goto err;
if (BIO_puts(bp, " with ") <= 0)
goto err;
maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
if (maskHash != NULL) {
if (i2a_ASN1_OBJECT(bp, maskHash->algorithm) <= 0)
goto err;
} else if (BIO_puts(bp, "INVALID") <= 0) {
goto err;
}
} else if (BIO_puts(bp, "mgf1 with sha1 (default)") <= 0) {
goto err;
}
BIO_puts(bp, "\n");
if (!BIO_indent(bp, indent, 128))
goto err;
if (BIO_printf(bp, "%s Salt Length: 0x", pss_key ? "Minimum" : "") <= 0)
goto err;
if (pss->saltLength) {
if (i2a_ASN1_INTEGER(bp, pss->saltLength) <= 0)
goto err;
} else if (BIO_puts(bp, "14 (default)") <= 0) {
goto err;
}
BIO_puts(bp, "\n");
if (!BIO_indent(bp, indent, 128))
goto err;
if (BIO_puts(bp, "Trailer Field: 0x") <= 0)
goto err;
if (pss->trailerField) {
if (i2a_ASN1_INTEGER(bp, pss->trailerField) <= 0)
goto err;
} else if (BIO_puts(bp, "BC (default)") <= 0) {
goto err;
}
BIO_puts(bp, "\n");
rv = 1;
err:
X509_ALGOR_free(maskHash);
return rv;
}
static int pkey_rsa_print(BIO *bp, const EVP_PKEY *pkey, int off, int priv)
{
const RSA *x = pkey->pkey.rsa;
char *str;
const char *s;
int ret = 0, mod_len = 0, ex_primes;
if (x->n != NULL)
mod_len = BN_num_bits(x->n);
ex_primes = sk_RSA_PRIME_INFO_num(x->prime_infos);
if (!BIO_indent(bp, off, 128))
goto err;
if (BIO_printf(bp, "%s ", pkey_is_pss(pkey) ? "RSA-PSS" : "RSA") <= 0)
goto err;
if (priv && x->d) {
if (BIO_printf(bp, "Private-Key: (%d bit, %d primes)\n",
mod_len, ex_primes <= 0 ? 2 : ex_primes + 2) <= 0)
goto err;
str = "modulus:";
s = "publicExponent:";
} else {
if (BIO_printf(bp, "Public-Key: (%d bit)\n", mod_len) <= 0)
goto err;
str = "Modulus:";
s = "Exponent:";
}
if (!ASN1_bn_print(bp, str, x->n, NULL, off))
goto err;
if (!ASN1_bn_print(bp, s, x->e, NULL, off))
goto err;
if (priv) {
int i;
if (!ASN1_bn_print(bp, "privateExponent:", x->d, NULL, off))
goto err;
if (!ASN1_bn_print(bp, "prime1:", x->p, NULL, off))
goto err;
if (!ASN1_bn_print(bp, "prime2:", x->q, NULL, off))
goto err;
if (!ASN1_bn_print(bp, "exponent1:", x->dmp1, NULL, off))
goto err;
if (!ASN1_bn_print(bp, "exponent2:", x->dmq1, NULL, off))
goto err;
if (!ASN1_bn_print(bp, "coefficient:", x->iqmp, NULL, off))
goto err;
for (i = 0; i < sk_RSA_PRIME_INFO_num(x->prime_infos); i++) {
/* print multi-prime info */
BIGNUM *bn = NULL;
RSA_PRIME_INFO *pinfo;
int j;
pinfo = sk_RSA_PRIME_INFO_value(x->prime_infos, i);
for (j = 0; j < 3; j++) {
if (!BIO_indent(bp, off, 128))
goto err;
switch (j) {
case 0:
if (BIO_printf(bp, "prime%d:", i + 3) <= 0)
goto err;
bn = pinfo->r;
break;
case 1:
if (BIO_printf(bp, "exponent%d:", i + 3) <= 0)
goto err;
bn = pinfo->d;
break;
case 2:
if (BIO_printf(bp, "coefficient%d:", i + 3) <= 0)
goto err;
bn = pinfo->t;
break;
default:
break;
}
if (!ASN1_bn_print(bp, "", bn, NULL, off))
goto err;
}
}
}
if (pkey_is_pss(pkey) && !rsa_pss_param_print(bp, 1, x->pss, off))
goto err;
ret = 1;
err:
return ret;
}
static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
return pkey_rsa_print(bp, pkey, indent, 0);
}
static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
ASN1_PCTX *ctx)
{
return pkey_rsa_print(bp, pkey, indent, 1);
}
static RSA_PSS_PARAMS *rsa_pss_decode(const X509_ALGOR *alg)
{
RSA_PSS_PARAMS *pss;
pss = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_PSS_PARAMS),
alg->parameter);
if (pss == NULL)
return NULL;
if (pss->maskGenAlgorithm != NULL) {
pss->maskHash = rsa_mgf1_decode(pss->maskGenAlgorithm);
if (pss->maskHash == NULL) {
RSA_PSS_PARAMS_free(pss);
return NULL;
}
}
return pss;
}
static int rsa_sig_print(BIO *bp, const X509_ALGOR *sigalg,
const ASN1_STRING *sig, int indent, ASN1_PCTX *pctx)
{
if (OBJ_obj2nid(sigalg->algorithm) == EVP_PKEY_RSA_PSS) {
int rv;
RSA_PSS_PARAMS *pss = rsa_pss_decode(sigalg);
rv = rsa_pss_param_print(bp, 0, pss, indent);
RSA_PSS_PARAMS_free(pss);
if (!rv)
return 0;
} else if (!sig && BIO_puts(bp, "\n") <= 0) {
return 0;
}
if (sig)
return X509_signature_dump(bp, sig, indent);
return 1;
}
static int rsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
{
X509_ALGOR *alg = NULL;
switch (op) {
case ASN1_PKEY_CTRL_PKCS7_SIGN:
if (arg1 == 0)
PKCS7_SIGNER_INFO_get0_algs(arg2, NULL, NULL, &alg);
break;
case ASN1_PKEY_CTRL_PKCS7_ENCRYPT:
if (pkey_is_pss(pkey))
return -2;
if (arg1 == 0)
PKCS7_RECIP_INFO_get0_alg(arg2, &alg);
break;
#ifndef OPENSSL_NO_CMS
case ASN1_PKEY_CTRL_CMS_SIGN:
if (arg1 == 0)
return rsa_cms_sign(arg2);
else if (arg1 == 1)
return rsa_cms_verify(arg2);
break;
case ASN1_PKEY_CTRL_CMS_ENVELOPE:
if (pkey_is_pss(pkey))
return -2;
if (arg1 == 0)
return rsa_cms_encrypt(arg2);
else if (arg1 == 1)
return rsa_cms_decrypt(arg2);
break;
case ASN1_PKEY_CTRL_CMS_RI_TYPE:
if (pkey_is_pss(pkey))
return -2;
*(int *)arg2 = CMS_RECIPINFO_TRANS;
return 1;
#endif
case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
*(int *)arg2 = NID_sha256;
return 1;
default:
return -2;
}
if (alg)
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
return 1;
}
/* allocate and set algorithm ID from EVP_MD, default SHA1 */
static int rsa_md_to_algor(X509_ALGOR **palg, const EVP_MD *md)
{
if (md == NULL || EVP_MD_type(md) == NID_sha1)
return 1;
*palg = X509_ALGOR_new();
if (*palg == NULL)
return 0;
X509_ALGOR_set_md(*palg, md);
return 1;
}
/* Allocate and set MGF1 algorithm ID from EVP_MD */
static int rsa_md_to_mgf1(X509_ALGOR **palg, const EVP_MD *mgf1md)
{
X509_ALGOR *algtmp = NULL;
ASN1_STRING *stmp = NULL;
*palg = NULL;
if (mgf1md == NULL || EVP_MD_type(mgf1md) == NID_sha1)
return 1;
/* need to embed algorithm ID inside another */
if (!rsa_md_to_algor(&algtmp, mgf1md))
goto err;
if (ASN1_item_pack(algtmp, ASN1_ITEM_rptr(X509_ALGOR), &stmp) == NULL)
goto err;
*palg = X509_ALGOR_new();
if (*palg == NULL)
goto err;
X509_ALGOR_set0(*palg, OBJ_nid2obj(NID_mgf1), V_ASN1_SEQUENCE, stmp);
stmp = NULL;
err:
ASN1_STRING_free(stmp);
X509_ALGOR_free(algtmp);
if (*palg)
return 1;
return 0;
}
/* convert algorithm ID to EVP_MD, default SHA1 */
static const EVP_MD *rsa_algor_to_md(X509_ALGOR *alg)
{
const EVP_MD *md;
if (!alg)
return EVP_sha1();
md = EVP_get_digestbyobj(alg->algorithm);
if (md == NULL)
RSAerr(RSA_F_RSA_ALGOR_TO_MD, RSA_R_UNKNOWN_DIGEST);
return md;
}
/*
* Convert EVP_PKEY_CTX in PSS mode into corresponding algorithm parameter,
* suitable for setting an AlgorithmIdentifier.
*/
static RSA_PSS_PARAMS *rsa_ctx_to_pss(EVP_PKEY_CTX *pkctx)
{
const EVP_MD *sigmd, *mgf1md;
EVP_PKEY *pk = EVP_PKEY_CTX_get0_pkey(pkctx);
int saltlen;
if (EVP_PKEY_CTX_get_signature_md(pkctx, &sigmd) <= 0)
return NULL;
if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
return NULL;
if (!EVP_PKEY_CTX_get_rsa_pss_saltlen(pkctx, &saltlen))
return NULL;
if (saltlen == -1) {
saltlen = EVP_MD_size(sigmd);
- } else if (saltlen == -2) {
+ } else if (saltlen == -2 || saltlen == -3) {
saltlen = EVP_PKEY_size(pk) - EVP_MD_size(sigmd) - 2;
if ((EVP_PKEY_bits(pk) & 0x7) == 1)
saltlen--;
+ if (saltlen < 0)
+ return NULL;
}
return rsa_pss_params_create(sigmd, mgf1md, saltlen);
}
RSA_PSS_PARAMS *rsa_pss_params_create(const EVP_MD *sigmd,
const EVP_MD *mgf1md, int saltlen)
{
RSA_PSS_PARAMS *pss = RSA_PSS_PARAMS_new();
if (pss == NULL)
goto err;
if (saltlen != 20) {
pss->saltLength = ASN1_INTEGER_new();
if (pss->saltLength == NULL)
goto err;
if (!ASN1_INTEGER_set(pss->saltLength, saltlen))
goto err;
}
if (!rsa_md_to_algor(&pss->hashAlgorithm, sigmd))
goto err;
if (mgf1md == NULL)
mgf1md = sigmd;
if (!rsa_md_to_mgf1(&pss->maskGenAlgorithm, mgf1md))
goto err;
if (!rsa_md_to_algor(&pss->maskHash, mgf1md))
goto err;
return pss;
err:
RSA_PSS_PARAMS_free(pss);
return NULL;
}
static ASN1_STRING *rsa_ctx_to_pss_string(EVP_PKEY_CTX *pkctx)
{
RSA_PSS_PARAMS *pss = rsa_ctx_to_pss(pkctx);
ASN1_STRING *os;
if (pss == NULL)
return NULL;
os = ASN1_item_pack(pss, ASN1_ITEM_rptr(RSA_PSS_PARAMS), NULL);
RSA_PSS_PARAMS_free(pss);
return os;
}
/*
* From PSS AlgorithmIdentifier set public key parameters. If pkey isn't NULL
* then the EVP_MD_CTX is setup and initialised. If it is NULL parameters are
* passed to pkctx instead.
*/
static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx,
X509_ALGOR *sigalg, EVP_PKEY *pkey)
{
int rv = -1;
int saltlen;
const EVP_MD *mgf1md = NULL, *md = NULL;
RSA_PSS_PARAMS *pss;
/* Sanity check: make sure it is PSS */
if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
return -1;
}
/* Decode PSS parameters */
pss = rsa_pss_decode(sigalg);
if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen)) {
RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS);
goto err;
}
/* We have all parameters now set up context */
if (pkey) {
if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey))
goto err;
} else {
const EVP_MD *checkmd;
if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0)
goto err;
if (EVP_MD_type(md) != EVP_MD_type(checkmd)) {
RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH);
goto err;
}
}
if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0)
goto err;
if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0)
goto err;
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
goto err;
/* Carry on */
rv = 1;
err:
RSA_PSS_PARAMS_free(pss);
return rv;
}
int rsa_pss_get_param(const RSA_PSS_PARAMS *pss, const EVP_MD **pmd,
const EVP_MD **pmgf1md, int *psaltlen)
{
if (pss == NULL)
return 0;
*pmd = rsa_algor_to_md(pss->hashAlgorithm);
if (*pmd == NULL)
return 0;
*pmgf1md = rsa_algor_to_md(pss->maskHash);
if (*pmgf1md == NULL)
return 0;
if (pss->saltLength) {
*psaltlen = ASN1_INTEGER_get(pss->saltLength);
if (*psaltlen < 0) {
RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_SALT_LENGTH);
return 0;
}
} else {
*psaltlen = 20;
}
/*
* low-level routines support only trailer field 0xbc (value 1) and
* PKCS#1 says we should reject any other value anyway.
*/
if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) {
RSAerr(RSA_F_RSA_PSS_GET_PARAM, RSA_R_INVALID_TRAILER);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_CMS
static int rsa_cms_verify(CMS_SignerInfo *si)
{
int nid, nid2;
X509_ALGOR *alg;
EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
nid = OBJ_obj2nid(alg->algorithm);
if (nid == EVP_PKEY_RSA_PSS)
return rsa_pss_to_ctx(NULL, pkctx, alg, NULL);
/* Only PSS allowed for PSS keys */
if (pkey_ctx_is_pss(pkctx)) {
RSAerr(RSA_F_RSA_CMS_VERIFY, RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return 0;
}
if (nid == NID_rsaEncryption)
return 1;
/* Workaround for some implementation that use a signature OID */
if (OBJ_find_sigid_algs(nid, NULL, &nid2)) {
if (nid2 == NID_rsaEncryption)
return 1;
}
return 0;
}
#endif
/*
* Customised RSA item verification routine. This is called when a signature
* is encountered requiring special handling. We currently only handle PSS.
*/
static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
X509_ALGOR *sigalg, ASN1_BIT_STRING *sig,
EVP_PKEY *pkey)
{
/* Sanity check: make sure it is PSS */
if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS) {
RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE);
return -1;
}
if (rsa_pss_to_ctx(ctx, NULL, sigalg, pkey) > 0) {
/* Carry on */
return 2;
}
return -1;
}
#ifndef OPENSSL_NO_CMS
static int rsa_cms_sign(CMS_SignerInfo *si)
{
int pad_mode = RSA_PKCS1_PADDING;
X509_ALGOR *alg;
EVP_PKEY_CTX *pkctx = CMS_SignerInfo_get0_pkey_ctx(si);
ASN1_STRING *os = NULL;
CMS_SignerInfo_get0_algs(si, NULL, NULL, NULL, &alg);
if (pkctx) {
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
return 0;
}
if (pad_mode == RSA_PKCS1_PADDING) {
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
return 1;
}
/* We don't support it */
if (pad_mode != RSA_PKCS1_PSS_PADDING)
return 0;
os = rsa_ctx_to_pss_string(pkctx);
if (!os)
return 0;
X509_ALGOR_set0(alg, OBJ_nid2obj(EVP_PKEY_RSA_PSS), V_ASN1_SEQUENCE, os);
return 1;
}
#endif
static int rsa_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn,
X509_ALGOR *alg1, X509_ALGOR *alg2,
ASN1_BIT_STRING *sig)
{
int pad_mode;
EVP_PKEY_CTX *pkctx = EVP_MD_CTX_pkey_ctx(ctx);
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
return 0;
if (pad_mode == RSA_PKCS1_PADDING)
return 2;
if (pad_mode == RSA_PKCS1_PSS_PADDING) {
ASN1_STRING *os1 = NULL;
os1 = rsa_ctx_to_pss_string(pkctx);
if (!os1)
return 0;
/* Duplicate parameters if we have to */
if (alg2) {
ASN1_STRING *os2 = ASN1_STRING_dup(os1);
if (!os2) {
ASN1_STRING_free(os1);
return 0;
}
X509_ALGOR_set0(alg2, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
V_ASN1_SEQUENCE, os2);
}
X509_ALGOR_set0(alg1, OBJ_nid2obj(EVP_PKEY_RSA_PSS),
V_ASN1_SEQUENCE, os1);
return 3;
}
return 2;
}
static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg,
const ASN1_STRING *sig)
{
int rv = 0;
int mdnid, saltlen;
uint32_t flags;
const EVP_MD *mgf1md = NULL, *md = NULL;
RSA_PSS_PARAMS *pss;
/* Sanity check: make sure it is PSS */
if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS)
return 0;
/* Decode PSS parameters */
pss = rsa_pss_decode(sigalg);
if (!rsa_pss_get_param(pss, &md, &mgf1md, &saltlen))
goto err;
mdnid = EVP_MD_type(md);
/*
* For TLS need SHA256, SHA384 or SHA512, digest and MGF1 digest must
* match and salt length must equal digest size
*/
if ((mdnid == NID_sha256 || mdnid == NID_sha384 || mdnid == NID_sha512)
&& mdnid == EVP_MD_type(mgf1md) && saltlen == EVP_MD_size(md))
flags = X509_SIG_INFO_TLS;
else
flags = 0;
/* Note: security bits half number of digest bits */
X509_SIG_INFO_set(siginf, mdnid, EVP_PKEY_RSA_PSS, EVP_MD_size(md) * 4,
flags);
rv = 1;
err:
RSA_PSS_PARAMS_free(pss);
return rv;
}
#ifndef OPENSSL_NO_CMS
static RSA_OAEP_PARAMS *rsa_oaep_decode(const X509_ALGOR *alg)
{
RSA_OAEP_PARAMS *oaep;
oaep = ASN1_TYPE_unpack_sequence(ASN1_ITEM_rptr(RSA_OAEP_PARAMS),
alg->parameter);
if (oaep == NULL)
return NULL;
if (oaep->maskGenFunc != NULL) {
oaep->maskHash = rsa_mgf1_decode(oaep->maskGenFunc);
if (oaep->maskHash == NULL) {
RSA_OAEP_PARAMS_free(oaep);
return NULL;
}
}
return oaep;
}
static int rsa_cms_decrypt(CMS_RecipientInfo *ri)
{
EVP_PKEY_CTX *pkctx;
X509_ALGOR *cmsalg;
int nid;
int rv = -1;
unsigned char *label = NULL;
int labellen = 0;
const EVP_MD *mgf1md = NULL, *md = NULL;
RSA_OAEP_PARAMS *oaep;
pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
if (pkctx == NULL)
return 0;
if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg))
return -1;
nid = OBJ_obj2nid(cmsalg->algorithm);
if (nid == NID_rsaEncryption)
return 1;
if (nid != NID_rsaesOaep) {
RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE);
return -1;
}
/* Decode OAEP parameters */
oaep = rsa_oaep_decode(cmsalg);
if (oaep == NULL) {
RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS);
goto err;
}
mgf1md = rsa_algor_to_md(oaep->maskHash);
if (mgf1md == NULL)
goto err;
md = rsa_algor_to_md(oaep->hashFunc);
if (md == NULL)
goto err;
if (oaep->pSourceFunc != NULL) {
X509_ALGOR *plab = oaep->pSourceFunc;
if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) {
RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE);
goto err;
}
if (plab->parameter->type != V_ASN1_OCTET_STRING) {
RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_LABEL);
goto err;
}
label = plab->parameter->value.octet_string->data;
/* Stop label being freed when OAEP parameters are freed */
plab->parameter->value.octet_string->data = NULL;
labellen = plab->parameter->value.octet_string->length;
}
if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0)
goto err;
if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0)
goto err;
if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0)
goto err;
if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0)
goto err;
/* Carry on */
rv = 1;
err:
RSA_OAEP_PARAMS_free(oaep);
return rv;
}
static int rsa_cms_encrypt(CMS_RecipientInfo *ri)
{
const EVP_MD *md, *mgf1md;
RSA_OAEP_PARAMS *oaep = NULL;
ASN1_STRING *os = NULL;
X509_ALGOR *alg;
EVP_PKEY_CTX *pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
int pad_mode = RSA_PKCS1_PADDING, rv = 0, labellen;
unsigned char *label;
if (CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &alg) <= 0)
return 0;
if (pkctx) {
if (EVP_PKEY_CTX_get_rsa_padding(pkctx, &pad_mode) <= 0)
return 0;
}
if (pad_mode == RSA_PKCS1_PADDING) {
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaEncryption), V_ASN1_NULL, 0);
return 1;
}
/* Not supported */
if (pad_mode != RSA_PKCS1_OAEP_PADDING)
return 0;
if (EVP_PKEY_CTX_get_rsa_oaep_md(pkctx, &md) <= 0)
goto err;
if (EVP_PKEY_CTX_get_rsa_mgf1_md(pkctx, &mgf1md) <= 0)
goto err;
labellen = EVP_PKEY_CTX_get0_rsa_oaep_label(pkctx, &label);
if (labellen < 0)
goto err;
oaep = RSA_OAEP_PARAMS_new();
if (oaep == NULL)
goto err;
if (!rsa_md_to_algor(&oaep->hashFunc, md))
goto err;
if (!rsa_md_to_mgf1(&oaep->maskGenFunc, mgf1md))
goto err;
if (labellen > 0) {
ASN1_OCTET_STRING *los;
oaep->pSourceFunc = X509_ALGOR_new();
if (oaep->pSourceFunc == NULL)
goto err;
los = ASN1_OCTET_STRING_new();
if (los == NULL)
goto err;
if (!ASN1_OCTET_STRING_set(los, label, labellen)) {
ASN1_OCTET_STRING_free(los);
goto err;
}
X509_ALGOR_set0(oaep->pSourceFunc, OBJ_nid2obj(NID_pSpecified),
V_ASN1_OCTET_STRING, los);
}
/* create string with pss parameter encoding. */
if (!ASN1_item_pack(oaep, ASN1_ITEM_rptr(RSA_OAEP_PARAMS), &os))
goto err;
X509_ALGOR_set0(alg, OBJ_nid2obj(NID_rsaesOaep), V_ASN1_SEQUENCE, os);
os = NULL;
rv = 1;
err:
RSA_OAEP_PARAMS_free(oaep);
ASN1_STRING_free(os);
return rv;
}
#endif
static int rsa_pkey_check(const EVP_PKEY *pkey)
{
return RSA_check_key_ex(pkey->pkey.rsa, NULL);
}
const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[2] = {
{
EVP_PKEY_RSA,
EVP_PKEY_RSA,
ASN1_PKEY_SIGPARAM_NULL,
"RSA",
"OpenSSL RSA method",
rsa_pub_decode,
rsa_pub_encode,
rsa_pub_cmp,
rsa_pub_print,
rsa_priv_decode,
rsa_priv_encode,
rsa_priv_print,
int_rsa_size,
rsa_bits,
rsa_security_bits,
0, 0, 0, 0, 0, 0,
rsa_sig_print,
int_rsa_free,
rsa_pkey_ctrl,
old_rsa_priv_decode,
old_rsa_priv_encode,
rsa_item_verify,
rsa_item_sign,
rsa_sig_info_set,
rsa_pkey_check
},
{
EVP_PKEY_RSA2,
EVP_PKEY_RSA,
ASN1_PKEY_ALIAS}
};
const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth = {
EVP_PKEY_RSA_PSS,
EVP_PKEY_RSA_PSS,
ASN1_PKEY_SIGPARAM_NULL,
"RSA-PSS",
"OpenSSL RSA-PSS method",
rsa_pub_decode,
rsa_pub_encode,
rsa_pub_cmp,
rsa_pub_print,
rsa_priv_decode,
rsa_priv_encode,
rsa_priv_print,
int_rsa_size,
rsa_bits,
rsa_security_bits,
0, 0, 0, 0, 0, 0,
rsa_sig_print,
int_rsa_free,
rsa_pkey_ctrl,
0, 0,
rsa_item_verify,
rsa_item_sign,
0,
rsa_pkey_check
};
diff --git a/crypto/rsa/rsa_gen.c b/crypto/rsa/rsa_gen.c
index 7f0a25648140..4997a632f2d3 100644
--- a/crypto/rsa/rsa_gen.c
+++ b/crypto/rsa/rsa_gen.c
@@ -1,394 +1,393 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* NB: these functions have been "upgraded", the deprecated versions (which
* are compatibility wrappers using these functions) are in rsa_depr.c. -
* Geoff
*/
#include <stdio.h>
#include <time.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include "rsa_locl.h"
static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
BN_GENCB *cb);
/*
* NB: this wrapper would normally be placed in rsa_lib.c and the static
* implementation would probably be in rsa_eay.c. Nonetheless, is kept here
* so that we don't introduce a new linker dependency. Eg. any application
* that wasn't previously linking object code related to key-generation won't
* have to now just because key-generation is part of RSA_METHOD.
*/
int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
{
if (rsa->meth->rsa_keygen != NULL)
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
return RSA_generate_multi_prime_key(rsa, bits, RSA_DEFAULT_PRIME_NUM,
e_value, cb);
}
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int primes,
BIGNUM *e_value, BN_GENCB *cb)
{
/* multi-prime is only supported with the builtin key generation */
if (rsa->meth->rsa_multi_prime_keygen != NULL) {
return rsa->meth->rsa_multi_prime_keygen(rsa, bits, primes,
e_value, cb);
} else if (rsa->meth->rsa_keygen != NULL) {
/*
* However, if rsa->meth implements only rsa_keygen, then we
* have to honour it in 2-prime case and assume that it wouldn't
* know what to do with multi-prime key generated by builtin
* subroutine...
*/
if (primes == 2)
return rsa->meth->rsa_keygen(rsa, bits, e_value, cb);
else
return 0;
}
return rsa_builtin_keygen(rsa, bits, primes, e_value, cb);
}
static int rsa_builtin_keygen(RSA *rsa, int bits, int primes, BIGNUM *e_value,
BN_GENCB *cb)
{
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *tmp, *prime;
int ok = -1, n = 0, bitsr[RSA_MAX_PRIME_NUM], bitse = 0;
int i = 0, quo = 0, rmd = 0, adj = 0, retries = 0;
RSA_PRIME_INFO *pinfo = NULL;
STACK_OF(RSA_PRIME_INFO) *prime_infos = NULL;
BN_CTX *ctx = NULL;
BN_ULONG bitst = 0;
unsigned long error = 0;
if (bits < RSA_MIN_MODULUS_BITS) {
ok = 0; /* we set our own err */
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_SIZE_TOO_SMALL);
goto err;
}
if (primes < RSA_DEFAULT_PRIME_NUM || primes > rsa_multip_cap(bits)) {
ok = 0; /* we set our own err */
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, RSA_R_KEY_PRIME_NUM_INVALID);
goto err;
}
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
r0 = BN_CTX_get(ctx);
r1 = BN_CTX_get(ctx);
r2 = BN_CTX_get(ctx);
if (r2 == NULL)
goto err;
/* divide bits into 'primes' pieces evenly */
quo = bits / primes;
rmd = bits % primes;
for (i = 0; i < primes; i++)
bitsr[i] = (i < rmd) ? quo + 1 : quo;
/* We need the RSA components non-NULL */
if (!rsa->n && ((rsa->n = BN_new()) == NULL))
goto err;
if (!rsa->d && ((rsa->d = BN_secure_new()) == NULL))
goto err;
if (!rsa->e && ((rsa->e = BN_new()) == NULL))
goto err;
if (!rsa->p && ((rsa->p = BN_secure_new()) == NULL))
goto err;
if (!rsa->q && ((rsa->q = BN_secure_new()) == NULL))
goto err;
if (!rsa->dmp1 && ((rsa->dmp1 = BN_secure_new()) == NULL))
goto err;
if (!rsa->dmq1 && ((rsa->dmq1 = BN_secure_new()) == NULL))
goto err;
if (!rsa->iqmp && ((rsa->iqmp = BN_secure_new()) == NULL))
goto err;
/* initialize multi-prime components */
if (primes > RSA_DEFAULT_PRIME_NUM) {
rsa->version = RSA_ASN1_VERSION_MULTI;
prime_infos = sk_RSA_PRIME_INFO_new_reserve(NULL, primes - 2);
if (prime_infos == NULL)
goto err;
if (rsa->prime_infos != NULL) {
/* could this happen? */
sk_RSA_PRIME_INFO_pop_free(rsa->prime_infos, rsa_multip_info_free);
}
rsa->prime_infos = prime_infos;
/* prime_info from 2 to |primes| -1 */
for (i = 2; i < primes; i++) {
pinfo = rsa_multip_info_new();
if (pinfo == NULL)
goto err;
(void)sk_RSA_PRIME_INFO_push(prime_infos, pinfo);
}
}
if (BN_copy(rsa->e, e_value) == NULL)
goto err;
/* generate p, q and other primes (if any) */
for (i = 0; i < primes; i++) {
adj = 0;
retries = 0;
if (i == 0) {
prime = rsa->p;
} else if (i == 1) {
prime = rsa->q;
} else {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
prime = pinfo->r;
}
BN_set_flags(prime, BN_FLG_CONSTTIME);
for (;;) {
redo:
if (!BN_generate_prime_ex(prime, bitsr[i] + adj, 0, NULL, NULL, cb))
goto err;
/*
* prime should not be equal to p, q, r_3...
* (those primes prior to this one)
*/
{
int j;
for (j = 0; j < i; j++) {
BIGNUM *prev_prime;
if (j == 0)
prev_prime = rsa->p;
else if (j == 1)
prev_prime = rsa->q;
else
prev_prime = sk_RSA_PRIME_INFO_value(prime_infos,
j - 2)->r;
if (!BN_cmp(prime, prev_prime)) {
goto redo;
}
}
}
if (!BN_sub(r2, prime, BN_value_one()))
goto err;
ERR_set_mark();
BN_set_flags(r2, BN_FLG_CONSTTIME);
if (BN_mod_inverse(r1, r2, rsa->e, ctx) != NULL) {
/* GCD == 1 since inverse exists */
break;
}
error = ERR_peek_last_error();
if (ERR_GET_LIB(error) == ERR_LIB_BN
&& ERR_GET_REASON(error) == BN_R_NO_INVERSE) {
/* GCD != 1 */
ERR_pop_to_mark();
} else {
goto err;
}
if (!BN_GENCB_call(cb, 2, n++))
goto err;
}
bitse += bitsr[i];
/* calculate n immediately to see if it's sufficient */
if (i == 1) {
/* we get at least 2 primes */
if (!BN_mul(r1, rsa->p, rsa->q, ctx))
goto err;
} else if (i != 0) {
/* modulus n = p * q * r_3 * r_4 ... */
if (!BN_mul(r1, rsa->n, prime, ctx))
goto err;
} else {
/* i == 0, do nothing */
if (!BN_GENCB_call(cb, 3, i))
goto err;
continue;
}
/*
* if |r1|, product of factors so far, is not as long as expected
* (by checking the first 4 bits are less than 0x9 or greater than
* 0xF). If so, re-generate the last prime.
*
* NOTE: This actually can't happen in two-prime case, because of
* the way factors are generated.
*
* Besides, another consideration is, for multi-prime case, even the
* length modulus is as long as expected, the modulus could start at
* 0x8, which could be utilized to distinguish a multi-prime private
* key by using the modulus in a certificate. This is also covered
* by checking the length should not be less than 0x9.
*/
if (!BN_rshift(r2, r1, bitse - 4))
goto err;
bitst = BN_get_word(r2);
if (bitst < 0x9 || bitst > 0xF) {
/*
* For keys with more than 4 primes, we attempt longer factor to
* meet length requirement.
*
* Otherwise, we just re-generate the prime with the same length.
*
* This strategy has the following goals:
*
* 1. 1024-bit factors are effcient when using 3072 and 4096-bit key
* 2. stay the same logic with normal 2-prime key
*/
bitse -= bitsr[i];
if (!BN_GENCB_call(cb, 2, n++))
goto err;
if (primes > 4) {
if (bitst < 0x9)
adj++;
else
adj--;
} else if (retries == 4) {
/*
* re-generate all primes from scratch, mainly used
* in 4 prime case to avoid long loop. Max retry times
* is set to 4.
*/
i = -1;
bitse = 0;
continue;
}
retries++;
goto redo;
}
/* save product of primes for further use, for multi-prime only */
if (i > 1 && BN_copy(pinfo->pp, rsa->n) == NULL)
goto err;
if (BN_copy(rsa->n, r1) == NULL)
goto err;
if (!BN_GENCB_call(cb, 3, i))
goto err;
}
if (BN_cmp(rsa->p, rsa->q) < 0) {
tmp = rsa->p;
rsa->p = rsa->q;
rsa->q = tmp;
}
/* calculate d */
/* p - 1 */
if (!BN_sub(r1, rsa->p, BN_value_one()))
goto err;
/* q - 1 */
if (!BN_sub(r2, rsa->q, BN_value_one()))
goto err;
/* (p - 1)(q - 1) */
if (!BN_mul(r0, r1, r2, ctx))
goto err;
/* multi-prime */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
/* save r_i - 1 to pinfo->d temporarily */
if (!BN_sub(pinfo->d, pinfo->r, BN_value_one()))
goto err;
if (!BN_mul(r0, r0, pinfo->d, ctx))
goto err;
}
{
BIGNUM *pr0 = BN_new();
if (pr0 == NULL)
goto err;
BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
BN_free(pr0);
goto err; /* d */
}
/* We MUST free pr0 before any further use of r0 */
BN_free(pr0);
}
{
BIGNUM *d = BN_new();
if (d == NULL)
goto err;
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
/* calculate d mod (p-1) and d mod (q - 1) */
if (!BN_mod(rsa->dmp1, d, r1, ctx)
|| !BN_mod(rsa->dmq1, d, r2, ctx)) {
BN_free(d);
goto err;
}
/* calculate CRT exponents */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
/* pinfo->d == r_i - 1 */
if (!BN_mod(pinfo->d, d, pinfo->d, ctx)) {
BN_free(d);
goto err;
}
}
/* We MUST free d before any further use of rsa->d */
BN_free(d);
}
{
BIGNUM *p = BN_new();
if (p == NULL)
goto err;
BN_with_flags(p, rsa->p, BN_FLG_CONSTTIME);
/* calculate inverse of q mod p */
if (!BN_mod_inverse(rsa->iqmp, rsa->q, p, ctx)) {
BN_free(p);
goto err;
}
/* calculate CRT coefficient for other primes */
for (i = 2; i < primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(prime_infos, i - 2);
BN_with_flags(p, pinfo->r, BN_FLG_CONSTTIME);
if (!BN_mod_inverse(pinfo->t, pinfo->pp, p, ctx)) {
BN_free(p);
goto err;
}
}
/* We MUST free p before any further use of rsa->p */
BN_free(p);
}
ok = 1;
err:
if (ok == -1) {
RSAerr(RSA_F_RSA_BUILTIN_KEYGEN, ERR_LIB_BN);
ok = 0;
}
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ok;
}
diff --git a/crypto/rsa/rsa_oaep.c b/crypto/rsa/rsa_oaep.c
index 689e6dc22292..48b888bf27ad 100644
--- a/crypto/rsa/rsa_oaep.c
+++ b/crypto/rsa/rsa_oaep.c
@@ -1,313 +1,313 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/* EME-OAEP as defined in RFC 2437 (PKCS #1 v2.0) */
/*
* See Victor Shoup, "OAEP reconsidered," Nov. 2000, <URL:
* http://www.shoup.net/papers/oaep.ps.Z> for problems with the security
* proof for the original OAEP scheme, which EME-OAEP is based on. A new
* proof can be found in E. Fujisaki, T. Okamoto, D. Pointcheval, J. Stern,
* "RSA-OEAP is Still Alive!", Dec. 2000, <URL:
* http://eprint.iacr.org/2000/061/>. The new proof has stronger requirements
* for the underlying permutation: "partial-one-wayness" instead of
* one-wayness. For the RSA function, this is an equivalent notion.
*/
#include "internal/constant_time_locl.h"
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include "rsa_locl.h"
int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *from, int flen,
const unsigned char *param, int plen)
{
return RSA_padding_add_PKCS1_OAEP_mgf1(to, tlen, from, flen,
param, plen, NULL, NULL);
}
int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
const unsigned char *from, int flen,
const unsigned char *param, int plen,
const EVP_MD *md, const EVP_MD *mgf1md)
{
int rv = 0;
int i, emlen = tlen - 1;
unsigned char *db, *seed;
unsigned char *dbmask = NULL;
unsigned char seedmask[EVP_MAX_MD_SIZE];
int mdlen, dbmask_len = 0;
if (md == NULL)
md = EVP_sha1();
if (mgf1md == NULL)
mgf1md = md;
mdlen = EVP_MD_size(md);
if (flen > emlen - 2 * mdlen - 1) {
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
if (emlen < 2 * mdlen + 1) {
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1,
RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
to[0] = 0;
seed = to + 1;
db = to + mdlen + 1;
if (!EVP_Digest((void *)param, plen, db, NULL, md, NULL))
goto err;
memset(db + mdlen, 0, emlen - flen - 2 * mdlen - 1);
db[emlen - flen - mdlen - 1] = 0x01;
memcpy(db + emlen - flen - mdlen, from, (unsigned int)flen);
if (RAND_bytes(seed, mdlen) <= 0)
goto err;
dbmask_len = emlen - mdlen;
dbmask = OPENSSL_malloc(dbmask_len);
if (dbmask == NULL) {
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
goto err;
}
if (PKCS1_MGF1(dbmask, dbmask_len, seed, mdlen, mgf1md) < 0)
goto err;
for (i = 0; i < dbmask_len; i++)
db[i] ^= dbmask[i];
if (PKCS1_MGF1(seedmask, mdlen, db, dbmask_len, mgf1md) < 0)
goto err;
for (i = 0; i < mdlen; i++)
seed[i] ^= seedmask[i];
rv = 1;
err:
OPENSSL_cleanse(seedmask, sizeof(seedmask));
OPENSSL_clear_free(dbmask, dbmask_len);
return rv;
}
int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
const unsigned char *from, int flen, int num,
const unsigned char *param, int plen)
{
return RSA_padding_check_PKCS1_OAEP_mgf1(to, tlen, from, flen, num,
param, plen, NULL, NULL);
}
int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
const unsigned char *from, int flen,
int num, const unsigned char *param,
int plen, const EVP_MD *md,
const EVP_MD *mgf1md)
{
int i, dblen = 0, mlen = -1, one_index = 0, msg_index;
unsigned int good = 0, found_one_byte, mask;
const unsigned char *maskedseed, *maskeddb;
/*
* |em| is the encoded message, zero-padded to exactly |num| bytes: em =
* Y || maskedSeed || maskedDB
*/
unsigned char *db = NULL, *em = NULL, seed[EVP_MAX_MD_SIZE],
phash[EVP_MAX_MD_SIZE];
int mdlen;
if (md == NULL)
md = EVP_sha1();
if (mgf1md == NULL)
mgf1md = md;
mdlen = EVP_MD_size(md);
if (tlen <= 0 || flen <= 0)
return -1;
/*
* |num| is the length of the modulus; |flen| is the length of the
* encoded message. Therefore, for any |from| that was obtained by
* decrypting a ciphertext, we must have |flen| <= |num|. Similarly,
- * num < 2 * mdlen + 2 must hold for the modulus irrespective of
+ * |num| >= 2 * |mdlen| + 2 must hold for the modulus irrespective of
* the ciphertext, see PKCS #1 v2.2, section 7.1.2.
* This does not leak any side-channel information.
*/
if (num < flen || num < 2 * mdlen + 2) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
RSA_R_OAEP_DECODING_ERROR);
return -1;
}
dblen = num - mdlen - 1;
db = OPENSSL_malloc(dblen);
if (db == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1, ERR_R_MALLOC_FAILURE);
goto cleanup;
}
em = OPENSSL_malloc(num);
if (em == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
ERR_R_MALLOC_FAILURE);
goto cleanup;
}
/*
* Caller is encouraged to pass zero-padded message created with
* BN_bn2binpad. Trouble is that since we can't read out of |from|'s
* bounds, it's impossible to have an invariant memory access pattern
* in case |from| was not zero-padded in advance.
*/
for (from += flen, em += num, i = 0; i < num; i++) {
mask = ~constant_time_is_zero(flen);
flen -= 1 & mask;
from -= 1 & mask;
*--em = *from & mask;
}
- from = em;
/*
* The first byte must be zero, however we must not leak if this is
* true. See James H. Manger, "A Chosen Ciphertext Attack on RSA
* Optimal Asymmetric Encryption Padding (OAEP) [...]", CRYPTO 2001).
*/
- good = constant_time_is_zero(from[0]);
+ good = constant_time_is_zero(em[0]);
- maskedseed = from + 1;
- maskeddb = from + 1 + mdlen;
+ maskedseed = em + 1;
+ maskeddb = em + 1 + mdlen;
if (PKCS1_MGF1(seed, mdlen, maskeddb, dblen, mgf1md))
goto cleanup;
for (i = 0; i < mdlen; i++)
seed[i] ^= maskedseed[i];
if (PKCS1_MGF1(db, dblen, seed, mdlen, mgf1md))
goto cleanup;
for (i = 0; i < dblen; i++)
db[i] ^= maskeddb[i];
if (!EVP_Digest((void *)param, plen, phash, NULL, md, NULL))
goto cleanup;
good &= constant_time_is_zero(CRYPTO_memcmp(db, phash, mdlen));
found_one_byte = 0;
for (i = mdlen; i < dblen; i++) {
/*
* Padding consists of a number of 0-bytes, followed by a 1.
*/
unsigned int equals1 = constant_time_eq(db[i], 1);
unsigned int equals0 = constant_time_is_zero(db[i]);
one_index = constant_time_select_int(~found_one_byte & equals1,
i, one_index);
found_one_byte |= equals1;
good &= (found_one_byte | equals0);
}
good &= found_one_byte;
/*
* At this point |good| is zero unless the plaintext was valid,
* so plaintext-awareness ensures timing side-channels are no longer a
* concern.
*/
msg_index = one_index + 1;
mlen = dblen - msg_index;
/*
- * For good measure, do this check in constant tine as well.
+ * For good measure, do this check in constant time as well.
*/
good &= constant_time_ge(tlen, mlen);
/*
- * Even though we can't fake result's length, we can pretend copying
- * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |dblen|
- * bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
- * where |mlen'| is "saturated" |mlen| value. Deducing information
- * about failure or |mlen| would take attacker's ability to observe
- * memory access pattern with byte granularity *as it occurs*. It
- * should be noted that failure is indistinguishable from normal
- * operation if |tlen| is fixed by protocol.
+ * Move the result in-place by |dblen|-|mdlen|-1-|mlen| bytes to the left.
+ * Then if |good| move |mlen| bytes from |db|+|mdlen|+1 to |to|.
+ * Otherwise leave |to| unchanged.
+ * Copy the memory back in a way that does not reveal the size of
+ * the data being copied via a timing side channel. This requires copying
+ * parts of the buffer multiple times based on the bits set in the real
+ * length. Clear bits do a non-copy with identical access pattern.
+ * The loop below has overall complexity of O(N*log(N)).
*/
- tlen = constant_time_select_int(constant_time_lt(dblen, tlen), dblen, tlen);
- msg_index = constant_time_select_int(good, msg_index, dblen - tlen);
- mlen = dblen - msg_index;
- for (from = db + msg_index, mask = good, i = 0; i < tlen; i++) {
- unsigned int equals = constant_time_eq(i, mlen);
-
- from -= dblen & equals; /* if (i == dblen) rewind */
- mask &= mask ^ equals; /* if (i == dblen) mask = 0 */
- to[i] = constant_time_select_8(mask, from[i], to[i]);
+ tlen = constant_time_select_int(constant_time_lt(dblen - mdlen - 1, tlen),
+ dblen - mdlen - 1, tlen);
+ for (msg_index = 1; msg_index < dblen - mdlen - 1; msg_index <<= 1) {
+ mask = ~constant_time_eq(msg_index & (dblen - mdlen - 1 - mlen), 0);
+ for (i = mdlen + 1; i < dblen - msg_index; i++)
+ db[i] = constant_time_select_8(mask, db[i + msg_index], db[i]);
+ }
+ for (i = 0; i < tlen; i++) {
+ mask = good & constant_time_lt(i, mlen);
+ to[i] = constant_time_select_8(mask, db[i + mdlen + 1], to[i]);
}
/*
* To avoid chosen ciphertext attacks, the error message should not
* reveal which kind of decoding error happened.
*/
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1,
RSA_R_OAEP_DECODING_ERROR);
err_clear_last_constant_time(1 & good);
cleanup:
OPENSSL_cleanse(seed, sizeof(seed));
OPENSSL_clear_free(db, dblen);
OPENSSL_clear_free(em, num);
return constant_time_select_int(good, mlen, -1);
}
int PKCS1_MGF1(unsigned char *mask, long len,
const unsigned char *seed, long seedlen, const EVP_MD *dgst)
{
long i, outlen = 0;
unsigned char cnt[4];
EVP_MD_CTX *c = EVP_MD_CTX_new();
unsigned char md[EVP_MAX_MD_SIZE];
int mdlen;
int rv = -1;
if (c == NULL)
goto err;
mdlen = EVP_MD_size(dgst);
if (mdlen < 0)
goto err;
for (i = 0; outlen < len; i++) {
cnt[0] = (unsigned char)((i >> 24) & 255);
cnt[1] = (unsigned char)((i >> 16) & 255);
cnt[2] = (unsigned char)((i >> 8)) & 255;
cnt[3] = (unsigned char)(i & 255);
if (!EVP_DigestInit_ex(c, dgst, NULL)
|| !EVP_DigestUpdate(c, seed, seedlen)
|| !EVP_DigestUpdate(c, cnt, 4))
goto err;
if (outlen + mdlen <= len) {
if (!EVP_DigestFinal_ex(c, mask + outlen, NULL))
goto err;
outlen += mdlen;
} else {
if (!EVP_DigestFinal_ex(c, md, NULL))
goto err;
memcpy(mask + outlen, md, len - outlen);
outlen = len;
}
}
rv = 0;
err:
OPENSSL_cleanse(md, sizeof(md));
EVP_MD_CTX_free(c);
return rv;
}
diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c
index 465134257fcc..33be9ea8cb84 100644
--- a/crypto/rsa/rsa_ossl.c
+++ b/crypto/rsa/rsa_ossl.c
@@ -1,970 +1,966 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/cryptlib.h"
#include "internal/bn_int.h"
#include "rsa_locl.h"
#include "internal/constant_time_locl.h"
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *i, RSA *rsa,
BN_CTX *ctx);
static int rsa_ossl_init(RSA *rsa);
static int rsa_ossl_finish(RSA *rsa);
static RSA_METHOD rsa_pkcs1_ossl_meth = {
"OpenSSL PKCS#1 RSA",
rsa_ossl_public_encrypt,
rsa_ossl_public_decrypt, /* signature verification */
rsa_ossl_private_encrypt, /* signing */
rsa_ossl_private_decrypt,
rsa_ossl_mod_exp,
BN_mod_exp_mont, /* XXX probably we should not use Montgomery
* if e == 3 */
rsa_ossl_init,
rsa_ossl_finish,
RSA_FLAG_FIPS_METHOD, /* flags */
NULL,
0, /* rsa_sign */
0, /* rsa_verify */
NULL, /* rsa_keygen */
NULL /* rsa_multi_prime_keygen */
};
static const RSA_METHOD *default_RSA_meth = &rsa_pkcs1_ossl_meth;
void RSA_set_default_method(const RSA_METHOD *meth)
{
default_RSA_meth = meth;
}
const RSA_METHOD *RSA_get_default_method(void)
{
return default_RSA_meth;
}
const RSA_METHOD *RSA_PKCS1_OpenSSL(void)
{
return &rsa_pkcs1_ossl_meth;
}
const RSA_METHOD *RSA_null_method(void)
{
return NULL;
}
static int rsa_ossl_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_MODULUS_TOO_LARGE);
return -1;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
return -1;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_BAD_E_VALUE);
return -1;
}
}
if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
switch (padding) {
case RSA_PKCS1_PADDING:
i = RSA_padding_add_PKCS1_type_2(buf, num, from, flen);
break;
case RSA_PKCS1_OAEP_PADDING:
i = RSA_padding_add_PKCS1_OAEP(buf, num, from, flen, NULL, 0);
break;
case RSA_SSLV23_PADDING:
i = RSA_padding_add_SSLv23(buf, num, from, flen);
break;
case RSA_NO_PADDING:
i = RSA_padding_add_none(buf, num, from, flen);
break;
default:
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (i <= 0)
goto err;
if (BN_bin2bn(buf, num, f) == NULL)
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
/* usually the padding functions would catch this */
RSAerr(RSA_F_RSA_OSSL_PUBLIC_ENCRYPT,
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
goto err;
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
/*
* BN_bn2binpad puts in leading 0 bytes if the number is less than
* the length of the modulus.
*/
r = BN_bn2binpad(ret, to, num);
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
}
static BN_BLINDING *rsa_get_blinding(RSA *rsa, int *local, BN_CTX *ctx)
{
BN_BLINDING *ret;
CRYPTO_THREAD_write_lock(rsa->lock);
if (rsa->blinding == NULL) {
rsa->blinding = RSA_setup_blinding(rsa, ctx);
}
ret = rsa->blinding;
if (ret == NULL)
goto err;
if (BN_BLINDING_is_current_thread(ret)) {
/* rsa->blinding is ours! */
*local = 1;
} else {
/* resort to rsa->mt_blinding instead */
/*
* instructs rsa_blinding_convert(), rsa_blinding_invert() that the
* BN_BLINDING is shared, meaning that accesses require locks, and
* that the blinding factor must be stored outside the BN_BLINDING
*/
*local = 0;
if (rsa->mt_blinding == NULL) {
rsa->mt_blinding = RSA_setup_blinding(rsa, ctx);
}
ret = rsa->mt_blinding;
}
err:
CRYPTO_THREAD_unlock(rsa->lock);
return ret;
}
static int rsa_blinding_convert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
BN_CTX *ctx)
{
if (unblind == NULL) {
/*
* Local blinding: store the unblinding factor in BN_BLINDING.
*/
return BN_BLINDING_convert_ex(f, NULL, b, ctx);
} else {
/*
* Shared blinding: store the unblinding factor outside BN_BLINDING.
*/
int ret;
BN_BLINDING_lock(b);
ret = BN_BLINDING_convert_ex(f, unblind, b, ctx);
BN_BLINDING_unlock(b);
return ret;
}
}
static int rsa_blinding_invert(BN_BLINDING *b, BIGNUM *f, BIGNUM *unblind,
BN_CTX *ctx)
{
/*
* For local blinding, unblind is set to NULL, and BN_BLINDING_invert_ex
* will use the unblinding factor stored in BN_BLINDING. If BN_BLINDING
* is shared between threads, unblind must be non-null:
* BN_BLINDING_invert_ex will then use the local unblinding factor, and
* will only read the modulus from BN_BLINDING. In both cases it's safe
* to access the blinding without a lock.
*/
return BN_BLINDING_invert_ex(f, unblind, b, ctx);
}
/* signing */
static int rsa_ossl_private_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret, *res;
int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
int local_blinding = 0;
/*
* Used only if the blinding structure is shared. A non-NULL unblind
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
* the unblinding factor outside the blinding structure.
*/
BIGNUM *unblind = NULL;
BN_BLINDING *blinding = NULL;
if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
switch (padding) {
case RSA_PKCS1_PADDING:
i = RSA_padding_add_PKCS1_type_1(buf, num, from, flen);
break;
case RSA_X931_PADDING:
i = RSA_padding_add_X931(buf, num, from, flen);
break;
case RSA_NO_PADDING:
i = RSA_padding_add_none(buf, num, from, flen);
break;
case RSA_SSLV23_PADDING:
default:
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (i <= 0)
goto err;
if (BN_bin2bn(buf, num, f) == NULL)
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
/* usually the padding functions would catch this */
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT,
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
goto err;
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
if (blinding == NULL) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (blinding != NULL) {
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
goto err;
}
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
(rsa->version == RSA_ASN1_VERSION_MULTI) ||
((rsa->p != NULL) &&
(rsa->q != NULL) &&
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
goto err;
} else {
BIGNUM *d = BN_new();
if (d == NULL) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_ENCRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx,
rsa->_method_mod_n)) {
BN_free(d);
goto err;
}
/* We MUST free d before any further use of rsa->d */
BN_free(d);
}
if (blinding)
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
goto err;
if (padding == RSA_X931_PADDING) {
if (!BN_sub(f, rsa->n, ret))
goto err;
if (BN_cmp(ret, f) > 0)
res = f;
else
res = ret;
} else {
res = ret;
}
/*
* BN_bn2binpad puts in leading 0 bytes if the number is less than
* the length of the modulus.
*/
r = BN_bn2binpad(res, to, num);
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
}
static int rsa_ossl_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
int j, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
int local_blinding = 0;
/*
* Used only if the blinding structure is shared. A non-NULL unblind
* instructs rsa_blinding_convert() and rsa_blinding_invert() to store
* the unblinding factor outside the blinding structure.
*/
BIGNUM *unblind = NULL;
BN_BLINDING *blinding = NULL;
if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* This check was for equality but PGP does evil things and chops off the
* top '0' bytes
*/
if (flen > num) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT,
RSA_R_DATA_GREATER_THAN_MOD_LEN);
goto err;
}
/* make data into a big number */
if (BN_bin2bn(from, (int)flen, f) == NULL)
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT,
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
blinding = rsa_get_blinding(rsa, &local_blinding, ctx);
if (blinding == NULL) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (blinding != NULL) {
if (!local_blinding && ((unblind = BN_CTX_get(ctx)) == NULL)) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!rsa_blinding_convert(blinding, f, unblind, ctx))
goto err;
}
/* do the decrypt */
if ((rsa->flags & RSA_FLAG_EXT_PKEY) ||
(rsa->version == RSA_ASN1_VERSION_MULTI) ||
((rsa->p != NULL) &&
(rsa->q != NULL) &&
(rsa->dmp1 != NULL) && (rsa->dmq1 != NULL) && (rsa->iqmp != NULL))) {
if (!rsa->meth->rsa_mod_exp(ret, f, rsa, ctx))
goto err;
} else {
BIGNUM *d = BN_new();
if (d == NULL) {
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx)) {
BN_free(d);
goto err;
}
if (!rsa->meth->bn_mod_exp(ret, f, d, rsa->n, ctx,
rsa->_method_mod_n)) {
BN_free(d);
goto err;
}
/* We MUST free d before any further use of rsa->d */
BN_free(d);
}
if (blinding)
if (!rsa_blinding_invert(blinding, ret, unblind, ctx))
goto err;
j = BN_bn2binpad(ret, buf, num);
switch (padding) {
case RSA_PKCS1_PADDING:
r = RSA_padding_check_PKCS1_type_2(to, num, buf, j, num);
break;
case RSA_PKCS1_OAEP_PADDING:
r = RSA_padding_check_PKCS1_OAEP(to, num, buf, j, num, NULL, 0);
break;
case RSA_SSLV23_PADDING:
r = RSA_padding_check_SSLv23(to, num, buf, j, num);
break;
case RSA_NO_PADDING:
memcpy(to, buf, (r = j));
break;
default:
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
RSAerr(RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
- err_clear_last_constant_time(r >= 0);
+ err_clear_last_constant_time(1 & ~constant_time_msb(r));
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
}
/* signature verification */
static int rsa_ossl_public_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding)
{
BIGNUM *f, *ret;
int i, num = 0, r = -1;
unsigned char *buf = NULL;
BN_CTX *ctx = NULL;
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_MODULUS_TOO_LARGE);
return -1;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
return -1;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS) {
if (BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_BAD_E_VALUE);
return -1;
}
}
if ((ctx = BN_CTX_new()) == NULL)
goto err;
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
ret = BN_CTX_get(ctx);
num = BN_num_bytes(rsa->n);
buf = OPENSSL_malloc(num);
if (ret == NULL || buf == NULL) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, ERR_R_MALLOC_FAILURE);
goto err;
}
/*
* This check was for equality but PGP does evil things and chops off the
* top '0' bytes
*/
if (flen > num) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN);
goto err;
}
if (BN_bin2bn(from, flen, f) == NULL)
goto err;
if (BN_ucmp(f, rsa->n) >= 0) {
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT,
RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
goto err;
if (!rsa->meth->bn_mod_exp(ret, f, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
if ((padding == RSA_X931_PADDING) && ((bn_get_words(ret)[0] & 0xf) != 12))
if (!BN_sub(ret, rsa->n, ret))
goto err;
i = BN_bn2binpad(ret, buf, num);
switch (padding) {
case RSA_PKCS1_PADDING:
r = RSA_padding_check_PKCS1_type_1(to, num, buf, i, num);
break;
case RSA_X931_PADDING:
r = RSA_padding_check_X931(to, num, buf, i, num);
break;
case RSA_NO_PADDING:
memcpy(to, buf, (r = i));
break;
default:
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (r < 0)
RSAerr(RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_PADDING_CHECK_FAILED);
err:
- if (ctx != NULL)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
OPENSSL_clear_free(buf, num);
return r;
}
static int rsa_ossl_mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx)
{
BIGNUM *r1, *m1, *vrfy, *r2, *m[RSA_MAX_PRIME_NUM - 2];
int ret = 0, i, ex_primes = 0, smooth = 0;
RSA_PRIME_INFO *pinfo;
BN_CTX_start(ctx);
r1 = BN_CTX_get(ctx);
r2 = BN_CTX_get(ctx);
m1 = BN_CTX_get(ctx);
vrfy = BN_CTX_get(ctx);
if (vrfy == NULL)
goto err;
if (rsa->version == RSA_ASN1_VERSION_MULTI
&& ((ex_primes = sk_RSA_PRIME_INFO_num(rsa->prime_infos)) <= 0
|| ex_primes > RSA_MAX_PRIME_NUM - 2))
goto err;
if (rsa->flags & RSA_FLAG_CACHE_PRIVATE) {
BIGNUM *factor = BN_new();
if (factor == NULL)
goto err;
/*
* Make sure BN_mod_inverse in Montgomery initialization uses the
* BN_FLG_CONSTTIME flag
*/
if (!(BN_with_flags(factor, rsa->p, BN_FLG_CONSTTIME),
BN_MONT_CTX_set_locked(&rsa->_method_mod_p, rsa->lock,
factor, ctx))
|| !(BN_with_flags(factor, rsa->q, BN_FLG_CONSTTIME),
BN_MONT_CTX_set_locked(&rsa->_method_mod_q, rsa->lock,
factor, ctx))) {
BN_free(factor);
goto err;
}
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_with_flags(factor, pinfo->r, BN_FLG_CONSTTIME);
if (!BN_MONT_CTX_set_locked(&pinfo->m, rsa->lock, factor, ctx)) {
BN_free(factor);
goto err;
}
}
/*
* We MUST free |factor| before any further use of the prime factors
*/
BN_free(factor);
smooth = (ex_primes == 0)
&& (rsa->meth->bn_mod_exp == BN_mod_exp_mont)
&& (BN_num_bits(rsa->q) == BN_num_bits(rsa->p));
}
if (rsa->flags & RSA_FLAG_CACHE_PUBLIC)
if (!BN_MONT_CTX_set_locked(&rsa->_method_mod_n, rsa->lock,
rsa->n, ctx))
goto err;
if (smooth) {
/*
* Conversion from Montgomery domain, a.k.a. Montgomery reduction,
* accepts values in [0-m*2^w) range. w is m's bit width rounded up
* to limb width. So that at the very least if |I| is fully reduced,
* i.e. less than p*q, we can count on from-to round to perform
* below modulo operations on |I|. Unlike BN_mod it's constant time.
*/
if (/* m1 = I moq q */
!bn_from_mont_fixed_top(m1, I, rsa->_method_mod_q, ctx)
|| !bn_to_mont_fixed_top(m1, m1, rsa->_method_mod_q, ctx)
/* m1 = m1^dmq1 mod q */
|| !BN_mod_exp_mont_consttime(m1, m1, rsa->dmq1, rsa->q, ctx,
rsa->_method_mod_q)
/* r1 = I mod p */
|| !bn_from_mont_fixed_top(r1, I, rsa->_method_mod_p, ctx)
|| !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)
/* r1 = r1^dmp1 mod p */
|| !BN_mod_exp_mont_consttime(r1, r1, rsa->dmp1, rsa->p, ctx,
rsa->_method_mod_p)
/* r1 = (r1 - m1) mod p */
/*
* bn_mod_sub_fixed_top is not regular modular subtraction,
* it can tolerate subtrahend to be larger than modulus, but
* not bit-wise wider. This makes up for uncommon q>p case,
* when |m1| can be larger than |rsa->p|.
*/
|| !bn_mod_sub_fixed_top(r1, r1, m1, rsa->p)
/* r1 = r1 * iqmp mod p */
|| !bn_to_mont_fixed_top(r1, r1, rsa->_method_mod_p, ctx)
|| !bn_mul_mont_fixed_top(r1, r1, rsa->iqmp, rsa->_method_mod_p,
ctx)
/* r0 = r1 * q + m1 */
|| !bn_mul_fixed_top(r0, r1, rsa->q, ctx)
|| !bn_mod_add_fixed_top(r0, r0, m1, rsa->n))
goto err;
goto tail;
}
/* compute I mod q */
{
BIGNUM *c = BN_new();
if (c == NULL)
goto err;
BN_with_flags(c, I, BN_FLG_CONSTTIME);
if (!BN_mod(r1, c, rsa->q, ctx)) {
BN_free(c);
goto err;
}
{
BIGNUM *dmq1 = BN_new();
if (dmq1 == NULL) {
BN_free(c);
goto err;
}
BN_with_flags(dmq1, rsa->dmq1, BN_FLG_CONSTTIME);
/* compute r1^dmq1 mod q */
if (!rsa->meth->bn_mod_exp(m1, r1, dmq1, rsa->q, ctx,
rsa->_method_mod_q)) {
BN_free(c);
BN_free(dmq1);
goto err;
}
/* We MUST free dmq1 before any further use of rsa->dmq1 */
BN_free(dmq1);
}
/* compute I mod p */
if (!BN_mod(r1, c, rsa->p, ctx)) {
BN_free(c);
goto err;
}
/* We MUST free c before any further use of I */
BN_free(c);
}
{
BIGNUM *dmp1 = BN_new();
if (dmp1 == NULL)
goto err;
BN_with_flags(dmp1, rsa->dmp1, BN_FLG_CONSTTIME);
/* compute r1^dmp1 mod p */
if (!rsa->meth->bn_mod_exp(r0, r1, dmp1, rsa->p, ctx,
rsa->_method_mod_p)) {
BN_free(dmp1);
goto err;
}
/* We MUST free dmp1 before any further use of rsa->dmp1 */
BN_free(dmp1);
}
/*
* calculate m_i in multi-prime case
*
* TODO:
* 1. squash the following two loops and calculate |m_i| there.
* 2. remove cc and reuse |c|.
* 3. remove |dmq1| and |dmp1| in previous block and use |di|.
*
* If these things are done, the code will be more readable.
*/
if (ex_primes > 0) {
BIGNUM *di = BN_new(), *cc = BN_new();
if (cc == NULL || di == NULL) {
BN_free(cc);
BN_free(di);
goto err;
}
for (i = 0; i < ex_primes; i++) {
/* prepare m_i */
if ((m[i] = BN_CTX_get(ctx)) == NULL) {
BN_free(cc);
BN_free(di);
goto err;
}
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
/* prepare c and d_i */
BN_with_flags(cc, I, BN_FLG_CONSTTIME);
BN_with_flags(di, pinfo->d, BN_FLG_CONSTTIME);
if (!BN_mod(r1, cc, pinfo->r, ctx)) {
BN_free(cc);
BN_free(di);
goto err;
}
/* compute r1 ^ d_i mod r_i */
if (!rsa->meth->bn_mod_exp(m[i], r1, di, pinfo->r, ctx, pinfo->m)) {
BN_free(cc);
BN_free(di);
goto err;
}
}
BN_free(cc);
BN_free(di);
}
if (!BN_sub(r0, r0, m1))
goto err;
/*
* This will help stop the size of r0 increasing, which does affect the
* multiply if it optimised for a power of 2 size
*/
if (BN_is_negative(r0))
if (!BN_add(r0, r0, rsa->p))
goto err;
if (!BN_mul(r1, r0, rsa->iqmp, ctx))
goto err;
{
BIGNUM *pr1 = BN_new();
if (pr1 == NULL)
goto err;
BN_with_flags(pr1, r1, BN_FLG_CONSTTIME);
if (!BN_mod(r0, pr1, rsa->p, ctx)) {
BN_free(pr1);
goto err;
}
/* We MUST free pr1 before any further use of r1 */
BN_free(pr1);
}
/*
* If p < q it is occasionally possible for the correction of adding 'p'
* if r0 is negative above to leave the result still negative. This can
* break the private key operations: the following second correction
* should *always* correct this rare occurrence. This will *never* happen
* with OpenSSL generated keys because they ensure p > q [steve]
*/
if (BN_is_negative(r0))
if (!BN_add(r0, r0, rsa->p))
goto err;
if (!BN_mul(r1, r0, rsa->q, ctx))
goto err;
if (!BN_add(r0, r1, m1))
goto err;
/* add m_i to m in multi-prime case */
if (ex_primes > 0) {
BIGNUM *pr2 = BN_new();
if (pr2 == NULL)
goto err;
for (i = 0; i < ex_primes; i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
if (!BN_sub(r1, m[i], r0)) {
BN_free(pr2);
goto err;
}
if (!BN_mul(r2, r1, pinfo->t, ctx)) {
BN_free(pr2);
goto err;
}
BN_with_flags(pr2, r2, BN_FLG_CONSTTIME);
if (!BN_mod(r1, pr2, pinfo->r, ctx)) {
BN_free(pr2);
goto err;
}
if (BN_is_negative(r1))
if (!BN_add(r1, r1, pinfo->r)) {
BN_free(pr2);
goto err;
}
if (!BN_mul(r1, r1, pinfo->pp, ctx)) {
BN_free(pr2);
goto err;
}
if (!BN_add(r0, r0, r1)) {
BN_free(pr2);
goto err;
}
}
BN_free(pr2);
}
tail:
if (rsa->e && rsa->n) {
if (rsa->meth->bn_mod_exp == BN_mod_exp_mont) {
if (!BN_mod_exp_mont(vrfy, r0, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
} else {
bn_correct_top(r0);
if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
rsa->_method_mod_n))
goto err;
}
/*
* If 'I' was greater than (or equal to) rsa->n, the operation will
* be equivalent to using 'I mod n'. However, the result of the
* verify will *always* be less than 'n' so we don't check for
* absolute equality, just congruency.
*/
if (!BN_sub(vrfy, vrfy, I))
goto err;
if (BN_is_zero(vrfy)) {
bn_correct_top(r0);
ret = 1;
goto err; /* not actually error */
}
if (!BN_mod(vrfy, vrfy, rsa->n, ctx))
goto err;
if (BN_is_negative(vrfy))
if (!BN_add(vrfy, vrfy, rsa->n))
goto err;
if (!BN_is_zero(vrfy)) {
/*
* 'I' and 'vrfy' aren't congruent mod n. Don't leak
* miscalculated CRT output, just do a raw (slower) mod_exp and
* return that instead.
*/
BIGNUM *d = BN_new();
if (d == NULL)
goto err;
BN_with_flags(d, rsa->d, BN_FLG_CONSTTIME);
if (!rsa->meth->bn_mod_exp(r0, I, d, rsa->n, ctx,
rsa->_method_mod_n)) {
BN_free(d);
goto err;
}
/* We MUST free d before any further use of rsa->d */
BN_free(d);
}
}
/*
* It's unfortunate that we have to bn_correct_top(r0). What hopefully
* saves the day is that correction is highly unlike, and private key
* operations are customarily performed on blinded message. Which means
* that attacker won't observe correlation with chosen plaintext.
* Secondly, remaining code would still handle it in same computational
* time and even conceal memory access pattern around corrected top.
*/
bn_correct_top(r0);
ret = 1;
err:
BN_CTX_end(ctx);
return ret;
}
static int rsa_ossl_init(RSA *rsa)
{
rsa->flags |= RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE;
return 1;
}
static int rsa_ossl_finish(RSA *rsa)
{
int i;
RSA_PRIME_INFO *pinfo;
BN_MONT_CTX_free(rsa->_method_mod_n);
BN_MONT_CTX_free(rsa->_method_mod_p);
BN_MONT_CTX_free(rsa->_method_mod_q);
for (i = 0; i < sk_RSA_PRIME_INFO_num(rsa->prime_infos); i++) {
pinfo = sk_RSA_PRIME_INFO_value(rsa->prime_infos, i);
BN_MONT_CTX_free(pinfo->m);
}
return 1;
}
diff --git a/crypto/rsa/rsa_pk1.c b/crypto/rsa/rsa_pk1.c
index 062690741809..5260d12f4c91 100644
--- a/crypto/rsa/rsa_pk1.c
+++ b/crypto/rsa/rsa_pk1.c
@@ -1,255 +1,255 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include "internal/constant_time_locl.h"
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *from, int flen)
{
int j;
unsigned char *p;
if (flen > (tlen - RSA_PKCS1_PADDING_SIZE)) {
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1,
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
p = (unsigned char *)to;
*(p++) = 0;
*(p++) = 1; /* Private Key BT (Block Type) */
/* pad out with 0xff data */
j = tlen - 3 - flen;
memset(p, 0xff, j);
p += j;
*(p++) = '\0';
memcpy(p, from, (unsigned int)flen);
return 1;
}
int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
const unsigned char *from, int flen,
int num)
{
int i, j;
const unsigned char *p;
p = from;
/*
* The format is
* 00 || 01 || PS || 00 || D
* PS - padding string, at least 8 bytes of FF
* D - data.
*/
if (num < 11)
return -1;
/* Accept inputs with and without the leading 0-byte. */
if (num == flen) {
if ((*p++) != 0x00) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
RSA_R_INVALID_PADDING);
return -1;
}
flen--;
}
if ((num != (flen + 1)) || (*(p++) != 0x01)) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
RSA_R_BLOCK_TYPE_IS_NOT_01);
return -1;
}
/* scan over padding data */
j = flen - 1; /* one for type. */
for (i = 0; i < j; i++) {
if (*p != 0xff) { /* should decrypt to 0xff */
if (*p == 0) {
p++;
break;
} else {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
RSA_R_BAD_FIXED_HEADER_DECRYPT);
return -1;
}
}
p++;
}
if (i == j) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
RSA_R_NULL_BEFORE_BLOCK_MISSING);
return -1;
}
if (i < 8) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1,
RSA_R_BAD_PAD_BYTE_COUNT);
return -1;
}
i++; /* Skip over the '\0' */
j -= i;
if (j > tlen) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1, RSA_R_DATA_TOO_LARGE);
return -1;
}
memcpy(to, p, (unsigned int)j);
return j;
}
int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
const unsigned char *from, int flen)
{
int i, j;
unsigned char *p;
if (flen > (tlen - 11)) {
RSAerr(RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2,
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
p = (unsigned char *)to;
*(p++) = 0;
*(p++) = 2; /* Public Key BT (Block Type) */
/* pad out with non-zero random data */
j = tlen - 3 - flen;
if (RAND_bytes(p, j) <= 0)
return 0;
for (i = 0; i < j; i++) {
if (*p == '\0')
do {
if (RAND_bytes(p, 1) <= 0)
return 0;
} while (*p == '\0');
p++;
}
*(p++) = '\0';
memcpy(p, from, (unsigned int)flen);
return 1;
}
int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
const unsigned char *from, int flen,
int num)
{
int i;
/* |em| is the encoded message, zero-padded to exactly |num| bytes */
unsigned char *em = NULL;
unsigned int good, found_zero_byte, mask;
int zero_index = 0, msg_index, mlen = -1;
if (tlen <= 0 || flen <= 0)
return -1;
/*
* PKCS#1 v1.5 decryption. See "PKCS #1 v2.2: RSA Cryptography Standard",
* section 7.2.2.
*/
if (flen > num || num < 11) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2,
RSA_R_PKCS_DECODING_ERROR);
return -1;
}
em = OPENSSL_malloc(num);
if (em == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, ERR_R_MALLOC_FAILURE);
return -1;
}
/*
* Caller is encouraged to pass zero-padded message created with
* BN_bn2binpad. Trouble is that since we can't read out of |from|'s
* bounds, it's impossible to have an invariant memory access pattern
* in case |from| was not zero-padded in advance.
*/
for (from += flen, em += num, i = 0; i < num; i++) {
mask = ~constant_time_is_zero(flen);
flen -= 1 & mask;
from -= 1 & mask;
*--em = *from & mask;
}
- from = em;
- good = constant_time_is_zero(from[0]);
- good &= constant_time_eq(from[1], 2);
+ good = constant_time_is_zero(em[0]);
+ good &= constant_time_eq(em[1], 2);
/* scan over padding data */
found_zero_byte = 0;
for (i = 2; i < num; i++) {
- unsigned int equals0 = constant_time_is_zero(from[i]);
+ unsigned int equals0 = constant_time_is_zero(em[i]);
zero_index = constant_time_select_int(~found_zero_byte & equals0,
i, zero_index);
found_zero_byte |= equals0;
}
/*
- * PS must be at least 8 bytes long, and it starts two bytes into |from|.
+ * PS must be at least 8 bytes long, and it starts two bytes into |em|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
good &= constant_time_ge(zero_index, 2 + 8);
/*
* Skip the zero byte. This is incorrect if we never found a zero-byte
* but in this case we also do not copy the message out.
*/
msg_index = zero_index + 1;
mlen = num - msg_index;
/*
* For good measure, do this check in constant time as well.
*/
good &= constant_time_ge(tlen, mlen);
/*
- * Even though we can't fake result's length, we can pretend copying
- * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num|
- * bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
- * where |mlen'| is "saturated" |mlen| value. Deducing information
- * about failure or |mlen| would take attacker's ability to observe
- * memory access pattern with byte granularity *as it occurs*. It
- * should be noted that failure is indistinguishable from normal
- * operation if |tlen| is fixed by protocol.
+ * Move the result in-place by |num|-11-|mlen| bytes to the left.
+ * Then if |good| move |mlen| bytes from |em|+11 to |to|.
+ * Otherwise leave |to| unchanged.
+ * Copy the memory back in a way that does not reveal the size of
+ * the data being copied via a timing side channel. This requires copying
+ * parts of the buffer multiple times based on the bits set in the real
+ * length. Clear bits do a non-copy with identical access pattern.
+ * The loop below has overall complexity of O(N*log(N)).
*/
- tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen);
- msg_index = constant_time_select_int(good, msg_index, num - tlen);
- mlen = num - msg_index;
- for (from += msg_index, mask = good, i = 0; i < tlen; i++) {
- unsigned int equals = constant_time_eq(i, mlen);
-
- from -= tlen & equals; /* if (i == mlen) rewind */
- mask &= mask ^ equals; /* if (i == mlen) mask = 0 */
- to[i] = constant_time_select_8(mask, from[i], to[i]);
+ tlen = constant_time_select_int(constant_time_lt(num - 11, tlen),
+ num - 11, tlen);
+ for (msg_index = 1; msg_index < num - 11; msg_index <<= 1) {
+ mask = ~constant_time_eq(msg_index & (num - 11 - mlen), 0);
+ for (i = 11; i < num - msg_index; i++)
+ em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
+ }
+ for (i = 0; i < tlen; i++) {
+ mask = good & constant_time_lt(i, mlen);
+ to[i] = constant_time_select_8(mask, em[i + 11], to[i]);
}
OPENSSL_clear_free(em, num);
RSAerr(RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2, RSA_R_PKCS_DECODING_ERROR);
err_clear_last_constant_time(1 & good);
return constant_time_select_int(good, mlen, -1);
}
diff --git a/crypto/rsa/rsa_pmeth.c b/crypto/rsa/rsa_pmeth.c
index c10669f8a91b..082ab8fd8a1f 100644
--- a/crypto/rsa/rsa_pmeth.c
+++ b/crypto/rsa/rsa_pmeth.c
@@ -1,860 +1,861 @@
/*
- * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
+#include "internal/constant_time_locl.h"
+
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/x509.h>
#include <openssl/rsa.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509v3.h>
#include <openssl/cms.h>
#include "internal/evp_int.h"
#include "rsa_locl.h"
/* RSA pkey context structure */
typedef struct {
/* Key gen parameters */
int nbits;
BIGNUM *pub_exp;
int primes;
/* Keygen callback info */
int gentmp[2];
/* RSA padding mode */
int pad_mode;
/* message digest */
const EVP_MD *md;
/* message digest for MGF1 */
const EVP_MD *mgf1md;
/* PSS salt length */
int saltlen;
/* Minimum salt length or -1 if no PSS parameter restriction */
int min_saltlen;
/* Temp buffer */
unsigned char *tbuf;
/* OAEP label */
unsigned char *oaep_label;
size_t oaep_labellen;
} RSA_PKEY_CTX;
/* True if PSS parameters are restricted */
#define rsa_pss_restricted(rctx) (rctx->min_saltlen != -1)
static int pkey_rsa_init(EVP_PKEY_CTX *ctx)
{
RSA_PKEY_CTX *rctx = OPENSSL_zalloc(sizeof(*rctx));
if (rctx == NULL)
return 0;
- rctx->nbits = 1024;
+ rctx->nbits = 2048;
rctx->primes = RSA_DEFAULT_PRIME_NUM;
if (pkey_ctx_is_pss(ctx))
rctx->pad_mode = RSA_PKCS1_PSS_PADDING;
else
rctx->pad_mode = RSA_PKCS1_PADDING;
/* Maximum for sign, auto for verify */
rctx->saltlen = RSA_PSS_SALTLEN_AUTO;
rctx->min_saltlen = -1;
ctx->data = rctx;
ctx->keygen_info = rctx->gentmp;
ctx->keygen_info_count = 2;
return 1;
}
static int pkey_rsa_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
{
RSA_PKEY_CTX *dctx, *sctx;
if (!pkey_rsa_init(dst))
return 0;
sctx = src->data;
dctx = dst->data;
dctx->nbits = sctx->nbits;
if (sctx->pub_exp) {
dctx->pub_exp = BN_dup(sctx->pub_exp);
if (!dctx->pub_exp)
return 0;
}
dctx->pad_mode = sctx->pad_mode;
dctx->md = sctx->md;
dctx->mgf1md = sctx->mgf1md;
if (sctx->oaep_label) {
OPENSSL_free(dctx->oaep_label);
dctx->oaep_label = OPENSSL_memdup(sctx->oaep_label, sctx->oaep_labellen);
if (!dctx->oaep_label)
return 0;
dctx->oaep_labellen = sctx->oaep_labellen;
}
return 1;
}
static int setup_tbuf(RSA_PKEY_CTX *ctx, EVP_PKEY_CTX *pk)
{
if (ctx->tbuf != NULL)
return 1;
if ((ctx->tbuf = OPENSSL_malloc(EVP_PKEY_size(pk->pkey))) == NULL) {
RSAerr(RSA_F_SETUP_TBUF, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
static void pkey_rsa_cleanup(EVP_PKEY_CTX *ctx)
{
RSA_PKEY_CTX *rctx = ctx->data;
if (rctx) {
BN_free(rctx->pub_exp);
OPENSSL_free(rctx->tbuf);
OPENSSL_free(rctx->oaep_label);
OPENSSL_free(rctx);
}
}
static int pkey_rsa_sign(EVP_PKEY_CTX *ctx, unsigned char *sig,
size_t *siglen, const unsigned char *tbs,
size_t tbslen)
{
int ret;
RSA_PKEY_CTX *rctx = ctx->data;
RSA *rsa = ctx->pkey->pkey.rsa;
if (rctx->md) {
if (tbslen != (size_t)EVP_MD_size(rctx->md)) {
RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_INVALID_DIGEST_LENGTH);
return -1;
}
if (EVP_MD_type(rctx->md) == NID_mdc2) {
unsigned int sltmp;
if (rctx->pad_mode != RSA_PKCS1_PADDING)
return -1;
ret = RSA_sign_ASN1_OCTET_STRING(0,
tbs, tbslen, sig, &sltmp, rsa);
if (ret <= 0)
return ret;
ret = sltmp;
} else if (rctx->pad_mode == RSA_X931_PADDING) {
if ((size_t)EVP_PKEY_size(ctx->pkey) < tbslen + 1) {
RSAerr(RSA_F_PKEY_RSA_SIGN, RSA_R_KEY_SIZE_TOO_SMALL);
return -1;
}
if (!setup_tbuf(rctx, ctx)) {
RSAerr(RSA_F_PKEY_RSA_SIGN, ERR_R_MALLOC_FAILURE);
return -1;
}
memcpy(rctx->tbuf, tbs, tbslen);
rctx->tbuf[tbslen] = RSA_X931_hash_id(EVP_MD_type(rctx->md));
ret = RSA_private_encrypt(tbslen + 1, rctx->tbuf,
sig, rsa, RSA_X931_PADDING);
} else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
unsigned int sltmp;
ret = RSA_sign(EVP_MD_type(rctx->md),
tbs, tbslen, sig, &sltmp, rsa);
if (ret <= 0)
return ret;
ret = sltmp;
} else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
if (!setup_tbuf(rctx, ctx))
return -1;
if (!RSA_padding_add_PKCS1_PSS_mgf1(rsa,
rctx->tbuf, tbs,
rctx->md, rctx->mgf1md,
rctx->saltlen))
return -1;
ret = RSA_private_encrypt(RSA_size(rsa), rctx->tbuf,
sig, rsa, RSA_NO_PADDING);
} else {
return -1;
}
} else {
ret = RSA_private_encrypt(tbslen, tbs, sig, ctx->pkey->pkey.rsa,
rctx->pad_mode);
}
if (ret < 0)
return ret;
*siglen = ret;
return 1;
}
static int pkey_rsa_verifyrecover(EVP_PKEY_CTX *ctx,
unsigned char *rout, size_t *routlen,
const unsigned char *sig, size_t siglen)
{
int ret;
RSA_PKEY_CTX *rctx = ctx->data;
if (rctx->md) {
if (rctx->pad_mode == RSA_X931_PADDING) {
if (!setup_tbuf(rctx, ctx))
return -1;
ret = RSA_public_decrypt(siglen, sig,
rctx->tbuf, ctx->pkey->pkey.rsa,
RSA_X931_PADDING);
if (ret < 1)
return 0;
ret--;
if (rctx->tbuf[ret] != RSA_X931_hash_id(EVP_MD_type(rctx->md))) {
RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
RSA_R_ALGORITHM_MISMATCH);
return 0;
}
if (ret != EVP_MD_size(rctx->md)) {
RSAerr(RSA_F_PKEY_RSA_VERIFYRECOVER,
RSA_R_INVALID_DIGEST_LENGTH);
return 0;
}
if (rout)
memcpy(rout, rctx->tbuf, ret);
} else if (rctx->pad_mode == RSA_PKCS1_PADDING) {
size_t sltmp;
ret = int_rsa_verify(EVP_MD_type(rctx->md),
NULL, 0, rout, &sltmp,
sig, siglen, ctx->pkey->pkey.rsa);
if (ret <= 0)
return 0;
ret = sltmp;
} else {
return -1;
}
} else {
ret = RSA_public_decrypt(siglen, sig, rout, ctx->pkey->pkey.rsa,
rctx->pad_mode);
}
if (ret < 0)
return ret;
*routlen = ret;
return 1;
}
static int pkey_rsa_verify(EVP_PKEY_CTX *ctx,
const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen)
{
RSA_PKEY_CTX *rctx = ctx->data;
RSA *rsa = ctx->pkey->pkey.rsa;
size_t rslen;
if (rctx->md) {
if (rctx->pad_mode == RSA_PKCS1_PADDING)
return RSA_verify(EVP_MD_type(rctx->md), tbs, tbslen,
sig, siglen, rsa);
if (tbslen != (size_t)EVP_MD_size(rctx->md)) {
RSAerr(RSA_F_PKEY_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH);
return -1;
}
if (rctx->pad_mode == RSA_X931_PADDING) {
if (pkey_rsa_verifyrecover(ctx, NULL, &rslen, sig, siglen) <= 0)
return 0;
} else if (rctx->pad_mode == RSA_PKCS1_PSS_PADDING) {
int ret;
if (!setup_tbuf(rctx, ctx))
return -1;
ret = RSA_public_decrypt(siglen, sig, rctx->tbuf,
rsa, RSA_NO_PADDING);
if (ret <= 0)
return 0;
ret = RSA_verify_PKCS1_PSS_mgf1(rsa, tbs,
rctx->md, rctx->mgf1md,
rctx->tbuf, rctx->saltlen);
if (ret <= 0)
return 0;
return 1;
} else {
return -1;
}
} else {
if (!setup_tbuf(rctx, ctx))
return -1;
rslen = RSA_public_decrypt(siglen, sig, rctx->tbuf,
rsa, rctx->pad_mode);
if (rslen == 0)
return 0;
}
if ((rslen != tbslen) || memcmp(tbs, rctx->tbuf, rslen))
return 0;
return 1;
}
static int pkey_rsa_encrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen)
{
int ret;
RSA_PKEY_CTX *rctx = ctx->data;
if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
int klen = RSA_size(ctx->pkey->pkey.rsa);
if (!setup_tbuf(rctx, ctx))
return -1;
if (!RSA_padding_add_PKCS1_OAEP_mgf1(rctx->tbuf, klen,
in, inlen,
rctx->oaep_label,
rctx->oaep_labellen,
rctx->md, rctx->mgf1md))
return -1;
ret = RSA_public_encrypt(klen, rctx->tbuf, out,
ctx->pkey->pkey.rsa, RSA_NO_PADDING);
} else {
ret = RSA_public_encrypt(inlen, in, out, ctx->pkey->pkey.rsa,
rctx->pad_mode);
}
if (ret < 0)
return ret;
*outlen = ret;
return 1;
}
static int pkey_rsa_decrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen)
{
int ret;
RSA_PKEY_CTX *rctx = ctx->data;
if (rctx->pad_mode == RSA_PKCS1_OAEP_PADDING) {
if (!setup_tbuf(rctx, ctx))
return -1;
ret = RSA_private_decrypt(inlen, in, rctx->tbuf,
ctx->pkey->pkey.rsa, RSA_NO_PADDING);
if (ret <= 0)
return ret;
ret = RSA_padding_check_PKCS1_OAEP_mgf1(out, ret, rctx->tbuf,
ret, ret,
rctx->oaep_label,
rctx->oaep_labellen,
rctx->md, rctx->mgf1md);
} else {
ret = RSA_private_decrypt(inlen, in, out, ctx->pkey->pkey.rsa,
rctx->pad_mode);
}
- if (ret < 0)
- return ret;
- *outlen = ret;
- return 1;
+ *outlen = constant_time_select_s(constant_time_msb_s(ret), *outlen, ret);
+ ret = constant_time_select_int(constant_time_msb(ret), ret, 1);
+ return ret;
}
static int check_padding_md(const EVP_MD *md, int padding)
{
int mdnid;
if (!md)
return 1;
mdnid = EVP_MD_type(md);
if (padding == RSA_NO_PADDING) {
RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_PADDING_MODE);
return 0;
}
if (padding == RSA_X931_PADDING) {
if (RSA_X931_hash_id(mdnid) == -1) {
RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_X931_DIGEST);
return 0;
}
} else {
switch(mdnid) {
/* List of all supported RSA digests */
case NID_sha1:
case NID_sha224:
case NID_sha256:
case NID_sha384:
case NID_sha512:
case NID_md5:
case NID_md5_sha1:
case NID_md2:
case NID_md4:
case NID_mdc2:
case NID_ripemd160:
case NID_sha3_224:
case NID_sha3_256:
case NID_sha3_384:
case NID_sha3_512:
return 1;
default:
RSAerr(RSA_F_CHECK_PADDING_MD, RSA_R_INVALID_DIGEST);
return 0;
}
}
return 1;
}
static int pkey_rsa_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
{
RSA_PKEY_CTX *rctx = ctx->data;
switch (type) {
case EVP_PKEY_CTRL_RSA_PADDING:
if ((p1 >= RSA_PKCS1_PADDING) && (p1 <= RSA_PKCS1_PSS_PADDING)) {
if (!check_padding_md(rctx->md, p1))
return 0;
if (p1 == RSA_PKCS1_PSS_PADDING) {
if (!(ctx->operation &
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY)))
goto bad_pad;
if (!rctx->md)
rctx->md = EVP_sha1();
} else if (pkey_ctx_is_pss(ctx)) {
goto bad_pad;
}
if (p1 == RSA_PKCS1_OAEP_PADDING) {
if (!(ctx->operation & EVP_PKEY_OP_TYPE_CRYPT))
goto bad_pad;
if (!rctx->md)
rctx->md = EVP_sha1();
}
rctx->pad_mode = p1;
return 1;
}
bad_pad:
RSAerr(RSA_F_PKEY_RSA_CTRL,
RSA_R_ILLEGAL_OR_UNSUPPORTED_PADDING_MODE);
return -2;
case EVP_PKEY_CTRL_GET_RSA_PADDING:
*(int *)p2 = rctx->pad_mode;
return 1;
case EVP_PKEY_CTRL_RSA_PSS_SALTLEN:
case EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN:
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
return -2;
}
if (type == EVP_PKEY_CTRL_GET_RSA_PSS_SALTLEN) {
*(int *)p2 = rctx->saltlen;
} else {
if (p1 < RSA_PSS_SALTLEN_MAX)
return -2;
if (rsa_pss_restricted(rctx)) {
if (p1 == RSA_PSS_SALTLEN_AUTO
&& ctx->operation == EVP_PKEY_OP_VERIFY) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PSS_SALTLEN);
return -2;
}
if ((p1 == RSA_PSS_SALTLEN_DIGEST
&& rctx->min_saltlen > EVP_MD_size(rctx->md))
|| (p1 >= 0 && p1 < rctx->min_saltlen)) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_PSS_SALTLEN_TOO_SMALL);
return 0;
}
}
rctx->saltlen = p1;
}
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_BITS:
if (p1 < RSA_MIN_MODULUS_BITS) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_SIZE_TOO_SMALL);
return -2;
}
rctx->nbits = p1;
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_PUBEXP:
if (p2 == NULL || !BN_is_odd((BIGNUM *)p2) || BN_is_one((BIGNUM *)p2)) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_BAD_E_VALUE);
return -2;
}
BN_free(rctx->pub_exp);
rctx->pub_exp = p2;
return 1;
case EVP_PKEY_CTRL_RSA_KEYGEN_PRIMES:
if (p1 < RSA_DEFAULT_PRIME_NUM || p1 > RSA_MAX_PRIME_NUM) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_PRIME_NUM_INVALID);
return -2;
}
rctx->primes = p1;
return 1;
case EVP_PKEY_CTRL_RSA_OAEP_MD:
case EVP_PKEY_CTRL_GET_RSA_OAEP_MD:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
return -2;
}
if (type == EVP_PKEY_CTRL_GET_RSA_OAEP_MD)
*(const EVP_MD **)p2 = rctx->md;
else
rctx->md = p2;
return 1;
case EVP_PKEY_CTRL_MD:
if (!check_padding_md(p2, rctx->pad_mode))
return 0;
if (rsa_pss_restricted(rctx)) {
if (EVP_MD_type(rctx->md) == EVP_MD_type(p2))
return 1;
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_DIGEST_NOT_ALLOWED);
return 0;
}
rctx->md = p2;
return 1;
case EVP_PKEY_CTRL_GET_MD:
*(const EVP_MD **)p2 = rctx->md;
return 1;
case EVP_PKEY_CTRL_RSA_MGF1_MD:
case EVP_PKEY_CTRL_GET_RSA_MGF1_MD:
if (rctx->pad_mode != RSA_PKCS1_PSS_PADDING
&& rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_MGF1_MD);
return -2;
}
if (type == EVP_PKEY_CTRL_GET_RSA_MGF1_MD) {
if (rctx->mgf1md)
*(const EVP_MD **)p2 = rctx->mgf1md;
else
*(const EVP_MD **)p2 = rctx->md;
} else {
if (rsa_pss_restricted(rctx)) {
if (EVP_MD_type(rctx->mgf1md) == EVP_MD_type(p2))
return 1;
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_MGF1_DIGEST_NOT_ALLOWED);
return 0;
}
rctx->mgf1md = p2;
}
return 1;
case EVP_PKEY_CTRL_RSA_OAEP_LABEL:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
return -2;
}
OPENSSL_free(rctx->oaep_label);
if (p2 && p1 > 0) {
rctx->oaep_label = p2;
rctx->oaep_labellen = p1;
} else {
rctx->oaep_label = NULL;
rctx->oaep_labellen = 0;
}
return 1;
case EVP_PKEY_CTRL_GET_RSA_OAEP_LABEL:
if (rctx->pad_mode != RSA_PKCS1_OAEP_PADDING) {
RSAerr(RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_PADDING_MODE);
return -2;
}
*(unsigned char **)p2 = rctx->oaep_label;
return rctx->oaep_labellen;
case EVP_PKEY_CTRL_DIGESTINIT:
case EVP_PKEY_CTRL_PKCS7_SIGN:
#ifndef OPENSSL_NO_CMS
case EVP_PKEY_CTRL_CMS_SIGN:
#endif
return 1;
case EVP_PKEY_CTRL_PKCS7_ENCRYPT:
case EVP_PKEY_CTRL_PKCS7_DECRYPT:
#ifndef OPENSSL_NO_CMS
case EVP_PKEY_CTRL_CMS_DECRYPT:
case EVP_PKEY_CTRL_CMS_ENCRYPT:
#endif
if (!pkey_ctx_is_pss(ctx))
return 1;
/* fall through */
case EVP_PKEY_CTRL_PEER_KEY:
RSAerr(RSA_F_PKEY_RSA_CTRL,
RSA_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
default:
return -2;
}
}
static int pkey_rsa_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
{
if (value == NULL) {
RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_VALUE_MISSING);
return 0;
}
if (strcmp(type, "rsa_padding_mode") == 0) {
int pm;
if (strcmp(value, "pkcs1") == 0) {
pm = RSA_PKCS1_PADDING;
} else if (strcmp(value, "sslv23") == 0) {
pm = RSA_SSLV23_PADDING;
} else if (strcmp(value, "none") == 0) {
pm = RSA_NO_PADDING;
} else if (strcmp(value, "oeap") == 0) {
pm = RSA_PKCS1_OAEP_PADDING;
} else if (strcmp(value, "oaep") == 0) {
pm = RSA_PKCS1_OAEP_PADDING;
} else if (strcmp(value, "x931") == 0) {
pm = RSA_X931_PADDING;
} else if (strcmp(value, "pss") == 0) {
pm = RSA_PKCS1_PSS_PADDING;
} else {
RSAerr(RSA_F_PKEY_RSA_CTRL_STR, RSA_R_UNKNOWN_PADDING_TYPE);
return -2;
}
return EVP_PKEY_CTX_set_rsa_padding(ctx, pm);
}
if (strcmp(type, "rsa_pss_saltlen") == 0) {
int saltlen;
if (!strcmp(value, "digest"))
saltlen = RSA_PSS_SALTLEN_DIGEST;
else if (!strcmp(value, "max"))
saltlen = RSA_PSS_SALTLEN_MAX;
else if (!strcmp(value, "auto"))
saltlen = RSA_PSS_SALTLEN_AUTO;
else
saltlen = atoi(value);
return EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, saltlen);
}
if (strcmp(type, "rsa_keygen_bits") == 0) {
int nbits = atoi(value);
return EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, nbits);
}
if (strcmp(type, "rsa_keygen_pubexp") == 0) {
int ret;
BIGNUM *pubexp = NULL;
if (!BN_asc2bn(&pubexp, value))
return 0;
ret = EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, pubexp);
if (ret <= 0)
BN_free(pubexp);
return ret;
}
if (strcmp(type, "rsa_keygen_primes") == 0) {
int nprimes = atoi(value);
return EVP_PKEY_CTX_set_rsa_keygen_primes(ctx, nprimes);
}
if (strcmp(type, "rsa_mgf1_md") == 0)
return EVP_PKEY_CTX_md(ctx,
EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_RSA_MGF1_MD, value);
if (pkey_ctx_is_pss(ctx)) {
if (strcmp(type, "rsa_pss_keygen_mgf1_md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_RSA_MGF1_MD, value);
if (strcmp(type, "rsa_pss_keygen_md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_KEYGEN,
EVP_PKEY_CTRL_MD, value);
if (strcmp(type, "rsa_pss_keygen_saltlen") == 0) {
int saltlen = atoi(value);
return EVP_PKEY_CTX_set_rsa_pss_keygen_saltlen(ctx, saltlen);
}
}
if (strcmp(type, "rsa_oaep_md") == 0)
return EVP_PKEY_CTX_md(ctx, EVP_PKEY_OP_TYPE_CRYPT,
EVP_PKEY_CTRL_RSA_OAEP_MD, value);
if (strcmp(type, "rsa_oaep_label") == 0) {
unsigned char *lab;
long lablen;
int ret;
lab = OPENSSL_hexstr2buf(value, &lablen);
if (!lab)
return 0;
ret = EVP_PKEY_CTX_set0_rsa_oaep_label(ctx, lab, lablen);
if (ret <= 0)
OPENSSL_free(lab);
return ret;
}
return -2;
}
/* Set PSS parameters when generating a key, if necessary */
static int rsa_set_pss_param(RSA *rsa, EVP_PKEY_CTX *ctx)
{
RSA_PKEY_CTX *rctx = ctx->data;
if (!pkey_ctx_is_pss(ctx))
return 1;
/* If all parameters are default values don't set pss */
if (rctx->md == NULL && rctx->mgf1md == NULL && rctx->saltlen == -2)
return 1;
rsa->pss = rsa_pss_params_create(rctx->md, rctx->mgf1md,
rctx->saltlen == -2 ? 0 : rctx->saltlen);
if (rsa->pss == NULL)
return 0;
return 1;
}
static int pkey_rsa_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
RSA *rsa = NULL;
RSA_PKEY_CTX *rctx = ctx->data;
BN_GENCB *pcb;
int ret;
if (rctx->pub_exp == NULL) {
rctx->pub_exp = BN_new();
if (rctx->pub_exp == NULL || !BN_set_word(rctx->pub_exp, RSA_F4))
return 0;
}
rsa = RSA_new();
if (rsa == NULL)
return 0;
if (ctx->pkey_gencb) {
pcb = BN_GENCB_new();
if (pcb == NULL) {
RSA_free(rsa);
return 0;
}
evp_pkey_set_cb_translate(pcb, ctx);
} else {
pcb = NULL;
}
ret = RSA_generate_multi_prime_key(rsa, rctx->nbits, rctx->primes,
rctx->pub_exp, pcb);
BN_GENCB_free(pcb);
if (ret > 0 && !rsa_set_pss_param(rsa, ctx)) {
RSA_free(rsa);
return 0;
}
if (ret > 0)
EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, rsa);
else
RSA_free(rsa);
return ret;
}
const EVP_PKEY_METHOD rsa_pkey_meth = {
EVP_PKEY_RSA,
EVP_PKEY_FLAG_AUTOARGLEN,
pkey_rsa_init,
pkey_rsa_copy,
pkey_rsa_cleanup,
0, 0,
0,
pkey_rsa_keygen,
0,
pkey_rsa_sign,
0,
pkey_rsa_verify,
0,
pkey_rsa_verifyrecover,
0, 0, 0, 0,
0,
pkey_rsa_encrypt,
0,
pkey_rsa_decrypt,
0, 0,
pkey_rsa_ctrl,
pkey_rsa_ctrl_str
};
/*
* Called for PSS sign or verify initialisation: checks PSS parameter
* sanity and sets any restrictions on key usage.
*/
static int pkey_pss_init(EVP_PKEY_CTX *ctx)
{
RSA *rsa;
RSA_PKEY_CTX *rctx = ctx->data;
const EVP_MD *md;
const EVP_MD *mgf1md;
int min_saltlen, max_saltlen;
/* Should never happen */
if (!pkey_ctx_is_pss(ctx))
return 0;
rsa = ctx->pkey->pkey.rsa;
/* If no restrictions just return */
if (rsa->pss == NULL)
return 1;
/* Get and check parameters */
if (!rsa_pss_get_param(rsa->pss, &md, &mgf1md, &min_saltlen))
return 0;
/* See if minimum salt length exceeds maximum possible */
max_saltlen = RSA_size(rsa) - EVP_MD_size(md);
if ((RSA_bits(rsa) & 0x7) == 1)
max_saltlen--;
if (min_saltlen > max_saltlen) {
RSAerr(RSA_F_PKEY_PSS_INIT, RSA_R_INVALID_SALT_LENGTH);
return 0;
}
rctx->min_saltlen = min_saltlen;
/*
* Set PSS restrictions as defaults: we can then block any attempt to
* use invalid values in pkey_rsa_ctrl
*/
rctx->md = md;
rctx->mgf1md = mgf1md;
rctx->saltlen = min_saltlen;
return 1;
}
const EVP_PKEY_METHOD rsa_pss_pkey_meth = {
EVP_PKEY_RSA_PSS,
EVP_PKEY_FLAG_AUTOARGLEN,
pkey_rsa_init,
pkey_rsa_copy,
pkey_rsa_cleanup,
0, 0,
0,
pkey_rsa_keygen,
pkey_pss_init,
pkey_rsa_sign,
pkey_pss_init,
pkey_rsa_verify,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
pkey_rsa_ctrl,
pkey_rsa_ctrl_str
};
diff --git a/crypto/rsa/rsa_ssl.c b/crypto/rsa/rsa_ssl.c
index c5654595fb2f..3859128a6d80 100644
--- a/crypto/rsa/rsa_ssl.c
+++ b/crypto/rsa/rsa_ssl.c
@@ -1,167 +1,170 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/rand.h>
#include "internal/constant_time_locl.h"
int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
const unsigned char *from, int flen)
{
int i, j;
unsigned char *p;
if (flen > (tlen - 11)) {
RSAerr(RSA_F_RSA_PADDING_ADD_SSLV23,
RSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
return 0;
}
p = (unsigned char *)to;
*(p++) = 0;
*(p++) = 2; /* Public Key BT (Block Type) */
/* pad out with non-zero random data */
j = tlen - 3 - 8 - flen;
if (RAND_bytes(p, j) <= 0)
return 0;
for (i = 0; i < j; i++) {
if (*p == '\0')
do {
if (RAND_bytes(p, 1) <= 0)
return 0;
} while (*p == '\0');
p++;
}
memset(p, 3, 8);
p += 8;
*(p++) = '\0';
memcpy(p, from, (unsigned int)flen);
return 1;
}
/*
* Copy of RSA_padding_check_PKCS1_type_2 with a twist that rejects padding
- * if nul delimiter is preceded by 8 consecutive 0x03 bytes. It also
+ * if nul delimiter is not preceded by 8 consecutive 0x03 bytes. It also
* preserves error code reporting for backward compatibility.
*/
int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
const unsigned char *from, int flen, int num)
{
int i;
/* |em| is the encoded message, zero-padded to exactly |num| bytes */
unsigned char *em = NULL;
unsigned int good, found_zero_byte, mask, threes_in_row;
int zero_index = 0, msg_index, mlen = -1, err;
- if (flen < 10) {
+ if (tlen <= 0 || flen <= 0)
+ return -1;
+
+ if (flen > num || num < 11) {
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, RSA_R_DATA_TOO_SMALL);
return -1;
}
em = OPENSSL_malloc(num);
if (em == NULL) {
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, ERR_R_MALLOC_FAILURE);
return -1;
}
/*
* Caller is encouraged to pass zero-padded message created with
* BN_bn2binpad. Trouble is that since we can't read out of |from|'s
* bounds, it's impossible to have an invariant memory access pattern
* in case |from| was not zero-padded in advance.
*/
for (from += flen, em += num, i = 0; i < num; i++) {
mask = ~constant_time_is_zero(flen);
flen -= 1 & mask;
from -= 1 & mask;
*--em = *from & mask;
}
- from = em;
- good = constant_time_is_zero(from[0]);
- good &= constant_time_eq(from[1], 2);
+ good = constant_time_is_zero(em[0]);
+ good &= constant_time_eq(em[1], 2);
err = constant_time_select_int(good, 0, RSA_R_BLOCK_TYPE_IS_NOT_02);
mask = ~good;
/* scan over padding data */
found_zero_byte = 0;
threes_in_row = 0;
for (i = 2; i < num; i++) {
- unsigned int equals0 = constant_time_is_zero(from[i]);
+ unsigned int equals0 = constant_time_is_zero(em[i]);
zero_index = constant_time_select_int(~found_zero_byte & equals0,
i, zero_index);
found_zero_byte |= equals0;
threes_in_row += 1 & ~found_zero_byte;
- threes_in_row &= found_zero_byte | constant_time_eq(from[i], 3);
+ threes_in_row &= found_zero_byte | constant_time_eq(em[i], 3);
}
/*
- * PS must be at least 8 bytes long, and it starts two bytes into |from|.
+ * PS must be at least 8 bytes long, and it starts two bytes into |em|.
* If we never found a 0-byte, then |zero_index| is 0 and the check
* also fails.
*/
good &= constant_time_ge(zero_index, 2 + 8);
err = constant_time_select_int(mask | good, err,
RSA_R_NULL_BEFORE_BLOCK_MISSING);
mask = ~good;
- good &= constant_time_lt(threes_in_row, 8);
+ good &= constant_time_ge(threes_in_row, 8);
err = constant_time_select_int(mask | good, err,
RSA_R_SSLV3_ROLLBACK_ATTACK);
mask = ~good;
/*
* Skip the zero byte. This is incorrect if we never found a zero-byte
* but in this case we also do not copy the message out.
*/
msg_index = zero_index + 1;
mlen = num - msg_index;
/*
* For good measure, do this check in constant time as well.
*/
good &= constant_time_ge(tlen, mlen);
err = constant_time_select_int(mask | good, err, RSA_R_DATA_TOO_LARGE);
/*
- * Even though we can't fake result's length, we can pretend copying
- * |tlen| bytes where |mlen| bytes would be real. Last |tlen| of |num|
- * bytes are viewed as circular buffer with start at |tlen|-|mlen'|,
- * where |mlen'| is "saturated" |mlen| value. Deducing information
- * about failure or |mlen| would take attacker's ability to observe
- * memory access pattern with byte granularity *as it occurs*. It
- * should be noted that failure is indistinguishable from normal
- * operation if |tlen| is fixed by protocol.
+ * Move the result in-place by |num|-11-|mlen| bytes to the left.
+ * Then if |good| move |mlen| bytes from |em|+11 to |to|.
+ * Otherwise leave |to| unchanged.
+ * Copy the memory back in a way that does not reveal the size of
+ * the data being copied via a timing side channel. This requires copying
+ * parts of the buffer multiple times based on the bits set in the real
+ * length. Clear bits do a non-copy with identical access pattern.
+ * The loop below has overall complexity of O(N*log(N)).
*/
- tlen = constant_time_select_int(constant_time_lt(num, tlen), num, tlen);
- msg_index = constant_time_select_int(good, msg_index, num - tlen);
- mlen = num - msg_index;
- for (from += msg_index, mask = good, i = 0; i < tlen; i++) {
- unsigned int equals = constant_time_eq(i, mlen);
-
- from -= tlen & equals; /* if (i == mlen) rewind */
- mask &= mask ^ equals; /* if (i == mlen) mask = 0 */
- to[i] = constant_time_select_8(mask, from[i], to[i]);
+ tlen = constant_time_select_int(constant_time_lt(num - 11, tlen),
+ num - 11, tlen);
+ for (msg_index = 1; msg_index < num - 11; msg_index <<= 1) {
+ mask = ~constant_time_eq(msg_index & (num - 11 - mlen), 0);
+ for (i = 11; i < num - msg_index; i++)
+ em[i] = constant_time_select_8(mask, em[i + msg_index], em[i]);
+ }
+ for (i = 0; i < tlen; i++) {
+ mask = good & constant_time_lt(i, mlen);
+ to[i] = constant_time_select_8(mask, em[i + 11], to[i]);
}
OPENSSL_clear_free(em, num);
RSAerr(RSA_F_RSA_PADDING_CHECK_SSLV23, err);
err_clear_last_constant_time(1 & good);
return constant_time_select_int(good, mlen, -1);
}
diff --git a/crypto/rsa/rsa_x931g.c b/crypto/rsa/rsa_x931g.c
index 15e40e8d1dd7..e7ac476bb4a4 100644
--- a/crypto/rsa/rsa_x931g.c
+++ b/crypto/rsa/rsa_x931g.c
@@ -1,200 +1,198 @@
/*
- * Copyright 1995-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include "rsa_locl.h"
/* X9.31 RSA key derivation and generation */
int RSA_X931_derive_ex(RSA *rsa, BIGNUM *p1, BIGNUM *p2, BIGNUM *q1,
BIGNUM *q2, const BIGNUM *Xp1, const BIGNUM *Xp2,
const BIGNUM *Xp, const BIGNUM *Xq1, const BIGNUM *Xq2,
const BIGNUM *Xq, const BIGNUM *e, BN_GENCB *cb)
{
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL;
BN_CTX *ctx = NULL, *ctx2 = NULL;
int ret = 0;
if (!rsa)
goto err;
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
BN_CTX_start(ctx);
r0 = BN_CTX_get(ctx);
r1 = BN_CTX_get(ctx);
r2 = BN_CTX_get(ctx);
r3 = BN_CTX_get(ctx);
if (r3 == NULL)
goto err;
if (!rsa->e) {
rsa->e = BN_dup(e);
if (!rsa->e)
goto err;
} else {
e = rsa->e;
}
/*
* If not all parameters present only calculate what we can. This allows
* test programs to output selective parameters.
*/
if (Xp && rsa->p == NULL) {
rsa->p = BN_new();
if (rsa->p == NULL)
goto err;
if (!BN_X931_derive_prime_ex(rsa->p, p1, p2,
Xp, Xp1, Xp2, e, ctx, cb))
goto err;
}
if (Xq && rsa->q == NULL) {
rsa->q = BN_new();
if (rsa->q == NULL)
goto err;
if (!BN_X931_derive_prime_ex(rsa->q, q1, q2,
Xq, Xq1, Xq2, e, ctx, cb))
goto err;
}
if (rsa->p == NULL || rsa->q == NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return 2;
}
/*
* Since both primes are set we can now calculate all remaining
* components.
*/
/* calculate n */
rsa->n = BN_new();
if (rsa->n == NULL)
goto err;
if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx))
goto err;
/* calculate d */
if (!BN_sub(r1, rsa->p, BN_value_one()))
goto err; /* p-1 */
if (!BN_sub(r2, rsa->q, BN_value_one()))
goto err; /* q-1 */
if (!BN_mul(r0, r1, r2, ctx))
goto err; /* (p-1)(q-1) */
if (!BN_gcd(r3, r1, r2, ctx))
goto err;
if (!BN_div(r0, NULL, r0, r3, ctx))
goto err; /* LCM((p-1)(q-1)) */
ctx2 = BN_CTX_new();
if (ctx2 == NULL)
goto err;
rsa->d = BN_mod_inverse(NULL, rsa->e, r0, ctx2); /* d */
if (rsa->d == NULL)
goto err;
/* calculate d mod (p-1) */
rsa->dmp1 = BN_new();
if (rsa->dmp1 == NULL)
goto err;
if (!BN_mod(rsa->dmp1, rsa->d, r1, ctx))
goto err;
/* calculate d mod (q-1) */
rsa->dmq1 = BN_new();
if (rsa->dmq1 == NULL)
goto err;
if (!BN_mod(rsa->dmq1, rsa->d, r2, ctx))
goto err;
/* calculate inverse of q mod p */
rsa->iqmp = BN_mod_inverse(NULL, rsa->q, rsa->p, ctx2);
if (rsa->iqmp == NULL)
goto err;
ret = 1;
err:
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_CTX_free(ctx2);
return ret;
}
int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e,
BN_GENCB *cb)
{
int ok = 0;
BIGNUM *Xp = NULL, *Xq = NULL;
BN_CTX *ctx = NULL;
ctx = BN_CTX_new();
if (ctx == NULL)
goto error;
BN_CTX_start(ctx);
Xp = BN_CTX_get(ctx);
Xq = BN_CTX_get(ctx);
if (Xq == NULL)
goto error;
if (!BN_X931_generate_Xpq(Xp, Xq, bits, ctx))
goto error;
rsa->p = BN_new();
rsa->q = BN_new();
if (rsa->p == NULL || rsa->q == NULL)
goto error;
/* Generate two primes from Xp, Xq */
if (!BN_X931_generate_prime_ex(rsa->p, NULL, NULL, NULL, NULL, Xp,
e, ctx, cb))
goto error;
if (!BN_X931_generate_prime_ex(rsa->q, NULL, NULL, NULL, NULL, Xq,
e, ctx, cb))
goto error;
/*
* Since rsa->p and rsa->q are valid this call will just derive remaining
* RSA components.
*/
if (!RSA_X931_derive_ex(rsa, NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, NULL, e, cb))
goto error;
ok = 1;
error:
- if (ctx)
- BN_CTX_end(ctx);
+ BN_CTX_end(ctx);
BN_CTX_free(ctx);
if (ok)
return 1;
return 0;
}
diff --git a/crypto/sha/keccak1600.c b/crypto/sha/keccak1600.c
index e7223486af5b..55a44023d51a 100644
--- a/crypto/sha/keccak1600.c
+++ b/crypto/sha/keccak1600.c
@@ -1,1246 +1,1246 @@
/*
- * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/e_os2.h>
#include <string.h>
#include <assert.h>
size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
size_t r);
void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r);
#if !defined(KECCAK1600_ASM) || !defined(SELFTEST)
/*
* Choose some sensible defaults
*/
#if !defined(KECCAK_REF) && !defined(KECCAK_1X) && !defined(KECCAK_1X_ALT) && \
!defined(KECCAK_2X) && !defined(KECCAK_INPLACE)
# define KECCAK_2X /* default to KECCAK_2X variant */
#endif
#if defined(__i386) || defined(__i386__) || defined(_M_IX86)
# define KECCAK_COMPLEMENTING_TRANSFORM
#endif
#if defined(__x86_64__) || defined(__aarch64__) || \
defined(__mips64) || defined(__ia64) || \
(defined(__VMS) && !defined(__vax))
/*
* These are available even in ILP32 flavours, but even then they are
* capable of performing 64-bit operations as efficiently as in *P64.
* Since it's not given that we can use sizeof(void *), just shunt it.
*/
# define BIT_INTERLEAVE (0)
#else
# define BIT_INTERLEAVE (sizeof(void *) < 8)
#endif
#define ROL32(a, offset) (((a) << (offset)) | ((a) >> ((32 - (offset)) & 31)))
static uint64_t ROL64(uint64_t val, int offset)
{
if (offset == 0) {
return val;
} else if (!BIT_INTERLEAVE) {
return (val << offset) | (val >> (64-offset));
} else {
uint32_t hi = (uint32_t)(val >> 32), lo = (uint32_t)val;
if (offset & 1) {
uint32_t tmp = hi;
offset >>= 1;
hi = ROL32(lo, offset);
lo = ROL32(tmp, offset + 1);
} else {
offset >>= 1;
lo = ROL32(lo, offset);
hi = ROL32(hi, offset);
}
return ((uint64_t)hi << 32) | lo;
}
}
static const unsigned char rhotates[5][5] = {
{ 0, 1, 62, 28, 27 },
{ 36, 44, 6, 55, 20 },
{ 3, 10, 43, 25, 39 },
{ 41, 45, 15, 21, 8 },
{ 18, 2, 61, 56, 14 }
};
static const uint64_t iotas[] = {
- BIT_INTERLEAVE ? 0x0000000000000001U : 0x0000000000000001U,
- BIT_INTERLEAVE ? 0x0000008900000000U : 0x0000000000008082U,
- BIT_INTERLEAVE ? 0x8000008b00000000U : 0x800000000000808aU,
- BIT_INTERLEAVE ? 0x8000808000000000U : 0x8000000080008000U,
- BIT_INTERLEAVE ? 0x0000008b00000001U : 0x000000000000808bU,
- BIT_INTERLEAVE ? 0x0000800000000001U : 0x0000000080000001U,
- BIT_INTERLEAVE ? 0x8000808800000001U : 0x8000000080008081U,
- BIT_INTERLEAVE ? 0x8000008200000001U : 0x8000000000008009U,
- BIT_INTERLEAVE ? 0x0000000b00000000U : 0x000000000000008aU,
- BIT_INTERLEAVE ? 0x0000000a00000000U : 0x0000000000000088U,
- BIT_INTERLEAVE ? 0x0000808200000001U : 0x0000000080008009U,
- BIT_INTERLEAVE ? 0x0000800300000000U : 0x000000008000000aU,
- BIT_INTERLEAVE ? 0x0000808b00000001U : 0x000000008000808bU,
- BIT_INTERLEAVE ? 0x8000000b00000001U : 0x800000000000008bU,
- BIT_INTERLEAVE ? 0x8000008a00000001U : 0x8000000000008089U,
- BIT_INTERLEAVE ? 0x8000008100000001U : 0x8000000000008003U,
- BIT_INTERLEAVE ? 0x8000008100000000U : 0x8000000000008002U,
- BIT_INTERLEAVE ? 0x8000000800000000U : 0x8000000000000080U,
- BIT_INTERLEAVE ? 0x0000008300000000U : 0x000000000000800aU,
- BIT_INTERLEAVE ? 0x8000800300000000U : 0x800000008000000aU,
- BIT_INTERLEAVE ? 0x8000808800000001U : 0x8000000080008081U,
- BIT_INTERLEAVE ? 0x8000008800000000U : 0x8000000000008080U,
- BIT_INTERLEAVE ? 0x0000800000000001U : 0x0000000080000001U,
- BIT_INTERLEAVE ? 0x8000808200000000U : 0x8000000080008008U
+ BIT_INTERLEAVE ? 0x0000000000000001ULL : 0x0000000000000001ULL,
+ BIT_INTERLEAVE ? 0x0000008900000000ULL : 0x0000000000008082ULL,
+ BIT_INTERLEAVE ? 0x8000008b00000000ULL : 0x800000000000808aULL,
+ BIT_INTERLEAVE ? 0x8000808000000000ULL : 0x8000000080008000ULL,
+ BIT_INTERLEAVE ? 0x0000008b00000001ULL : 0x000000000000808bULL,
+ BIT_INTERLEAVE ? 0x0000800000000001ULL : 0x0000000080000001ULL,
+ BIT_INTERLEAVE ? 0x8000808800000001ULL : 0x8000000080008081ULL,
+ BIT_INTERLEAVE ? 0x8000008200000001ULL : 0x8000000000008009ULL,
+ BIT_INTERLEAVE ? 0x0000000b00000000ULL : 0x000000000000008aULL,
+ BIT_INTERLEAVE ? 0x0000000a00000000ULL : 0x0000000000000088ULL,
+ BIT_INTERLEAVE ? 0x0000808200000001ULL : 0x0000000080008009ULL,
+ BIT_INTERLEAVE ? 0x0000800300000000ULL : 0x000000008000000aULL,
+ BIT_INTERLEAVE ? 0x0000808b00000001ULL : 0x000000008000808bULL,
+ BIT_INTERLEAVE ? 0x8000000b00000001ULL : 0x800000000000008bULL,
+ BIT_INTERLEAVE ? 0x8000008a00000001ULL : 0x8000000000008089ULL,
+ BIT_INTERLEAVE ? 0x8000008100000001ULL : 0x8000000000008003ULL,
+ BIT_INTERLEAVE ? 0x8000008100000000ULL : 0x8000000000008002ULL,
+ BIT_INTERLEAVE ? 0x8000000800000000ULL : 0x8000000000000080ULL,
+ BIT_INTERLEAVE ? 0x0000008300000000ULL : 0x000000000000800aULL,
+ BIT_INTERLEAVE ? 0x8000800300000000ULL : 0x800000008000000aULL,
+ BIT_INTERLEAVE ? 0x8000808800000001ULL : 0x8000000080008081ULL,
+ BIT_INTERLEAVE ? 0x8000008800000000ULL : 0x8000000000008080ULL,
+ BIT_INTERLEAVE ? 0x0000800000000001ULL : 0x0000000080000001ULL,
+ BIT_INTERLEAVE ? 0x8000808200000000ULL : 0x8000000080008008ULL
};
#if defined(KECCAK_REF)
/*
* This is straightforward or "maximum clarity" implementation aiming
* to resemble section 3.2 of the FIPS PUB 202 "SHA-3 Standard:
* Permutation-Based Hash and Extendible-Output Functions" as much as
* possible. With one caveat. Because of the way C stores matrices,
* references to A[x,y] in the specification are presented as A[y][x].
* Implementation unrolls inner x-loops so that modulo 5 operations are
* explicitly pre-computed.
*/
static void Theta(uint64_t A[5][5])
{
uint64_t C[5], D[5];
size_t y;
C[0] = A[0][0];
C[1] = A[0][1];
C[2] = A[0][2];
C[3] = A[0][3];
C[4] = A[0][4];
for (y = 1; y < 5; y++) {
C[0] ^= A[y][0];
C[1] ^= A[y][1];
C[2] ^= A[y][2];
C[3] ^= A[y][3];
C[4] ^= A[y][4];
}
D[0] = ROL64(C[1], 1) ^ C[4];
D[1] = ROL64(C[2], 1) ^ C[0];
D[2] = ROL64(C[3], 1) ^ C[1];
D[3] = ROL64(C[4], 1) ^ C[2];
D[4] = ROL64(C[0], 1) ^ C[3];
for (y = 0; y < 5; y++) {
A[y][0] ^= D[0];
A[y][1] ^= D[1];
A[y][2] ^= D[2];
A[y][3] ^= D[3];
A[y][4] ^= D[4];
}
}
static void Rho(uint64_t A[5][5])
{
size_t y;
for (y = 0; y < 5; y++) {
A[y][0] = ROL64(A[y][0], rhotates[y][0]);
A[y][1] = ROL64(A[y][1], rhotates[y][1]);
A[y][2] = ROL64(A[y][2], rhotates[y][2]);
A[y][3] = ROL64(A[y][3], rhotates[y][3]);
A[y][4] = ROL64(A[y][4], rhotates[y][4]);
}
}
static void Pi(uint64_t A[5][5])
{
uint64_t T[5][5];
/*
* T = A
* A[y][x] = T[x][(3*y+x)%5]
*/
memcpy(T, A, sizeof(T));
A[0][0] = T[0][0];
A[0][1] = T[1][1];
A[0][2] = T[2][2];
A[0][3] = T[3][3];
A[0][4] = T[4][4];
A[1][0] = T[0][3];
A[1][1] = T[1][4];
A[1][2] = T[2][0];
A[1][3] = T[3][1];
A[1][4] = T[4][2];
A[2][0] = T[0][1];
A[2][1] = T[1][2];
A[2][2] = T[2][3];
A[2][3] = T[3][4];
A[2][4] = T[4][0];
A[3][0] = T[0][4];
A[3][1] = T[1][0];
A[3][2] = T[2][1];
A[3][3] = T[3][2];
A[3][4] = T[4][3];
A[4][0] = T[0][2];
A[4][1] = T[1][3];
A[4][2] = T[2][4];
A[4][3] = T[3][0];
A[4][4] = T[4][1];
}
static void Chi(uint64_t A[5][5])
{
uint64_t C[5];
size_t y;
for (y = 0; y < 5; y++) {
C[0] = A[y][0] ^ (~A[y][1] & A[y][2]);
C[1] = A[y][1] ^ (~A[y][2] & A[y][3]);
C[2] = A[y][2] ^ (~A[y][3] & A[y][4]);
C[3] = A[y][3] ^ (~A[y][4] & A[y][0]);
C[4] = A[y][4] ^ (~A[y][0] & A[y][1]);
A[y][0] = C[0];
A[y][1] = C[1];
A[y][2] = C[2];
A[y][3] = C[3];
A[y][4] = C[4];
}
}
static void Iota(uint64_t A[5][5], size_t i)
{
assert(i < (sizeof(iotas) / sizeof(iotas[0])));
A[0][0] ^= iotas[i];
}
static void KeccakF1600(uint64_t A[5][5])
{
size_t i;
for (i = 0; i < 24; i++) {
Theta(A);
Rho(A);
Pi(A);
Chi(A);
Iota(A, i);
}
}
#elif defined(KECCAK_1X)
/*
* This implementation is optimization of above code featuring unroll
* of even y-loops, their fusion and code motion. It also minimizes
* temporary storage. Compiler would normally do all these things for
* you, purpose of manual optimization is to provide "unobscured"
* reference for assembly implementation [in case this approach is
* chosen for implementation on some platform]. In the nutshell it's
* equivalent of "plane-per-plane processing" approach discussed in
* section 2.4 of "Keccak implementation overview".
*/
static void Round(uint64_t A[5][5], size_t i)
{
uint64_t C[5], E[2]; /* registers */
uint64_t D[5], T[2][5]; /* memory */
assert(i < (sizeof(iotas) / sizeof(iotas[0])));
C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0];
C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1];
C[2] = A[0][2] ^ A[1][2] ^ A[2][2] ^ A[3][2] ^ A[4][2];
C[3] = A[0][3] ^ A[1][3] ^ A[2][3] ^ A[3][3] ^ A[4][3];
C[4] = A[0][4] ^ A[1][4] ^ A[2][4] ^ A[3][4] ^ A[4][4];
#if defined(__arm__)
D[1] = E[0] = ROL64(C[2], 1) ^ C[0];
D[4] = E[1] = ROL64(C[0], 1) ^ C[3];
D[0] = C[0] = ROL64(C[1], 1) ^ C[4];
D[2] = C[1] = ROL64(C[3], 1) ^ C[1];
D[3] = C[2] = ROL64(C[4], 1) ^ C[2];
T[0][0] = A[3][0] ^ C[0]; /* borrow T[0][0] */
T[0][1] = A[0][1] ^ E[0]; /* D[1] */
T[0][2] = A[0][2] ^ C[1]; /* D[2] */
T[0][3] = A[0][3] ^ C[2]; /* D[3] */
T[0][4] = A[0][4] ^ E[1]; /* D[4] */
C[3] = ROL64(A[3][3] ^ C[2], rhotates[3][3]); /* D[3] */
C[4] = ROL64(A[4][4] ^ E[1], rhotates[4][4]); /* D[4] */
C[0] = A[0][0] ^ C[0]; /* rotate by 0 */ /* D[0] */
C[2] = ROL64(A[2][2] ^ C[1], rhotates[2][2]); /* D[2] */
C[1] = ROL64(A[1][1] ^ E[0], rhotates[1][1]); /* D[1] */
#else
D[0] = ROL64(C[1], 1) ^ C[4];
D[1] = ROL64(C[2], 1) ^ C[0];
D[2] = ROL64(C[3], 1) ^ C[1];
D[3] = ROL64(C[4], 1) ^ C[2];
D[4] = ROL64(C[0], 1) ^ C[3];
T[0][0] = A[3][0] ^ D[0]; /* borrow T[0][0] */
T[0][1] = A[0][1] ^ D[1];
T[0][2] = A[0][2] ^ D[2];
T[0][3] = A[0][3] ^ D[3];
T[0][4] = A[0][4] ^ D[4];
C[0] = A[0][0] ^ D[0]; /* rotate by 0 */
C[1] = ROL64(A[1][1] ^ D[1], rhotates[1][1]);
C[2] = ROL64(A[2][2] ^ D[2], rhotates[2][2]);
C[3] = ROL64(A[3][3] ^ D[3], rhotates[3][3]);
C[4] = ROL64(A[4][4] ^ D[4], rhotates[4][4]);
#endif
A[0][0] = C[0] ^ (~C[1] & C[2]) ^ iotas[i];
A[0][1] = C[1] ^ (~C[2] & C[3]);
A[0][2] = C[2] ^ (~C[3] & C[4]);
A[0][3] = C[3] ^ (~C[4] & C[0]);
A[0][4] = C[4] ^ (~C[0] & C[1]);
T[1][0] = A[1][0] ^ (C[3] = D[0]);
T[1][1] = A[2][1] ^ (C[4] = D[1]); /* borrow T[1][1] */
T[1][2] = A[1][2] ^ (E[0] = D[2]);
T[1][3] = A[1][3] ^ (E[1] = D[3]);
T[1][4] = A[2][4] ^ (C[2] = D[4]); /* borrow T[1][4] */
C[0] = ROL64(T[0][3], rhotates[0][3]);
C[1] = ROL64(A[1][4] ^ C[2], rhotates[1][4]); /* D[4] */
C[2] = ROL64(A[2][0] ^ C[3], rhotates[2][0]); /* D[0] */
C[3] = ROL64(A[3][1] ^ C[4], rhotates[3][1]); /* D[1] */
C[4] = ROL64(A[4][2] ^ E[0], rhotates[4][2]); /* D[2] */
A[1][0] = C[0] ^ (~C[1] & C[2]);
A[1][1] = C[1] ^ (~C[2] & C[3]);
A[1][2] = C[2] ^ (~C[3] & C[4]);
A[1][3] = C[3] ^ (~C[4] & C[0]);
A[1][4] = C[4] ^ (~C[0] & C[1]);
C[0] = ROL64(T[0][1], rhotates[0][1]);
C[1] = ROL64(T[1][2], rhotates[1][2]);
C[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]);
C[3] = ROL64(A[3][4] ^ D[4], rhotates[3][4]);
C[4] = ROL64(A[4][0] ^ D[0], rhotates[4][0]);
A[2][0] = C[0] ^ (~C[1] & C[2]);
A[2][1] = C[1] ^ (~C[2] & C[3]);
A[2][2] = C[2] ^ (~C[3] & C[4]);
A[2][3] = C[3] ^ (~C[4] & C[0]);
A[2][4] = C[4] ^ (~C[0] & C[1]);
C[0] = ROL64(T[0][4], rhotates[0][4]);
C[1] = ROL64(T[1][0], rhotates[1][0]);
C[2] = ROL64(T[1][1], rhotates[2][1]); /* originally A[2][1] */
C[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]);
C[4] = ROL64(A[4][3] ^ D[3], rhotates[4][3]);
A[3][0] = C[0] ^ (~C[1] & C[2]);
A[3][1] = C[1] ^ (~C[2] & C[3]);
A[3][2] = C[2] ^ (~C[3] & C[4]);
A[3][3] = C[3] ^ (~C[4] & C[0]);
A[3][4] = C[4] ^ (~C[0] & C[1]);
C[0] = ROL64(T[0][2], rhotates[0][2]);
C[1] = ROL64(T[1][3], rhotates[1][3]);
C[2] = ROL64(T[1][4], rhotates[2][4]); /* originally A[2][4] */
C[3] = ROL64(T[0][0], rhotates[3][0]); /* originally A[3][0] */
C[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]);
A[4][0] = C[0] ^ (~C[1] & C[2]);
A[4][1] = C[1] ^ (~C[2] & C[3]);
A[4][2] = C[2] ^ (~C[3] & C[4]);
A[4][3] = C[3] ^ (~C[4] & C[0]);
A[4][4] = C[4] ^ (~C[0] & C[1]);
}
static void KeccakF1600(uint64_t A[5][5])
{
size_t i;
for (i = 0; i < 24; i++) {
Round(A, i);
}
}
#elif defined(KECCAK_1X_ALT)
/*
* This is variant of above KECCAK_1X that reduces requirement for
* temporary storage even further, but at cost of more updates to A[][].
* It's less suitable if A[][] is memory bound, but better if it's
* register bound.
*/
static void Round(uint64_t A[5][5], size_t i)
{
uint64_t C[5], D[5];
assert(i < (sizeof(iotas) / sizeof(iotas[0])));
C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0];
C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1];
C[2] = A[0][2] ^ A[1][2] ^ A[2][2] ^ A[3][2] ^ A[4][2];
C[3] = A[0][3] ^ A[1][3] ^ A[2][3] ^ A[3][3] ^ A[4][3];
C[4] = A[0][4] ^ A[1][4] ^ A[2][4] ^ A[3][4] ^ A[4][4];
D[1] = C[0] ^ ROL64(C[2], 1);
D[2] = C[1] ^ ROL64(C[3], 1);
D[3] = C[2] ^= ROL64(C[4], 1);
D[4] = C[3] ^= ROL64(C[0], 1);
D[0] = C[4] ^= ROL64(C[1], 1);
A[0][1] ^= D[1];
A[1][1] ^= D[1];
A[2][1] ^= D[1];
A[3][1] ^= D[1];
A[4][1] ^= D[1];
A[0][2] ^= D[2];
A[1][2] ^= D[2];
A[2][2] ^= D[2];
A[3][2] ^= D[2];
A[4][2] ^= D[2];
A[0][3] ^= C[2];
A[1][3] ^= C[2];
A[2][3] ^= C[2];
A[3][3] ^= C[2];
A[4][3] ^= C[2];
A[0][4] ^= C[3];
A[1][4] ^= C[3];
A[2][4] ^= C[3];
A[3][4] ^= C[3];
A[4][4] ^= C[3];
A[0][0] ^= C[4];
A[1][0] ^= C[4];
A[2][0] ^= C[4];
A[3][0] ^= C[4];
A[4][0] ^= C[4];
C[1] = A[0][1];
C[2] = A[0][2];
C[3] = A[0][3];
C[4] = A[0][4];
A[0][1] = ROL64(A[1][1], rhotates[1][1]);
A[0][2] = ROL64(A[2][2], rhotates[2][2]);
A[0][3] = ROL64(A[3][3], rhotates[3][3]);
A[0][4] = ROL64(A[4][4], rhotates[4][4]);
A[1][1] = ROL64(A[1][4], rhotates[1][4]);
A[2][2] = ROL64(A[2][3], rhotates[2][3]);
A[3][3] = ROL64(A[3][2], rhotates[3][2]);
A[4][4] = ROL64(A[4][1], rhotates[4][1]);
A[1][4] = ROL64(A[4][2], rhotates[4][2]);
A[2][3] = ROL64(A[3][4], rhotates[3][4]);
A[3][2] = ROL64(A[2][1], rhotates[2][1]);
A[4][1] = ROL64(A[1][3], rhotates[1][3]);
A[4][2] = ROL64(A[2][4], rhotates[2][4]);
A[3][4] = ROL64(A[4][3], rhotates[4][3]);
A[2][1] = ROL64(A[1][2], rhotates[1][2]);
A[1][3] = ROL64(A[3][1], rhotates[3][1]);
A[2][4] = ROL64(A[4][0], rhotates[4][0]);
A[4][3] = ROL64(A[3][0], rhotates[3][0]);
A[1][2] = ROL64(A[2][0], rhotates[2][0]);
A[3][1] = ROL64(A[1][0], rhotates[1][0]);
A[1][0] = ROL64(C[3], rhotates[0][3]);
A[2][0] = ROL64(C[1], rhotates[0][1]);
A[3][0] = ROL64(C[4], rhotates[0][4]);
A[4][0] = ROL64(C[2], rhotates[0][2]);
C[0] = A[0][0];
C[1] = A[1][0];
D[0] = A[0][1];
D[1] = A[1][1];
A[0][0] ^= (~A[0][1] & A[0][2]);
A[1][0] ^= (~A[1][1] & A[1][2]);
A[0][1] ^= (~A[0][2] & A[0][3]);
A[1][1] ^= (~A[1][2] & A[1][3]);
A[0][2] ^= (~A[0][3] & A[0][4]);
A[1][2] ^= (~A[1][3] & A[1][4]);
A[0][3] ^= (~A[0][4] & C[0]);
A[1][3] ^= (~A[1][4] & C[1]);
A[0][4] ^= (~C[0] & D[0]);
A[1][4] ^= (~C[1] & D[1]);
C[2] = A[2][0];
C[3] = A[3][0];
D[2] = A[2][1];
D[3] = A[3][1];
A[2][0] ^= (~A[2][1] & A[2][2]);
A[3][0] ^= (~A[3][1] & A[3][2]);
A[2][1] ^= (~A[2][2] & A[2][3]);
A[3][1] ^= (~A[3][2] & A[3][3]);
A[2][2] ^= (~A[2][3] & A[2][4]);
A[3][2] ^= (~A[3][3] & A[3][4]);
A[2][3] ^= (~A[2][4] & C[2]);
A[3][3] ^= (~A[3][4] & C[3]);
A[2][4] ^= (~C[2] & D[2]);
A[3][4] ^= (~C[3] & D[3]);
C[4] = A[4][0];
D[4] = A[4][1];
A[4][0] ^= (~A[4][1] & A[4][2]);
A[4][1] ^= (~A[4][2] & A[4][3]);
A[4][2] ^= (~A[4][3] & A[4][4]);
A[4][3] ^= (~A[4][4] & C[4]);
A[4][4] ^= (~C[4] & D[4]);
A[0][0] ^= iotas[i];
}
static void KeccakF1600(uint64_t A[5][5])
{
size_t i;
for (i = 0; i < 24; i++) {
Round(A, i);
}
}
#elif defined(KECCAK_2X)
/*
* This implementation is variant of KECCAK_1X above with outer-most
* round loop unrolled twice. This allows to take temporary storage
* out of round procedure and simplify references to it by alternating
* it with actual data (see round loop below). Originally it was meant
* rather as reference for an assembly implementation, but it seems to
* play best with compilers [as well as provide best instruction per
* processed byte ratio at minimal round unroll factor]...
*/
static void Round(uint64_t R[5][5], uint64_t A[5][5], size_t i)
{
uint64_t C[5], D[5];
assert(i < (sizeof(iotas) / sizeof(iotas[0])));
C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0];
C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1];
C[2] = A[0][2] ^ A[1][2] ^ A[2][2] ^ A[3][2] ^ A[4][2];
C[3] = A[0][3] ^ A[1][3] ^ A[2][3] ^ A[3][3] ^ A[4][3];
C[4] = A[0][4] ^ A[1][4] ^ A[2][4] ^ A[3][4] ^ A[4][4];
D[0] = ROL64(C[1], 1) ^ C[4];
D[1] = ROL64(C[2], 1) ^ C[0];
D[2] = ROL64(C[3], 1) ^ C[1];
D[3] = ROL64(C[4], 1) ^ C[2];
D[4] = ROL64(C[0], 1) ^ C[3];
C[0] = A[0][0] ^ D[0]; /* rotate by 0 */
C[1] = ROL64(A[1][1] ^ D[1], rhotates[1][1]);
C[2] = ROL64(A[2][2] ^ D[2], rhotates[2][2]);
C[3] = ROL64(A[3][3] ^ D[3], rhotates[3][3]);
C[4] = ROL64(A[4][4] ^ D[4], rhotates[4][4]);
#ifdef KECCAK_COMPLEMENTING_TRANSFORM
R[0][0] = C[0] ^ ( C[1] | C[2]) ^ iotas[i];
R[0][1] = C[1] ^ (~C[2] | C[3]);
R[0][2] = C[2] ^ ( C[3] & C[4]);
R[0][3] = C[3] ^ ( C[4] | C[0]);
R[0][4] = C[4] ^ ( C[0] & C[1]);
#else
R[0][0] = C[0] ^ (~C[1] & C[2]) ^ iotas[i];
R[0][1] = C[1] ^ (~C[2] & C[3]);
R[0][2] = C[2] ^ (~C[3] & C[4]);
R[0][3] = C[3] ^ (~C[4] & C[0]);
R[0][4] = C[4] ^ (~C[0] & C[1]);
#endif
C[0] = ROL64(A[0][3] ^ D[3], rhotates[0][3]);
C[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]);
C[2] = ROL64(A[2][0] ^ D[0], rhotates[2][0]);
C[3] = ROL64(A[3][1] ^ D[1], rhotates[3][1]);
C[4] = ROL64(A[4][2] ^ D[2], rhotates[4][2]);
#ifdef KECCAK_COMPLEMENTING_TRANSFORM
R[1][0] = C[0] ^ (C[1] | C[2]);
R[1][1] = C[1] ^ (C[2] & C[3]);
R[1][2] = C[2] ^ (C[3] | ~C[4]);
R[1][3] = C[3] ^ (C[4] | C[0]);
R[1][4] = C[4] ^ (C[0] & C[1]);
#else
R[1][0] = C[0] ^ (~C[1] & C[2]);
R[1][1] = C[1] ^ (~C[2] & C[3]);
R[1][2] = C[2] ^ (~C[3] & C[4]);
R[1][3] = C[3] ^ (~C[4] & C[0]);
R[1][4] = C[4] ^ (~C[0] & C[1]);
#endif
C[0] = ROL64(A[0][1] ^ D[1], rhotates[0][1]);
C[1] = ROL64(A[1][2] ^ D[2], rhotates[1][2]);
C[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]);
C[3] = ROL64(A[3][4] ^ D[4], rhotates[3][4]);
C[4] = ROL64(A[4][0] ^ D[0], rhotates[4][0]);
#ifdef KECCAK_COMPLEMENTING_TRANSFORM
R[2][0] = C[0] ^ ( C[1] | C[2]);
R[2][1] = C[1] ^ ( C[2] & C[3]);
R[2][2] = C[2] ^ (~C[3] & C[4]);
R[2][3] = ~C[3] ^ ( C[4] | C[0]);
R[2][4] = C[4] ^ ( C[0] & C[1]);
#else
R[2][0] = C[0] ^ (~C[1] & C[2]);
R[2][1] = C[1] ^ (~C[2] & C[3]);
R[2][2] = C[2] ^ (~C[3] & C[4]);
R[2][3] = C[3] ^ (~C[4] & C[0]);
R[2][4] = C[4] ^ (~C[0] & C[1]);
#endif
C[0] = ROL64(A[0][4] ^ D[4], rhotates[0][4]);
C[1] = ROL64(A[1][0] ^ D[0], rhotates[1][0]);
C[2] = ROL64(A[2][1] ^ D[1], rhotates[2][1]);
C[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]);
C[4] = ROL64(A[4][3] ^ D[3], rhotates[4][3]);
#ifdef KECCAK_COMPLEMENTING_TRANSFORM
R[3][0] = C[0] ^ ( C[1] & C[2]);
R[3][1] = C[1] ^ ( C[2] | C[3]);
R[3][2] = C[2] ^ (~C[3] | C[4]);
R[3][3] = ~C[3] ^ ( C[4] & C[0]);
R[3][4] = C[4] ^ ( C[0] | C[1]);
#else
R[3][0] = C[0] ^ (~C[1] & C[2]);
R[3][1] = C[1] ^ (~C[2] & C[3]);
R[3][2] = C[2] ^ (~C[3] & C[4]);
R[3][3] = C[3] ^ (~C[4] & C[0]);
R[3][4] = C[4] ^ (~C[0] & C[1]);
#endif
C[0] = ROL64(A[0][2] ^ D[2], rhotates[0][2]);
C[1] = ROL64(A[1][3] ^ D[3], rhotates[1][3]);
C[2] = ROL64(A[2][4] ^ D[4], rhotates[2][4]);
C[3] = ROL64(A[3][0] ^ D[0], rhotates[3][0]);
C[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]);
#ifdef KECCAK_COMPLEMENTING_TRANSFORM
R[4][0] = C[0] ^ (~C[1] & C[2]);
R[4][1] = ~C[1] ^ ( C[2] | C[3]);
R[4][2] = C[2] ^ ( C[3] & C[4]);
R[4][3] = C[3] ^ ( C[4] | C[0]);
R[4][4] = C[4] ^ ( C[0] & C[1]);
#else
R[4][0] = C[0] ^ (~C[1] & C[2]);
R[4][1] = C[1] ^ (~C[2] & C[3]);
R[4][2] = C[2] ^ (~C[3] & C[4]);
R[4][3] = C[3] ^ (~C[4] & C[0]);
R[4][4] = C[4] ^ (~C[0] & C[1]);
#endif
}
static void KeccakF1600(uint64_t A[5][5])
{
uint64_t T[5][5];
size_t i;
#ifdef KECCAK_COMPLEMENTING_TRANSFORM
A[0][1] = ~A[0][1];
A[0][2] = ~A[0][2];
A[1][3] = ~A[1][3];
A[2][2] = ~A[2][2];
A[3][2] = ~A[3][2];
A[4][0] = ~A[4][0];
#endif
for (i = 0; i < 24; i += 2) {
Round(T, A, i);
Round(A, T, i + 1);
}
#ifdef KECCAK_COMPLEMENTING_TRANSFORM
A[0][1] = ~A[0][1];
A[0][2] = ~A[0][2];
A[1][3] = ~A[1][3];
A[2][2] = ~A[2][2];
A[3][2] = ~A[3][2];
A[4][0] = ~A[4][0];
#endif
}
#else /* define KECCAK_INPLACE to compile this code path */
/*
* This implementation is KECCAK_1X from above combined 4 times with
* a twist that allows to omit temporary storage and perform in-place
* processing. It's discussed in section 2.5 of "Keccak implementation
* overview". It's likely to be best suited for processors with large
* register bank... On the other hand processor with large register
* bank can as well use KECCAK_1X_ALT, it would be as fast but much
* more compact...
*/
static void FourRounds(uint64_t A[5][5], size_t i)
{
uint64_t B[5], C[5], D[5];
assert(i <= (sizeof(iotas) / sizeof(iotas[0]) - 4));
/* Round 4*n */
C[0] = A[0][0] ^ A[1][0] ^ A[2][0] ^ A[3][0] ^ A[4][0];
C[1] = A[0][1] ^ A[1][1] ^ A[2][1] ^ A[3][1] ^ A[4][1];
C[2] = A[0][2] ^ A[1][2] ^ A[2][2] ^ A[3][2] ^ A[4][2];
C[3] = A[0][3] ^ A[1][3] ^ A[2][3] ^ A[3][3] ^ A[4][3];
C[4] = A[0][4] ^ A[1][4] ^ A[2][4] ^ A[3][4] ^ A[4][4];
D[0] = ROL64(C[1], 1) ^ C[4];
D[1] = ROL64(C[2], 1) ^ C[0];
D[2] = ROL64(C[3], 1) ^ C[1];
D[3] = ROL64(C[4], 1) ^ C[2];
D[4] = ROL64(C[0], 1) ^ C[3];
B[0] = A[0][0] ^ D[0]; /* rotate by 0 */
B[1] = ROL64(A[1][1] ^ D[1], rhotates[1][1]);
B[2] = ROL64(A[2][2] ^ D[2], rhotates[2][2]);
B[3] = ROL64(A[3][3] ^ D[3], rhotates[3][3]);
B[4] = ROL64(A[4][4] ^ D[4], rhotates[4][4]);
C[0] = A[0][0] = B[0] ^ (~B[1] & B[2]) ^ iotas[i];
C[1] = A[1][1] = B[1] ^ (~B[2] & B[3]);
C[2] = A[2][2] = B[2] ^ (~B[3] & B[4]);
C[3] = A[3][3] = B[3] ^ (~B[4] & B[0]);
C[4] = A[4][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[0][3] ^ D[3], rhotates[0][3]);
B[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]);
B[2] = ROL64(A[2][0] ^ D[0], rhotates[2][0]);
B[3] = ROL64(A[3][1] ^ D[1], rhotates[3][1]);
B[4] = ROL64(A[4][2] ^ D[2], rhotates[4][2]);
C[0] ^= A[2][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[3][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[4][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[0][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[1][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[0][1] ^ D[1], rhotates[0][1]);
B[1] = ROL64(A[1][2] ^ D[2], rhotates[1][2]);
B[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]);
B[3] = ROL64(A[3][4] ^ D[4], rhotates[3][4]);
B[4] = ROL64(A[4][0] ^ D[0], rhotates[4][0]);
C[0] ^= A[4][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[0][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[1][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[2][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[3][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[0][4] ^ D[4], rhotates[0][4]);
B[1] = ROL64(A[1][0] ^ D[0], rhotates[1][0]);
B[2] = ROL64(A[2][1] ^ D[1], rhotates[2][1]);
B[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]);
B[4] = ROL64(A[4][3] ^ D[3], rhotates[4][3]);
C[0] ^= A[1][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[2][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[3][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[4][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[0][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[0][2] ^ D[2], rhotates[0][2]);
B[1] = ROL64(A[1][3] ^ D[3], rhotates[1][3]);
B[2] = ROL64(A[2][4] ^ D[4], rhotates[2][4]);
B[3] = ROL64(A[3][0] ^ D[0], rhotates[3][0]);
B[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]);
C[0] ^= A[3][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[4][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[0][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[1][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[2][4] = B[4] ^ (~B[0] & B[1]);
/* Round 4*n+1 */
D[0] = ROL64(C[1], 1) ^ C[4];
D[1] = ROL64(C[2], 1) ^ C[0];
D[2] = ROL64(C[3], 1) ^ C[1];
D[3] = ROL64(C[4], 1) ^ C[2];
D[4] = ROL64(C[0], 1) ^ C[3];
B[0] = A[0][0] ^ D[0]; /* rotate by 0 */
B[1] = ROL64(A[3][1] ^ D[1], rhotates[1][1]);
B[2] = ROL64(A[1][2] ^ D[2], rhotates[2][2]);
B[3] = ROL64(A[4][3] ^ D[3], rhotates[3][3]);
B[4] = ROL64(A[2][4] ^ D[4], rhotates[4][4]);
C[0] = A[0][0] = B[0] ^ (~B[1] & B[2]) ^ iotas[i + 1];
C[1] = A[3][1] = B[1] ^ (~B[2] & B[3]);
C[2] = A[1][2] = B[2] ^ (~B[3] & B[4]);
C[3] = A[4][3] = B[3] ^ (~B[4] & B[0]);
C[4] = A[2][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[3][3] ^ D[3], rhotates[0][3]);
B[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]);
B[2] = ROL64(A[4][0] ^ D[0], rhotates[2][0]);
B[3] = ROL64(A[2][1] ^ D[1], rhotates[3][1]);
B[4] = ROL64(A[0][2] ^ D[2], rhotates[4][2]);
C[0] ^= A[4][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[2][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[0][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[3][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[1][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[1][1] ^ D[1], rhotates[0][1]);
B[1] = ROL64(A[4][2] ^ D[2], rhotates[1][2]);
B[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]);
B[3] = ROL64(A[0][4] ^ D[4], rhotates[3][4]);
B[4] = ROL64(A[3][0] ^ D[0], rhotates[4][0]);
C[0] ^= A[3][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[1][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[4][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[2][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[0][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[4][4] ^ D[4], rhotates[0][4]);
B[1] = ROL64(A[2][0] ^ D[0], rhotates[1][0]);
B[2] = ROL64(A[0][1] ^ D[1], rhotates[2][1]);
B[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]);
B[4] = ROL64(A[1][3] ^ D[3], rhotates[4][3]);
C[0] ^= A[2][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[0][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[3][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[1][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[4][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[2][2] ^ D[2], rhotates[0][2]);
B[1] = ROL64(A[0][3] ^ D[3], rhotates[1][3]);
B[2] = ROL64(A[3][4] ^ D[4], rhotates[2][4]);
B[3] = ROL64(A[1][0] ^ D[0], rhotates[3][0]);
B[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]);
C[0] ^= A[1][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[4][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[2][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[0][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[3][4] = B[4] ^ (~B[0] & B[1]);
/* Round 4*n+2 */
D[0] = ROL64(C[1], 1) ^ C[4];
D[1] = ROL64(C[2], 1) ^ C[0];
D[2] = ROL64(C[3], 1) ^ C[1];
D[3] = ROL64(C[4], 1) ^ C[2];
D[4] = ROL64(C[0], 1) ^ C[3];
B[0] = A[0][0] ^ D[0]; /* rotate by 0 */
B[1] = ROL64(A[2][1] ^ D[1], rhotates[1][1]);
B[2] = ROL64(A[4][2] ^ D[2], rhotates[2][2]);
B[3] = ROL64(A[1][3] ^ D[3], rhotates[3][3]);
B[4] = ROL64(A[3][4] ^ D[4], rhotates[4][4]);
C[0] = A[0][0] = B[0] ^ (~B[1] & B[2]) ^ iotas[i + 2];
C[1] = A[2][1] = B[1] ^ (~B[2] & B[3]);
C[2] = A[4][2] = B[2] ^ (~B[3] & B[4]);
C[3] = A[1][3] = B[3] ^ (~B[4] & B[0]);
C[4] = A[3][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[4][3] ^ D[3], rhotates[0][3]);
B[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]);
B[2] = ROL64(A[3][0] ^ D[0], rhotates[2][0]);
B[3] = ROL64(A[0][1] ^ D[1], rhotates[3][1]);
B[4] = ROL64(A[2][2] ^ D[2], rhotates[4][2]);
C[0] ^= A[3][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[0][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[2][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[4][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[1][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[3][1] ^ D[1], rhotates[0][1]);
B[1] = ROL64(A[0][2] ^ D[2], rhotates[1][2]);
B[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]);
B[3] = ROL64(A[4][4] ^ D[4], rhotates[3][4]);
B[4] = ROL64(A[1][0] ^ D[0], rhotates[4][0]);
C[0] ^= A[1][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[3][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[0][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[2][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[4][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[2][4] ^ D[4], rhotates[0][4]);
B[1] = ROL64(A[4][0] ^ D[0], rhotates[1][0]);
B[2] = ROL64(A[1][1] ^ D[1], rhotates[2][1]);
B[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]);
B[4] = ROL64(A[0][3] ^ D[3], rhotates[4][3]);
C[0] ^= A[4][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[1][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[3][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[0][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[2][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[1][2] ^ D[2], rhotates[0][2]);
B[1] = ROL64(A[3][3] ^ D[3], rhotates[1][3]);
B[2] = ROL64(A[0][4] ^ D[4], rhotates[2][4]);
B[3] = ROL64(A[2][0] ^ D[0], rhotates[3][0]);
B[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]);
C[0] ^= A[2][0] = B[0] ^ (~B[1] & B[2]);
C[1] ^= A[4][1] = B[1] ^ (~B[2] & B[3]);
C[2] ^= A[1][2] = B[2] ^ (~B[3] & B[4]);
C[3] ^= A[3][3] = B[3] ^ (~B[4] & B[0]);
C[4] ^= A[0][4] = B[4] ^ (~B[0] & B[1]);
/* Round 4*n+3 */
D[0] = ROL64(C[1], 1) ^ C[4];
D[1] = ROL64(C[2], 1) ^ C[0];
D[2] = ROL64(C[3], 1) ^ C[1];
D[3] = ROL64(C[4], 1) ^ C[2];
D[4] = ROL64(C[0], 1) ^ C[3];
B[0] = A[0][0] ^ D[0]; /* rotate by 0 */
B[1] = ROL64(A[0][1] ^ D[1], rhotates[1][1]);
B[2] = ROL64(A[0][2] ^ D[2], rhotates[2][2]);
B[3] = ROL64(A[0][3] ^ D[3], rhotates[3][3]);
B[4] = ROL64(A[0][4] ^ D[4], rhotates[4][4]);
/* C[0] = */ A[0][0] = B[0] ^ (~B[1] & B[2]) ^ iotas[i + 3];
/* C[1] = */ A[0][1] = B[1] ^ (~B[2] & B[3]);
/* C[2] = */ A[0][2] = B[2] ^ (~B[3] & B[4]);
/* C[3] = */ A[0][3] = B[3] ^ (~B[4] & B[0]);
/* C[4] = */ A[0][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[1][3] ^ D[3], rhotates[0][3]);
B[1] = ROL64(A[1][4] ^ D[4], rhotates[1][4]);
B[2] = ROL64(A[1][0] ^ D[0], rhotates[2][0]);
B[3] = ROL64(A[1][1] ^ D[1], rhotates[3][1]);
B[4] = ROL64(A[1][2] ^ D[2], rhotates[4][2]);
/* C[0] ^= */ A[1][0] = B[0] ^ (~B[1] & B[2]);
/* C[1] ^= */ A[1][1] = B[1] ^ (~B[2] & B[3]);
/* C[2] ^= */ A[1][2] = B[2] ^ (~B[3] & B[4]);
/* C[3] ^= */ A[1][3] = B[3] ^ (~B[4] & B[0]);
/* C[4] ^= */ A[1][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[2][1] ^ D[1], rhotates[0][1]);
B[1] = ROL64(A[2][2] ^ D[2], rhotates[1][2]);
B[2] = ROL64(A[2][3] ^ D[3], rhotates[2][3]);
B[3] = ROL64(A[2][4] ^ D[4], rhotates[3][4]);
B[4] = ROL64(A[2][0] ^ D[0], rhotates[4][0]);
/* C[0] ^= */ A[2][0] = B[0] ^ (~B[1] & B[2]);
/* C[1] ^= */ A[2][1] = B[1] ^ (~B[2] & B[3]);
/* C[2] ^= */ A[2][2] = B[2] ^ (~B[3] & B[4]);
/* C[3] ^= */ A[2][3] = B[3] ^ (~B[4] & B[0]);
/* C[4] ^= */ A[2][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[3][4] ^ D[4], rhotates[0][4]);
B[1] = ROL64(A[3][0] ^ D[0], rhotates[1][0]);
B[2] = ROL64(A[3][1] ^ D[1], rhotates[2][1]);
B[3] = ROL64(A[3][2] ^ D[2], rhotates[3][2]);
B[4] = ROL64(A[3][3] ^ D[3], rhotates[4][3]);
/* C[0] ^= */ A[3][0] = B[0] ^ (~B[1] & B[2]);
/* C[1] ^= */ A[3][1] = B[1] ^ (~B[2] & B[3]);
/* C[2] ^= */ A[3][2] = B[2] ^ (~B[3] & B[4]);
/* C[3] ^= */ A[3][3] = B[3] ^ (~B[4] & B[0]);
/* C[4] ^= */ A[3][4] = B[4] ^ (~B[0] & B[1]);
B[0] = ROL64(A[4][2] ^ D[2], rhotates[0][2]);
B[1] = ROL64(A[4][3] ^ D[3], rhotates[1][3]);
B[2] = ROL64(A[4][4] ^ D[4], rhotates[2][4]);
B[3] = ROL64(A[4][0] ^ D[0], rhotates[3][0]);
B[4] = ROL64(A[4][1] ^ D[1], rhotates[4][1]);
/* C[0] ^= */ A[4][0] = B[0] ^ (~B[1] & B[2]);
/* C[1] ^= */ A[4][1] = B[1] ^ (~B[2] & B[3]);
/* C[2] ^= */ A[4][2] = B[2] ^ (~B[3] & B[4]);
/* C[3] ^= */ A[4][3] = B[3] ^ (~B[4] & B[0]);
/* C[4] ^= */ A[4][4] = B[4] ^ (~B[0] & B[1]);
}
static void KeccakF1600(uint64_t A[5][5])
{
size_t i;
for (i = 0; i < 24; i += 4) {
FourRounds(A, i);
}
}
#endif
static uint64_t BitInterleave(uint64_t Ai)
{
if (BIT_INTERLEAVE) {
uint32_t hi = (uint32_t)(Ai >> 32), lo = (uint32_t)Ai;
uint32_t t0, t1;
t0 = lo & 0x55555555;
t0 |= t0 >> 1; t0 &= 0x33333333;
t0 |= t0 >> 2; t0 &= 0x0f0f0f0f;
t0 |= t0 >> 4; t0 &= 0x00ff00ff;
t0 |= t0 >> 8; t0 &= 0x0000ffff;
t1 = hi & 0x55555555;
t1 |= t1 >> 1; t1 &= 0x33333333;
t1 |= t1 >> 2; t1 &= 0x0f0f0f0f;
t1 |= t1 >> 4; t1 &= 0x00ff00ff;
t1 |= t1 >> 8; t1 <<= 16;
lo &= 0xaaaaaaaa;
lo |= lo << 1; lo &= 0xcccccccc;
lo |= lo << 2; lo &= 0xf0f0f0f0;
lo |= lo << 4; lo &= 0xff00ff00;
lo |= lo << 8; lo >>= 16;
hi &= 0xaaaaaaaa;
hi |= hi << 1; hi &= 0xcccccccc;
hi |= hi << 2; hi &= 0xf0f0f0f0;
hi |= hi << 4; hi &= 0xff00ff00;
hi |= hi << 8; hi &= 0xffff0000;
Ai = ((uint64_t)(hi | lo) << 32) | (t1 | t0);
}
return Ai;
}
static uint64_t BitDeinterleave(uint64_t Ai)
{
if (BIT_INTERLEAVE) {
uint32_t hi = (uint32_t)(Ai >> 32), lo = (uint32_t)Ai;
uint32_t t0, t1;
t0 = lo & 0x0000ffff;
t0 |= t0 << 8; t0 &= 0x00ff00ff;
t0 |= t0 << 4; t0 &= 0x0f0f0f0f;
t0 |= t0 << 2; t0 &= 0x33333333;
t0 |= t0 << 1; t0 &= 0x55555555;
t1 = hi << 16;
t1 |= t1 >> 8; t1 &= 0xff00ff00;
t1 |= t1 >> 4; t1 &= 0xf0f0f0f0;
t1 |= t1 >> 2; t1 &= 0xcccccccc;
t1 |= t1 >> 1; t1 &= 0xaaaaaaaa;
lo >>= 16;
lo |= lo << 8; lo &= 0x00ff00ff;
lo |= lo << 4; lo &= 0x0f0f0f0f;
lo |= lo << 2; lo &= 0x33333333;
lo |= lo << 1; lo &= 0x55555555;
hi &= 0xffff0000;
hi |= hi >> 8; hi &= 0xff00ff00;
hi |= hi >> 4; hi &= 0xf0f0f0f0;
hi |= hi >> 2; hi &= 0xcccccccc;
hi |= hi >> 1; hi &= 0xaaaaaaaa;
Ai = ((uint64_t)(hi | lo) << 32) | (t1 | t0);
}
return Ai;
}
/*
* SHA3_absorb can be called multiple times, but at each invocation
* largest multiple of |r| out of |len| bytes are processed. Then
* remaining amount of bytes is returned. This is done to spare caller
* trouble of calculating the largest multiple of |r|. |r| can be viewed
* as blocksize. It is commonly (1600 - 256*n)/8, e.g. 168, 136, 104,
* 72, but can also be (1600 - 448)/8 = 144. All this means that message
* padding and intermediate sub-block buffering, byte- or bitwise, is
* caller's responsibility.
*/
size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
size_t r)
{
uint64_t *A_flat = (uint64_t *)A;
size_t i, w = r / 8;
assert(r < (25 * sizeof(A[0][0])) && (r % 8) == 0);
while (len >= r) {
for (i = 0; i < w; i++) {
uint64_t Ai = (uint64_t)inp[0] | (uint64_t)inp[1] << 8 |
(uint64_t)inp[2] << 16 | (uint64_t)inp[3] << 24 |
(uint64_t)inp[4] << 32 | (uint64_t)inp[5] << 40 |
(uint64_t)inp[6] << 48 | (uint64_t)inp[7] << 56;
inp += 8;
A_flat[i] ^= BitInterleave(Ai);
}
KeccakF1600(A);
len -= r;
}
return len;
}
/*
* SHA3_squeeze is called once at the end to generate |out| hash value
* of |len| bytes.
*/
void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r)
{
uint64_t *A_flat = (uint64_t *)A;
size_t i, w = r / 8;
assert(r < (25 * sizeof(A[0][0])) && (r % 8) == 0);
while (len != 0) {
for (i = 0; i < w && len != 0; i++) {
uint64_t Ai = BitDeinterleave(A_flat[i]);
if (len < 8) {
for (i = 0; i < len; i++) {
*out++ = (unsigned char)Ai;
Ai >>= 8;
}
return;
}
out[0] = (unsigned char)(Ai);
out[1] = (unsigned char)(Ai >> 8);
out[2] = (unsigned char)(Ai >> 16);
out[3] = (unsigned char)(Ai >> 24);
out[4] = (unsigned char)(Ai >> 32);
out[5] = (unsigned char)(Ai >> 40);
out[6] = (unsigned char)(Ai >> 48);
out[7] = (unsigned char)(Ai >> 56);
out += 8;
len -= 8;
}
if (len)
KeccakF1600(A);
}
}
#endif
#ifdef SELFTEST
/*
* Post-padding one-shot implementations would look as following:
*
* SHA3_224 SHA3_sponge(inp, len, out, 224/8, (1600-448)/8);
* SHA3_256 SHA3_sponge(inp, len, out, 256/8, (1600-512)/8);
* SHA3_384 SHA3_sponge(inp, len, out, 384/8, (1600-768)/8);
* SHA3_512 SHA3_sponge(inp, len, out, 512/8, (1600-1024)/8);
* SHAKE_128 SHA3_sponge(inp, len, out, d, (1600-256)/8);
* SHAKE_256 SHA3_sponge(inp, len, out, d, (1600-512)/8);
*/
void SHA3_sponge(const unsigned char *inp, size_t len,
unsigned char *out, size_t d, size_t r)
{
uint64_t A[5][5];
memset(A, 0, sizeof(A));
SHA3_absorb(A, inp, len, r);
SHA3_squeeze(A, out, d, r);
}
# include <stdio.h>
int main()
{
/*
* This is 5-bit SHAKE128 test from http://csrc.nist.gov/groups/ST/toolkit/examples.html#aHashing
*/
unsigned char test[168] = { '\xf3', '\x3' };
unsigned char out[512];
size_t i;
static const unsigned char result[512] = {
0x2E, 0x0A, 0xBF, 0xBA, 0x83, 0xE6, 0x72, 0x0B,
0xFB, 0xC2, 0x25, 0xFF, 0x6B, 0x7A, 0xB9, 0xFF,
0xCE, 0x58, 0xBA, 0x02, 0x7E, 0xE3, 0xD8, 0x98,
0x76, 0x4F, 0xEF, 0x28, 0x7D, 0xDE, 0xCC, 0xCA,
0x3E, 0x6E, 0x59, 0x98, 0x41, 0x1E, 0x7D, 0xDB,
0x32, 0xF6, 0x75, 0x38, 0xF5, 0x00, 0xB1, 0x8C,
0x8C, 0x97, 0xC4, 0x52, 0xC3, 0x70, 0xEA, 0x2C,
0xF0, 0xAF, 0xCA, 0x3E, 0x05, 0xDE, 0x7E, 0x4D,
0xE2, 0x7F, 0xA4, 0x41, 0xA9, 0xCB, 0x34, 0xFD,
0x17, 0xC9, 0x78, 0xB4, 0x2D, 0x5B, 0x7E, 0x7F,
0x9A, 0xB1, 0x8F, 0xFE, 0xFF, 0xC3, 0xC5, 0xAC,
0x2F, 0x3A, 0x45, 0x5E, 0xEB, 0xFD, 0xC7, 0x6C,
0xEA, 0xEB, 0x0A, 0x2C, 0xCA, 0x22, 0xEE, 0xF6,
0xE6, 0x37, 0xF4, 0xCA, 0xBE, 0x5C, 0x51, 0xDE,
0xD2, 0xE3, 0xFA, 0xD8, 0xB9, 0x52, 0x70, 0xA3,
0x21, 0x84, 0x56, 0x64, 0xF1, 0x07, 0xD1, 0x64,
0x96, 0xBB, 0x7A, 0xBF, 0xBE, 0x75, 0x04, 0xB6,
0xED, 0xE2, 0xE8, 0x9E, 0x4B, 0x99, 0x6F, 0xB5,
0x8E, 0xFD, 0xC4, 0x18, 0x1F, 0x91, 0x63, 0x38,
0x1C, 0xBE, 0x7B, 0xC0, 0x06, 0xA7, 0xA2, 0x05,
0x98, 0x9C, 0x52, 0x6C, 0xD1, 0xBD, 0x68, 0x98,
0x36, 0x93, 0xB4, 0xBD, 0xC5, 0x37, 0x28, 0xB2,
0x41, 0xC1, 0xCF, 0xF4, 0x2B, 0xB6, 0x11, 0x50,
0x2C, 0x35, 0x20, 0x5C, 0xAB, 0xB2, 0x88, 0x75,
0x56, 0x55, 0xD6, 0x20, 0xC6, 0x79, 0x94, 0xF0,
0x64, 0x51, 0x18, 0x7F, 0x6F, 0xD1, 0x7E, 0x04,
0x66, 0x82, 0xBA, 0x12, 0x86, 0x06, 0x3F, 0xF8,
0x8F, 0xE2, 0x50, 0x8D, 0x1F, 0xCA, 0xF9, 0x03,
0x5A, 0x12, 0x31, 0xAD, 0x41, 0x50, 0xA9, 0xC9,
0xB2, 0x4C, 0x9B, 0x2D, 0x66, 0xB2, 0xAD, 0x1B,
0xDE, 0x0B, 0xD0, 0xBB, 0xCB, 0x8B, 0xE0, 0x5B,
0x83, 0x52, 0x29, 0xEF, 0x79, 0x19, 0x73, 0x73,
0x23, 0x42, 0x44, 0x01, 0xE1, 0xD8, 0x37, 0xB6,
0x6E, 0xB4, 0xE6, 0x30, 0xFF, 0x1D, 0xE7, 0x0C,
0xB3, 0x17, 0xC2, 0xBA, 0xCB, 0x08, 0x00, 0x1D,
0x34, 0x77, 0xB7, 0xA7, 0x0A, 0x57, 0x6D, 0x20,
0x86, 0x90, 0x33, 0x58, 0x9D, 0x85, 0xA0, 0x1D,
0xDB, 0x2B, 0x66, 0x46, 0xC0, 0x43, 0xB5, 0x9F,
0xC0, 0x11, 0x31, 0x1D, 0xA6, 0x66, 0xFA, 0x5A,
0xD1, 0xD6, 0x38, 0x7F, 0xA9, 0xBC, 0x40, 0x15,
0xA3, 0x8A, 0x51, 0xD1, 0xDA, 0x1E, 0xA6, 0x1D,
0x64, 0x8D, 0xC8, 0xE3, 0x9A, 0x88, 0xB9, 0xD6,
0x22, 0xBD, 0xE2, 0x07, 0xFD, 0xAB, 0xC6, 0xF2,
0x82, 0x7A, 0x88, 0x0C, 0x33, 0x0B, 0xBF, 0x6D,
0xF7, 0x33, 0x77, 0x4B, 0x65, 0x3E, 0x57, 0x30,
0x5D, 0x78, 0xDC, 0xE1, 0x12, 0xF1, 0x0A, 0x2C,
0x71, 0xF4, 0xCD, 0xAD, 0x92, 0xED, 0x11, 0x3E,
0x1C, 0xEA, 0x63, 0xB9, 0x19, 0x25, 0xED, 0x28,
0x19, 0x1E, 0x6D, 0xBB, 0xB5, 0xAA, 0x5A, 0x2A,
0xFD, 0xA5, 0x1F, 0xC0, 0x5A, 0x3A, 0xF5, 0x25,
0x8B, 0x87, 0x66, 0x52, 0x43, 0x55, 0x0F, 0x28,
0x94, 0x8A, 0xE2, 0xB8, 0xBE, 0xB6, 0xBC, 0x9C,
0x77, 0x0B, 0x35, 0xF0, 0x67, 0xEA, 0xA6, 0x41,
0xEF, 0xE6, 0x5B, 0x1A, 0x44, 0x90, 0x9D, 0x1B,
0x14, 0x9F, 0x97, 0xEE, 0xA6, 0x01, 0x39, 0x1C,
0x60, 0x9E, 0xC8, 0x1D, 0x19, 0x30, 0xF5, 0x7C,
0x18, 0xA4, 0xE0, 0xFA, 0xB4, 0x91, 0xD1, 0xCA,
0xDF, 0xD5, 0x04, 0x83, 0x44, 0x9E, 0xDC, 0x0F,
0x07, 0xFF, 0xB2, 0x4D, 0x2C, 0x6F, 0x9A, 0x9A,
0x3B, 0xFF, 0x39, 0xAE, 0x3D, 0x57, 0xF5, 0x60,
0x65, 0x4D, 0x7D, 0x75, 0xC9, 0x08, 0xAB, 0xE6,
0x25, 0x64, 0x75, 0x3E, 0xAC, 0x39, 0xD7, 0x50,
0x3D, 0xA6, 0xD3, 0x7C, 0x2E, 0x32, 0xE1, 0xAF,
0x3B, 0x8A, 0xEC, 0x8A, 0xE3, 0x06, 0x9C, 0xD9
};
test[167] = '\x80';
SHA3_sponge(test, sizeof(test), out, sizeof(out), sizeof(test));
/*
* Rationale behind keeping output [formatted as below] is that
* one should be able to redirect it to a file, then copy-n-paste
* final "output val" from official example to another file, and
* compare the two with diff(1).
*/
for (i = 0; i < sizeof(out);) {
printf("%02X", out[i]);
printf(++i % 16 && i != sizeof(out) ? " " : "\n");
}
if (memcmp(out,result,sizeof(out))) {
fprintf(stderr,"failure\n");
return 1;
} else {
fprintf(stderr,"success\n");
return 0;
}
}
#endif
diff --git a/crypto/x509/x509_lu.c b/crypto/x509/x509_lu.c
index be39015b0d01..8ddd7ec28023 100644
--- a/crypto/x509/x509_lu.c
+++ b/crypto/x509/x509_lu.c
@@ -1,898 +1,901 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
#include <openssl/x509.h>
#include "internal/x509_int.h"
#include <openssl/x509v3.h>
#include "x509_lcl.h"
X509_LOOKUP *X509_LOOKUP_new(X509_LOOKUP_METHOD *method)
{
X509_LOOKUP *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
X509err(X509_F_X509_LOOKUP_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->method = method;
if (method->new_item != NULL && method->new_item(ret) == 0) {
OPENSSL_free(ret);
return NULL;
}
return ret;
}
void X509_LOOKUP_free(X509_LOOKUP *ctx)
{
if (ctx == NULL)
return;
if ((ctx->method != NULL) && (ctx->method->free != NULL))
(*ctx->method->free) (ctx);
OPENSSL_free(ctx);
}
int X509_STORE_lock(X509_STORE *s)
{
return CRYPTO_THREAD_write_lock(s->lock);
}
int X509_STORE_unlock(X509_STORE *s)
{
return CRYPTO_THREAD_unlock(s->lock);
}
int X509_LOOKUP_init(X509_LOOKUP *ctx)
{
if (ctx->method == NULL)
return 0;
if (ctx->method->init != NULL)
return ctx->method->init(ctx);
else
return 1;
}
int X509_LOOKUP_shutdown(X509_LOOKUP *ctx)
{
if (ctx->method == NULL)
return 0;
if (ctx->method->shutdown != NULL)
return ctx->method->shutdown(ctx);
else
return 1;
}
int X509_LOOKUP_ctrl(X509_LOOKUP *ctx, int cmd, const char *argc, long argl,
char **ret)
{
if (ctx->method == NULL)
return -1;
if (ctx->method->ctrl != NULL)
return ctx->method->ctrl(ctx, cmd, argc, argl, ret);
else
return 1;
}
int X509_LOOKUP_by_subject(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_subject == NULL))
return 0;
if (ctx->skip)
return 0;
return ctx->method->get_by_subject(ctx, type, name, ret);
}
int X509_LOOKUP_by_issuer_serial(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
X509_NAME *name, ASN1_INTEGER *serial,
X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_issuer_serial == NULL))
return 0;
return ctx->method->get_by_issuer_serial(ctx, type, name, serial, ret);
}
int X509_LOOKUP_by_fingerprint(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const unsigned char *bytes, int len,
X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_fingerprint == NULL))
return 0;
return ctx->method->get_by_fingerprint(ctx, type, bytes, len, ret);
}
int X509_LOOKUP_by_alias(X509_LOOKUP *ctx, X509_LOOKUP_TYPE type,
const char *str, int len, X509_OBJECT *ret)
{
if ((ctx->method == NULL) || (ctx->method->get_by_alias == NULL))
return 0;
return ctx->method->get_by_alias(ctx, type, str, len, ret);
}
int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data)
{
ctx->method_data = data;
return 1;
}
void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx)
{
return ctx->method_data;
}
X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx)
{
return ctx->store_ctx;
}
static int x509_object_cmp(const X509_OBJECT *const *a,
const X509_OBJECT *const *b)
{
int ret;
ret = ((*a)->type - (*b)->type);
if (ret)
return ret;
switch ((*a)->type) {
case X509_LU_X509:
ret = X509_subject_name_cmp((*a)->data.x509, (*b)->data.x509);
break;
case X509_LU_CRL:
ret = X509_CRL_cmp((*a)->data.crl, (*b)->data.crl);
break;
case X509_LU_NONE:
/* abort(); */
return 0;
}
return ret;
}
X509_STORE *X509_STORE_new(void)
{
X509_STORE *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
if ((ret->objs = sk_X509_OBJECT_new(x509_object_cmp)) == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->cache = 1;
if ((ret->get_cert_methods = sk_X509_LOOKUP_new_null()) == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
if ((ret->param = X509_VERIFY_PARAM_new()) == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_X509_STORE, ret, &ret->ex_data)) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
X509err(X509_F_X509_STORE_NEW, ERR_R_MALLOC_FAILURE);
goto err;
}
ret->references = 1;
return ret;
err:
X509_VERIFY_PARAM_free(ret->param);
sk_X509_OBJECT_free(ret->objs);
sk_X509_LOOKUP_free(ret->get_cert_methods);
OPENSSL_free(ret);
return NULL;
}
void X509_STORE_free(X509_STORE *vfy)
{
int i;
STACK_OF(X509_LOOKUP) *sk;
X509_LOOKUP *lu;
if (vfy == NULL)
return;
CRYPTO_DOWN_REF(&vfy->references, &i, vfy->lock);
REF_PRINT_COUNT("X509_STORE", vfy);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
sk = vfy->get_cert_methods;
for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
lu = sk_X509_LOOKUP_value(sk, i);
X509_LOOKUP_shutdown(lu);
X509_LOOKUP_free(lu);
}
sk_X509_LOOKUP_free(sk);
sk_X509_OBJECT_pop_free(vfy->objs, X509_OBJECT_free);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_X509_STORE, vfy, &vfy->ex_data);
X509_VERIFY_PARAM_free(vfy->param);
CRYPTO_THREAD_lock_free(vfy->lock);
OPENSSL_free(vfy);
}
int X509_STORE_up_ref(X509_STORE *vfy)
{
int i;
if (CRYPTO_UP_REF(&vfy->references, &i, vfy->lock) <= 0)
return 0;
REF_PRINT_COUNT("X509_STORE", a);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
X509_LOOKUP *X509_STORE_add_lookup(X509_STORE *v, X509_LOOKUP_METHOD *m)
{
int i;
STACK_OF(X509_LOOKUP) *sk;
X509_LOOKUP *lu;
sk = v->get_cert_methods;
for (i = 0; i < sk_X509_LOOKUP_num(sk); i++) {
lu = sk_X509_LOOKUP_value(sk, i);
if (m == lu->method) {
return lu;
}
}
/* a new one */
lu = X509_LOOKUP_new(m);
if (lu == NULL) {
X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE);
return NULL;
}
lu->store_ctx = v;
if (sk_X509_LOOKUP_push(v->get_cert_methods, lu))
return lu;
/* malloc failed */
X509err(X509_F_X509_STORE_ADD_LOOKUP, ERR_R_MALLOC_FAILURE);
X509_LOOKUP_free(lu);
return NULL;
}
X509_OBJECT *X509_STORE_CTX_get_obj_by_subject(X509_STORE_CTX *vs,
X509_LOOKUP_TYPE type,
X509_NAME *name)
{
X509_OBJECT *ret = X509_OBJECT_new();
if (ret == NULL)
return NULL;
if (!X509_STORE_CTX_get_by_subject(vs, type, name, ret)) {
X509_OBJECT_free(ret);
return NULL;
}
return ret;
}
int X509_STORE_CTX_get_by_subject(X509_STORE_CTX *vs, X509_LOOKUP_TYPE type,
X509_NAME *name, X509_OBJECT *ret)
{
X509_STORE *ctx = vs->ctx;
X509_LOOKUP *lu;
X509_OBJECT stmp, *tmp;
int i, j;
if (ctx == NULL)
return 0;
+ stmp.type = X509_LU_NONE;
+ stmp.data.ptr = NULL;
+
CRYPTO_THREAD_write_lock(ctx->lock);
tmp = X509_OBJECT_retrieve_by_subject(ctx->objs, type, name);
CRYPTO_THREAD_unlock(ctx->lock);
if (tmp == NULL || type == X509_LU_CRL) {
for (i = 0; i < sk_X509_LOOKUP_num(ctx->get_cert_methods); i++) {
lu = sk_X509_LOOKUP_value(ctx->get_cert_methods, i);
j = X509_LOOKUP_by_subject(lu, type, name, &stmp);
if (j) {
tmp = &stmp;
break;
}
}
if (tmp == NULL)
return 0;
}
ret->type = tmp->type;
ret->data.ptr = tmp->data.ptr;
X509_OBJECT_up_ref_count(ret);
return 1;
}
static int x509_store_add(X509_STORE *ctx, void *x, int crl) {
X509_OBJECT *obj;
int ret = 0, added = 0;
if (x == NULL)
return 0;
obj = X509_OBJECT_new();
if (obj == NULL)
return 0;
if (crl) {
obj->type = X509_LU_CRL;
obj->data.crl = (X509_CRL *)x;
} else {
obj->type = X509_LU_X509;
obj->data.x509 = (X509 *)x;
}
X509_OBJECT_up_ref_count(obj);
CRYPTO_THREAD_write_lock(ctx->lock);
if (X509_OBJECT_retrieve_match(ctx->objs, obj)) {
ret = 1;
} else {
added = sk_X509_OBJECT_push(ctx->objs, obj);
ret = added != 0;
}
CRYPTO_THREAD_unlock(ctx->lock);
if (added == 0) /* obj not pushed */
X509_OBJECT_free(obj);
return ret;
}
int X509_STORE_add_cert(X509_STORE *ctx, X509 *x)
{
if (!x509_store_add(ctx, x, 0)) {
X509err(X509_F_X509_STORE_ADD_CERT, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
int X509_STORE_add_crl(X509_STORE *ctx, X509_CRL *x)
{
if (!x509_store_add(ctx, x, 1)) {
X509err(X509_F_X509_STORE_ADD_CRL, ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
}
int X509_OBJECT_up_ref_count(X509_OBJECT *a)
{
switch (a->type) {
case X509_LU_NONE:
break;
case X509_LU_X509:
return X509_up_ref(a->data.x509);
case X509_LU_CRL:
return X509_CRL_up_ref(a->data.crl);
}
return 1;
}
X509 *X509_OBJECT_get0_X509(const X509_OBJECT *a)
{
if (a == NULL || a->type != X509_LU_X509)
return NULL;
return a->data.x509;
}
X509_CRL *X509_OBJECT_get0_X509_CRL(X509_OBJECT *a)
{
if (a == NULL || a->type != X509_LU_CRL)
return NULL;
return a->data.crl;
}
X509_LOOKUP_TYPE X509_OBJECT_get_type(const X509_OBJECT *a)
{
return a->type;
}
X509_OBJECT *X509_OBJECT_new(void)
{
X509_OBJECT *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
X509err(X509_F_X509_OBJECT_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->type = X509_LU_NONE;
return ret;
}
static void x509_object_free_internal(X509_OBJECT *a)
{
if (a == NULL)
return;
switch (a->type) {
case X509_LU_NONE:
break;
case X509_LU_X509:
X509_free(a->data.x509);
break;
case X509_LU_CRL:
X509_CRL_free(a->data.crl);
break;
}
}
int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj)
{
if (a == NULL || !X509_up_ref(obj))
return 0;
x509_object_free_internal(a);
a->type = X509_LU_X509;
a->data.x509 = obj;
return 1;
}
int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj)
{
if (a == NULL || !X509_CRL_up_ref(obj))
return 0;
x509_object_free_internal(a);
a->type = X509_LU_CRL;
a->data.crl = obj;
return 1;
}
void X509_OBJECT_free(X509_OBJECT *a)
{
x509_object_free_internal(a);
OPENSSL_free(a);
}
static int x509_object_idx_cnt(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
X509_NAME *name, int *pnmatch)
{
X509_OBJECT stmp;
X509 x509_s;
X509_CRL crl_s;
int idx;
stmp.type = type;
switch (type) {
case X509_LU_X509:
stmp.data.x509 = &x509_s;
x509_s.cert_info.subject = name;
break;
case X509_LU_CRL:
stmp.data.crl = &crl_s;
crl_s.crl.issuer = name;
break;
case X509_LU_NONE:
/* abort(); */
return -1;
}
idx = sk_X509_OBJECT_find(h, &stmp);
if (idx >= 0 && pnmatch) {
int tidx;
const X509_OBJECT *tobj, *pstmp;
*pnmatch = 1;
pstmp = &stmp;
for (tidx = idx + 1; tidx < sk_X509_OBJECT_num(h); tidx++) {
tobj = sk_X509_OBJECT_value(h, tidx);
if (x509_object_cmp(&tobj, &pstmp))
break;
(*pnmatch)++;
}
}
return idx;
}
int X509_OBJECT_idx_by_subject(STACK_OF(X509_OBJECT) *h, X509_LOOKUP_TYPE type,
X509_NAME *name)
{
return x509_object_idx_cnt(h, type, name, NULL);
}
X509_OBJECT *X509_OBJECT_retrieve_by_subject(STACK_OF(X509_OBJECT) *h,
X509_LOOKUP_TYPE type,
X509_NAME *name)
{
int idx;
idx = X509_OBJECT_idx_by_subject(h, type, name);
if (idx == -1)
return NULL;
return sk_X509_OBJECT_value(h, idx);
}
STACK_OF(X509_OBJECT) *X509_STORE_get0_objects(X509_STORE *v)
{
return v->objs;
}
STACK_OF(X509) *X509_STORE_CTX_get1_certs(X509_STORE_CTX *ctx, X509_NAME *nm)
{
int i, idx, cnt;
STACK_OF(X509) *sk = NULL;
X509 *x;
X509_OBJECT *obj;
if (ctx->ctx == NULL)
return NULL;
CRYPTO_THREAD_write_lock(ctx->ctx->lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
if (idx < 0) {
/*
* Nothing found in cache: do lookup to possibly add new objects to
* cache
*/
X509_OBJECT *xobj = X509_OBJECT_new();
CRYPTO_THREAD_unlock(ctx->ctx->lock);
if (xobj == NULL)
return NULL;
if (!X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, nm, xobj)) {
X509_OBJECT_free(xobj);
return NULL;
}
X509_OBJECT_free(xobj);
CRYPTO_THREAD_write_lock(ctx->ctx->lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_X509, nm, &cnt);
if (idx < 0) {
CRYPTO_THREAD_unlock(ctx->ctx->lock);
return NULL;
}
}
sk = sk_X509_new_null();
for (i = 0; i < cnt; i++, idx++) {
obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
x = obj->data.x509;
X509_up_ref(x);
if (!sk_X509_push(sk, x)) {
CRYPTO_THREAD_unlock(ctx->ctx->lock);
X509_free(x);
sk_X509_pop_free(sk, X509_free);
return NULL;
}
}
CRYPTO_THREAD_unlock(ctx->ctx->lock);
return sk;
}
STACK_OF(X509_CRL) *X509_STORE_CTX_get1_crls(X509_STORE_CTX *ctx, X509_NAME *nm)
{
int i, idx, cnt;
STACK_OF(X509_CRL) *sk = sk_X509_CRL_new_null();
X509_CRL *x;
X509_OBJECT *obj, *xobj = X509_OBJECT_new();
/* Always do lookup to possibly add new CRLs to cache */
if (sk == NULL
|| xobj == NULL
|| ctx->ctx == NULL
|| !X509_STORE_CTX_get_by_subject(ctx, X509_LU_CRL, nm, xobj)) {
X509_OBJECT_free(xobj);
sk_X509_CRL_free(sk);
return NULL;
}
X509_OBJECT_free(xobj);
CRYPTO_THREAD_write_lock(ctx->ctx->lock);
idx = x509_object_idx_cnt(ctx->ctx->objs, X509_LU_CRL, nm, &cnt);
if (idx < 0) {
CRYPTO_THREAD_unlock(ctx->ctx->lock);
sk_X509_CRL_free(sk);
return NULL;
}
for (i = 0; i < cnt; i++, idx++) {
obj = sk_X509_OBJECT_value(ctx->ctx->objs, idx);
x = obj->data.crl;
X509_CRL_up_ref(x);
if (!sk_X509_CRL_push(sk, x)) {
CRYPTO_THREAD_unlock(ctx->ctx->lock);
X509_CRL_free(x);
sk_X509_CRL_pop_free(sk, X509_CRL_free);
return NULL;
}
}
CRYPTO_THREAD_unlock(ctx->ctx->lock);
return sk;
}
X509_OBJECT *X509_OBJECT_retrieve_match(STACK_OF(X509_OBJECT) *h,
X509_OBJECT *x)
{
int idx, i, num;
X509_OBJECT *obj;
idx = sk_X509_OBJECT_find(h, x);
if (idx < 0)
return NULL;
if ((x->type != X509_LU_X509) && (x->type != X509_LU_CRL))
return sk_X509_OBJECT_value(h, idx);
for (i = idx, num = sk_X509_OBJECT_num(h); i < num; i++) {
obj = sk_X509_OBJECT_value(h, i);
if (x509_object_cmp((const X509_OBJECT **)&obj,
(const X509_OBJECT **)&x))
return NULL;
if (x->type == X509_LU_X509) {
if (!X509_cmp(obj->data.x509, x->data.x509))
return obj;
} else if (x->type == X509_LU_CRL) {
if (!X509_CRL_match(obj->data.crl, x->data.crl))
return obj;
} else
return obj;
}
return NULL;
}
/*-
* Try to get issuer certificate from store. Due to limitations
* of the API this can only retrieve a single certificate matching
* a given subject name. However it will fill the cache with all
* matching certificates, so we can examine the cache for all
* matches.
*
* Return values are:
* 1 lookup successful.
* 0 certificate not found.
* -1 some other error.
*/
int X509_STORE_CTX_get1_issuer(X509 **issuer, X509_STORE_CTX *ctx, X509 *x)
{
X509_NAME *xn;
X509_OBJECT *obj = X509_OBJECT_new(), *pobj = NULL;
int i, ok, idx, ret;
if (obj == NULL)
return -1;
*issuer = NULL;
xn = X509_get_issuer_name(x);
ok = X509_STORE_CTX_get_by_subject(ctx, X509_LU_X509, xn, obj);
if (ok != 1) {
X509_OBJECT_free(obj);
return 0;
}
/* If certificate matches all OK */
if (ctx->check_issued(ctx, x, obj->data.x509)) {
if (x509_check_cert_time(ctx, obj->data.x509, -1)) {
*issuer = obj->data.x509;
X509_up_ref(*issuer);
X509_OBJECT_free(obj);
return 1;
}
}
X509_OBJECT_free(obj);
if (ctx->ctx == NULL)
return 0;
/* Else find index of first cert accepted by 'check_issued' */
ret = 0;
CRYPTO_THREAD_write_lock(ctx->ctx->lock);
idx = X509_OBJECT_idx_by_subject(ctx->ctx->objs, X509_LU_X509, xn);
if (idx != -1) { /* should be true as we've had at least one
* match */
/* Look through all matching certs for suitable issuer */
for (i = idx; i < sk_X509_OBJECT_num(ctx->ctx->objs); i++) {
pobj = sk_X509_OBJECT_value(ctx->ctx->objs, i);
/* See if we've run past the matches */
if (pobj->type != X509_LU_X509)
break;
if (X509_NAME_cmp(xn, X509_get_subject_name(pobj->data.x509)))
break;
if (ctx->check_issued(ctx, x, pobj->data.x509)) {
*issuer = pobj->data.x509;
ret = 1;
/*
* If times check, exit with match,
* otherwise keep looking. Leave last
* match in issuer so we return nearest
* match if no certificate time is OK.
*/
if (x509_check_cert_time(ctx, *issuer, -1))
break;
}
}
}
CRYPTO_THREAD_unlock(ctx->ctx->lock);
if (*issuer)
X509_up_ref(*issuer);
return ret;
}
int X509_STORE_set_flags(X509_STORE *ctx, unsigned long flags)
{
return X509_VERIFY_PARAM_set_flags(ctx->param, flags);
}
int X509_STORE_set_depth(X509_STORE *ctx, int depth)
{
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
return 1;
}
int X509_STORE_set_purpose(X509_STORE *ctx, int purpose)
{
return X509_VERIFY_PARAM_set_purpose(ctx->param, purpose);
}
int X509_STORE_set_trust(X509_STORE *ctx, int trust)
{
return X509_VERIFY_PARAM_set_trust(ctx->param, trust);
}
int X509_STORE_set1_param(X509_STORE *ctx, X509_VERIFY_PARAM *param)
{
return X509_VERIFY_PARAM_set1(ctx->param, param);
}
X509_VERIFY_PARAM *X509_STORE_get0_param(X509_STORE *ctx)
{
return ctx->param;
}
void X509_STORE_set_verify(X509_STORE *ctx, X509_STORE_CTX_verify_fn verify)
{
ctx->verify = verify;
}
X509_STORE_CTX_verify_fn X509_STORE_get_verify(X509_STORE *ctx)
{
return ctx->verify;
}
void X509_STORE_set_verify_cb(X509_STORE *ctx,
X509_STORE_CTX_verify_cb verify_cb)
{
ctx->verify_cb = verify_cb;
}
X509_STORE_CTX_verify_cb X509_STORE_get_verify_cb(X509_STORE *ctx)
{
return ctx->verify_cb;
}
void X509_STORE_set_get_issuer(X509_STORE *ctx,
X509_STORE_CTX_get_issuer_fn get_issuer)
{
ctx->get_issuer = get_issuer;
}
X509_STORE_CTX_get_issuer_fn X509_STORE_get_get_issuer(X509_STORE *ctx)
{
return ctx->get_issuer;
}
void X509_STORE_set_check_issued(X509_STORE *ctx,
X509_STORE_CTX_check_issued_fn check_issued)
{
ctx->check_issued = check_issued;
}
X509_STORE_CTX_check_issued_fn X509_STORE_get_check_issued(X509_STORE *ctx)
{
return ctx->check_issued;
}
void X509_STORE_set_check_revocation(X509_STORE *ctx,
X509_STORE_CTX_check_revocation_fn check_revocation)
{
ctx->check_revocation = check_revocation;
}
X509_STORE_CTX_check_revocation_fn X509_STORE_get_check_revocation(X509_STORE *ctx)
{
return ctx->check_revocation;
}
void X509_STORE_set_get_crl(X509_STORE *ctx,
X509_STORE_CTX_get_crl_fn get_crl)
{
ctx->get_crl = get_crl;
}
X509_STORE_CTX_get_crl_fn X509_STORE_get_get_crl(X509_STORE *ctx)
{
return ctx->get_crl;
}
void X509_STORE_set_check_crl(X509_STORE *ctx,
X509_STORE_CTX_check_crl_fn check_crl)
{
ctx->check_crl = check_crl;
}
X509_STORE_CTX_check_crl_fn X509_STORE_get_check_crl(X509_STORE *ctx)
{
return ctx->check_crl;
}
void X509_STORE_set_cert_crl(X509_STORE *ctx,
X509_STORE_CTX_cert_crl_fn cert_crl)
{
ctx->cert_crl = cert_crl;
}
X509_STORE_CTX_cert_crl_fn X509_STORE_get_cert_crl(X509_STORE *ctx)
{
return ctx->cert_crl;
}
void X509_STORE_set_check_policy(X509_STORE *ctx,
X509_STORE_CTX_check_policy_fn check_policy)
{
ctx->check_policy = check_policy;
}
X509_STORE_CTX_check_policy_fn X509_STORE_get_check_policy(X509_STORE *ctx)
{
return ctx->check_policy;
}
void X509_STORE_set_lookup_certs(X509_STORE *ctx,
X509_STORE_CTX_lookup_certs_fn lookup_certs)
{
ctx->lookup_certs = lookup_certs;
}
X509_STORE_CTX_lookup_certs_fn X509_STORE_get_lookup_certs(X509_STORE *ctx)
{
return ctx->lookup_certs;
}
void X509_STORE_set_lookup_crls(X509_STORE *ctx,
X509_STORE_CTX_lookup_crls_fn lookup_crls)
{
ctx->lookup_crls = lookup_crls;
}
X509_STORE_CTX_lookup_crls_fn X509_STORE_get_lookup_crls(X509_STORE *ctx)
{
return ctx->lookup_crls;
}
void X509_STORE_set_cleanup(X509_STORE *ctx,
X509_STORE_CTX_cleanup_fn ctx_cleanup)
{
ctx->cleanup = ctx_cleanup;
}
X509_STORE_CTX_cleanup_fn X509_STORE_get_cleanup(X509_STORE *ctx)
{
return ctx->cleanup;
}
int X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data)
{
return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
}
void *X509_STORE_get_ex_data(X509_STORE *ctx, int idx)
{
return CRYPTO_get_ex_data(&ctx->ex_data, idx);
}
X509_STORE *X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx)
{
return ctx->ctx;
}
diff --git a/crypto/x509v3/v3_genn.c b/crypto/x509v3/v3_genn.c
index 85fc3fc24672..23e3bc45653c 100644
--- a/crypto/x509v3/v3_genn.c
+++ b/crypto/x509v3/v3_genn.c
@@ -1,201 +1,201 @@
/*
- * Copyright 1999-2016 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "internal/cryptlib.h"
#include <openssl/asn1t.h>
#include <openssl/conf.h>
#include <openssl/x509v3.h>
ASN1_SEQUENCE(OTHERNAME) = {
ASN1_SIMPLE(OTHERNAME, type_id, ASN1_OBJECT),
/* Maybe have a true ANY DEFINED BY later */
ASN1_EXP(OTHERNAME, value, ASN1_ANY, 0)
} ASN1_SEQUENCE_END(OTHERNAME)
IMPLEMENT_ASN1_FUNCTIONS(OTHERNAME)
ASN1_SEQUENCE(EDIPARTYNAME) = {
ASN1_IMP_OPT(EDIPARTYNAME, nameAssigner, DIRECTORYSTRING, 0),
ASN1_IMP_OPT(EDIPARTYNAME, partyName, DIRECTORYSTRING, 1)
} ASN1_SEQUENCE_END(EDIPARTYNAME)
IMPLEMENT_ASN1_FUNCTIONS(EDIPARTYNAME)
ASN1_CHOICE(GENERAL_NAME) = {
ASN1_IMP(GENERAL_NAME, d.otherName, OTHERNAME, GEN_OTHERNAME),
ASN1_IMP(GENERAL_NAME, d.rfc822Name, ASN1_IA5STRING, GEN_EMAIL),
ASN1_IMP(GENERAL_NAME, d.dNSName, ASN1_IA5STRING, GEN_DNS),
/* Don't decode this */
ASN1_IMP(GENERAL_NAME, d.x400Address, ASN1_SEQUENCE, GEN_X400),
/* X509_NAME is a CHOICE type so use EXPLICIT */
ASN1_EXP(GENERAL_NAME, d.directoryName, X509_NAME, GEN_DIRNAME),
ASN1_IMP(GENERAL_NAME, d.ediPartyName, EDIPARTYNAME, GEN_EDIPARTY),
ASN1_IMP(GENERAL_NAME, d.uniformResourceIdentifier, ASN1_IA5STRING, GEN_URI),
ASN1_IMP(GENERAL_NAME, d.iPAddress, ASN1_OCTET_STRING, GEN_IPADD),
ASN1_IMP(GENERAL_NAME, d.registeredID, ASN1_OBJECT, GEN_RID)
} ASN1_CHOICE_END(GENERAL_NAME)
IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAME)
ASN1_ITEM_TEMPLATE(GENERAL_NAMES) =
ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, GeneralNames, GENERAL_NAME)
ASN1_ITEM_TEMPLATE_END(GENERAL_NAMES)
IMPLEMENT_ASN1_FUNCTIONS(GENERAL_NAMES)
GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a)
{
return (GENERAL_NAME *)ASN1_dup((i2d_of_void *)i2d_GENERAL_NAME,
(d2i_of_void *)d2i_GENERAL_NAME,
(char *)a);
}
/* Returns 0 if they are equal, != 0 otherwise. */
int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b)
{
int result = -1;
if (!a || !b || a->type != b->type)
return -1;
switch (a->type) {
case GEN_X400:
case GEN_EDIPARTY:
result = ASN1_TYPE_cmp(a->d.other, b->d.other);
break;
case GEN_OTHERNAME:
result = OTHERNAME_cmp(a->d.otherName, b->d.otherName);
break;
case GEN_EMAIL:
case GEN_DNS:
case GEN_URI:
result = ASN1_STRING_cmp(a->d.ia5, b->d.ia5);
break;
case GEN_DIRNAME:
result = X509_NAME_cmp(a->d.dirn, b->d.dirn);
break;
case GEN_IPADD:
result = ASN1_OCTET_STRING_cmp(a->d.ip, b->d.ip);
break;
case GEN_RID:
result = OBJ_cmp(a->d.rid, b->d.rid);
break;
}
return result;
}
/* Returns 0 if they are equal, != 0 otherwise. */
int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b)
{
int result = -1;
if (!a || !b)
return -1;
/* Check their type first. */
if ((result = OBJ_cmp(a->type_id, b->type_id)) != 0)
return result;
/* Check the value. */
result = ASN1_TYPE_cmp(a->value, b->value);
return result;
}
void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value)
{
switch (type) {
case GEN_X400:
case GEN_EDIPARTY:
a->d.other = value;
break;
case GEN_OTHERNAME:
a->d.otherName = value;
break;
case GEN_EMAIL:
case GEN_DNS:
case GEN_URI:
a->d.ia5 = value;
break;
case GEN_DIRNAME:
a->d.dirn = value;
break;
case GEN_IPADD:
a->d.ip = value;
break;
case GEN_RID:
a->d.rid = value;
break;
}
a->type = type;
}
-void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype)
+void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype)
{
if (ptype)
*ptype = a->type;
switch (a->type) {
case GEN_X400:
case GEN_EDIPARTY:
return a->d.other;
case GEN_OTHERNAME:
return a->d.otherName;
case GEN_EMAIL:
case GEN_DNS:
case GEN_URI:
return a->d.ia5;
case GEN_DIRNAME:
return a->d.dirn;
case GEN_IPADD:
return a->d.ip;
case GEN_RID:
return a->d.rid;
default:
return NULL;
}
}
int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
ASN1_OBJECT *oid, ASN1_TYPE *value)
{
OTHERNAME *oth;
oth = OTHERNAME_new();
if (oth == NULL)
return 0;
ASN1_TYPE_free(oth->value);
oth->type_id = oid;
oth->value = value;
GENERAL_NAME_set0_value(gen, GEN_OTHERNAME, oth);
return 1;
}
-int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
+int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
ASN1_OBJECT **poid, ASN1_TYPE **pvalue)
{
if (gen->type != GEN_OTHERNAME)
return 0;
if (poid)
*poid = gen->d.otherName->type_id;
if (pvalue)
*pvalue = gen->d.otherName->value;
return 1;
}
diff --git a/doc/man1/genpkey.pod b/doc/man1/genpkey.pod
index 202e531c7e07..1ba54d486619 100644
--- a/doc/man1/genpkey.pod
+++ b/doc/man1/genpkey.pod
@@ -1,335 +1,335 @@
=pod
=head1 NAME
openssl-genpkey,
genpkey - generate a private key
=head1 SYNOPSIS
B<openssl> B<genpkey>
[B<-help>]
[B<-out filename>]
[B<-outform PEM|DER>]
[B<-pass arg>]
[B<-I<cipher>>]
[B<-engine id>]
[B<-paramfile file>]
[B<-algorithm alg>]
[B<-pkeyopt opt:value>]
[B<-genparam>]
[B<-text>]
=head1 DESCRIPTION
The B<genpkey> command generates a private key.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-out filename>
Output the key to the specified file. If this argument is not specified then
standard output is used.
=item B<-outform DER|PEM>
This specifies the output format DER or PEM. The default format is PEM.
=item B<-pass arg>
The output file password source. For more information about the format of B<arg>
see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)>.
=item B<-I<cipher>>
This option encrypts the private key with the supplied cipher. Any algorithm
name accepted by EVP_get_cipherbyname() is acceptable such as B<des3>.
=item B<-engine id>
Specifying an engine (by its unique B<id> string) will cause B<genpkey>
to attempt to obtain a functional reference to the specified engine,
thus initialising it if needed. The engine will then be set as the default
for all available algorithms. If used this option should precede all other
options.
=item B<-algorithm alg>
Public key algorithm to use such as RSA, DSA or DH. If used this option must
precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm>
are mutually exclusive. Engines may add algorithms in addition to the standard
built-in ones.
Valid built-in algorithm names for private key generation are RSA, RSA-PSS, EC,
X25519, X448, ED25519 and ED448.
Valid built-in algorithm names for parameter generation (see the B<-genparam>
option) are DH, DSA and EC.
Note that the algorithm name X9.42 DH may be used as a synonym for the DH
algorithm. These are identical and do not indicate the type of parameters that
will be generated. Use the B<dh_paramgen_type> option to indicate whether PKCS#3
or X9.42 DH parameters are required. See L<DH Parameter Generation Options>
below for more details.
=item B<-pkeyopt opt:value>
Set the public key algorithm option B<opt> to B<value>. The precise set of
options supported depends on the public key algorithm used and its
implementation. See L<KEY GENERATION OPTIONS> and
L<PARAMETER GENERATION OPTIONS> below for more details.
=item B<-genparam>
Generate a set of parameters instead of a private key. If used this option must
precede any B<-algorithm>, B<-paramfile> or B<-pkeyopt> options.
=item B<-paramfile filename>
Some public key algorithms generate a private key based on a set of parameters.
They can be supplied using this option. If this option is used the public key
algorithm used is determined by the parameters. If used this option must
precede any B<-pkeyopt> options. The options B<-paramfile> and B<-algorithm>
are mutually exclusive.
=item B<-text>
Print an (unencrypted) text representation of private and public keys and
parameters along with the PEM or DER structure.
=back
=head1 KEY GENERATION OPTIONS
The options supported by each algorithm and indeed each implementation of an
algorithm can vary. The options for the OpenSSL implementations are detailed
below. There are no key generation options defined for the X25519, X448, ED25519
or ED448 algorithms.
=head2 RSA Key Generation Options
=over 4
=item B<rsa_keygen_bits:numbits>
-The number of bits in the generated key. If not specified 1024 is used.
+The number of bits in the generated key. If not specified 2048 is used.
=item B<rsa_keygen_primes:numprimes>
The number of primes in the generated key. If not specified 2 is used.
=item B<rsa_keygen_pubexp:value>
The RSA public exponent value. This can be a large decimal or
hexadecimal value if preceded by B<0x>. Default value is 65537.
=back
=head2 RSA-PSS Key Generation Options
Note: by default an B<RSA-PSS> key has no parameter restrictions.
=over 4
=item B<rsa_keygen_bits:numbits>, B<rsa_keygen_primes:numprimes>, B<rsa_keygen_pubexp:value>
These options have the same meaning as the B<RSA> algorithm.
=item B<rsa_pss_keygen_md:digest>
If set the key is restricted and can only use B<digest> for signing.
=item B<rsa_pss_keygen_mgf1_md:digest>
If set the key is restricted and can only use B<digest> as it's MGF1
parameter.
=item B<rsa_pss_keygen_saltlen:len>
If set the key is restricted and B<len> specifies the minimum salt length.
=back
=head2 EC Key Generation Options
The EC key generation options can also be used for parameter generation.
=over 4
=item B<ec_paramgen_curve:curve>
The EC curve to use. OpenSSL supports NIST curve names such as "P-256".
=item B<ec_param_enc:encoding>
The encoding to use for parameters. The "encoding" parameter must be either
"named_curve" or "explicit". The default value is "named_curve".
=back
=head1 PARAMETER GENERATION OPTIONS
The options supported by each algorithm and indeed each implementation of an
algorithm can vary. The options for the OpenSSL implementations are detailed
below.
=head2 DSA Parameter Generation Options
=over 4
=item B<dsa_paramgen_bits:numbits>
-The number of bits in the generated prime. If not specified 1024 is used.
+The number of bits in the generated prime. If not specified 2048 is used.
=item B<dsa_paramgen_q_bits:numbits>
The number of bits in the q parameter. Must be one of 160, 224 or 256. If not
-specified 160 is used.
+specified 224 is used.
=item B<dsa_paramgen_md:digest>
The digest to use during parameter generation. Must be one of B<sha1>, B<sha224>
or B<sha256>. If set, then the number of bits in B<q> will match the output size
of the specified digest and the B<dsa_paramgen_q_bits> parameter will be
ignored. If not set, then a digest will be used that gives an output matching
the number of bits in B<q>, i.e. B<sha1> if q length is 160, B<sha224> if it 224
or B<sha256> if it is 256.
=back
=head2 DH Parameter Generation Options
=over 4
=item B<dh_paramgen_prime_len:numbits>
-The number of bits in the prime parameter B<p>. The default is 1024.
+The number of bits in the prime parameter B<p>. The default is 2048.
=item B<dh_paramgen_subprime_len:numbits>
The number of bits in the sub prime parameter B<q>. The default is 256 if the
prime is at least 2048 bits long or 160 otherwise. Only relevant if used in
conjunction with the B<dh_paramgen_type> option to generate X9.42 DH parameters.
=item B<dh_paramgen_generator:value>
The value to use for the generator B<g>. The default is 2.
=item B<dh_paramgen_type:value>
The type of DH parameters to generate. Use 0 for PKCS#3 DH and 1 for X9.42 DH.
The default is 0.
=item B<dh_rfc5114:num>
If this option is set, then the appropriate RFC5114 parameters are used
instead of generating new parameters. The value B<num> can take the
values 1, 2 or 3 corresponding to RFC5114 DH parameters consisting of
1024 bit group with 160 bit subgroup, 2048 bit group with 224 bit subgroup
and 2048 bit group with 256 bit subgroup as mentioned in RFC5114 sections
2.1, 2.2 and 2.3 respectively. If present this overrides all other DH parameter
options.
=back
=head2 EC Parameter Generation Options
The EC parameter generation options are the same as for key generation. See
L<EC Key Generation Options> above.
=head1 NOTES
The use of the genpkey program is encouraged over the algorithm specific
utilities because additional algorithm options and ENGINE provided algorithms
can be used.
=head1 EXAMPLES
Generate an RSA private key using default parameters:
openssl genpkey -algorithm RSA -out key.pem
Encrypt output private key using 128 bit AES and the passphrase "hello":
openssl genpkey -algorithm RSA -out key.pem -aes-128-cbc -pass pass:hello
Generate a 2048 bit RSA key using 3 as the public exponent:
openssl genpkey -algorithm RSA -out key.pem \
-pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:3
Generate 2048 bit DSA parameters:
openssl genpkey -genparam -algorithm DSA -out dsap.pem \
-pkeyopt dsa_paramgen_bits:2048
Generate DSA key from parameters:
openssl genpkey -paramfile dsap.pem -out dsakey.pem
Generate 2048 bit DH parameters:
openssl genpkey -genparam -algorithm DH -out dhp.pem \
-pkeyopt dh_paramgen_prime_len:2048
Generate 2048 bit X9.42 DH parameters:
openssl genpkey -genparam -algorithm DH -out dhpx.pem \
-pkeyopt dh_paramgen_prime_len:2048 \
-pkeyopt dh_paramgen_type:1
Output RFC5114 2048 bit DH parameters with 224 bit subgroup:
openssl genpkey -genparam -algorithm DH -out dhp.pem -pkeyopt dh_rfc5114:2
Generate DH key from parameters:
openssl genpkey -paramfile dhp.pem -out dhkey.pem
Generate EC parameters:
openssl genpkey -genparam -algorithm EC -out ecp.pem \
-pkeyopt ec_paramgen_curve:secp384r1 \
-pkeyopt ec_param_enc:named_curve
Generate EC key from parameters:
openssl genpkey -paramfile ecp.pem -out eckey.pem
Generate EC key directly:
openssl genpkey -algorithm EC -out eckey.pem \
-pkeyopt ec_paramgen_curve:P-384 \
-pkeyopt ec_param_enc:named_curve
Generate an X25519 private key:
openssl genpkey -algorithm X25519 -out xkey.pem
Generate an ED448 private key:
openssl genpkey -algorithm ED448 -out xkey.pem
=head1 HISTORY
The ability to use NIST curve names, and to generate an EC key directly,
were added in OpenSSL 1.0.2.
The ability to generate X25519 keys was added in OpenSSL 1.1.0.
The ability to generate X448, ED25519 and ED448 keys was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man1/pkeyutl.pod b/doc/man1/pkeyutl.pod
index 664dbef3598b..dffc449a4e0e 100644
--- a/doc/man1/pkeyutl.pod
+++ b/doc/man1/pkeyutl.pod
@@ -1,338 +1,337 @@
=pod
=head1 NAME
openssl-pkeyutl,
pkeyutl - public key algorithm utility
=head1 SYNOPSIS
B<openssl> B<pkeyutl>
[B<-help>]
[B<-in file>]
[B<-out file>]
[B<-sigfile file>]
[B<-inkey file>]
[B<-keyform PEM|DER|ENGINE>]
[B<-passin arg>]
[B<-peerkey file>]
[B<-peerform PEM|DER|ENGINE>]
[B<-pubin>]
[B<-certin>]
[B<-rev>]
[B<-sign>]
[B<-verify>]
[B<-verifyrecover>]
[B<-encrypt>]
[B<-decrypt>]
[B<-derive>]
[B<-kdf algorithm>]
[B<-kdflen length>]
[B<-pkeyopt opt:value>]
[B<-hexdump>]
[B<-asn1parse>]
[B<-rand file...>]
[B<-writerand file>]
[B<-engine id>]
[B<-engine_impl>]
=head1 DESCRIPTION
The B<pkeyutl> command can be used to perform low level public key operations
using any supported algorithm.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-in filename>
This specifies the input filename to read data from or standard input
if this option is not specified.
=item B<-out filename>
Specifies the output filename to write to or standard output by
default.
=item B<-sigfile file>
Signature file, required for B<verify> operations only
=item B<-inkey file>
The input key file, by default it should be a private key.
=item B<-keyform PEM|DER|ENGINE>
The key format PEM, DER or ENGINE. Default is PEM.
=item B<-passin arg>
The input key password source. For more information about the format of B<arg>
see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)>.
=item B<-peerkey file>
The peer key file, used by key derivation (agreement) operations.
=item B<-peerform PEM|DER|ENGINE>
The peer key format PEM, DER or ENGINE. Default is PEM.
=item B<-pubin>
The input file is a public key.
=item B<-certin>
The input is a certificate containing a public key.
=item B<-rev>
Reverse the order of the input buffer. This is useful for some libraries
(such as CryptoAPI) which represent the buffer in little endian format.
=item B<-sign>
Sign the input data (which must be a hash) and output the signed result. This
requires a private key.
=item B<-verify>
Verify the input data (which must be a hash) against the signature file and
indicate if the verification succeeded or failed.
=item B<-verifyrecover>
Verify the input data (which must be a hash) and output the recovered data.
=item B<-encrypt>
Encrypt the input data using a public key.
=item B<-decrypt>
Decrypt the input data using a private key.
=item B<-derive>
Derive a shared secret using the peer key.
=item B<-kdf algorithm>
Use key derivation function B<algorithm>. The supported algorithms are
at present B<TLS1-PRF> and B<HKDF>.
Note: additional parameters and the KDF output length will normally have to be
set for this to work.
See L<EVP_PKEY_CTX_set_hkdf_md(3)> and L<EVP_PKEY_CTX_set_tls1_prf_md(3)>
for the supported string parameters of each algorithm.
=item B<-kdflen length>
Set the output length for KDF.
=item B<-pkeyopt opt:value>
Public key options specified as opt:value. See NOTES below for more details.
=item B<-hexdump>
hex dump the output data.
=item B<-asn1parse>
Parse the ASN.1 output data, this is useful when combined with the
B<-verifyrecover> option when an ASN1 structure is signed.
=item B<-rand file...>
A file or files containing random data used to seed the random number
generator.
Multiple files can be specified separated by an OS-dependent character.
The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
all others.
=item [B<-writerand file>]
Writes random data to the specified I<file> upon exit.
This can be used with a subsequent B<-rand> flag.
=item B<-engine id>
Specifying an engine (by its unique B<id> string) will cause B<pkeyutl>
to attempt to obtain a functional reference to the specified engine,
thus initialising it if needed. The engine will then be set as the default
for all available algorithms.
=item B<-engine_impl>
When used with the B<-engine> option, it specifies to also use
engine B<id> for crypto operations.
=back
=head1 NOTES
The operations and options supported vary according to the key algorithm
and its implementation. The OpenSSL operations and options are indicated below.
Unless otherwise mentioned all algorithms support the B<digest:alg> option
which specifies the digest in use for sign, verify and verifyrecover operations.
The value B<alg> should represent a digest name as used in the
EVP_get_digestbyname() function for example B<sha1>. This value is not used to
hash the input data. It is used (by some algorithms) for sanity-checking the
lengths of data passed in to the B<pkeyutl> and for creating the structures that
make up the signature (e.g. B<DigestInfo> in RSASSA PKCS#1 v1.5 signatures).
This utility does not hash the input data but rather it will use the data
directly as input to the signature algorithm. Depending on the key type,
signature type, and mode of padding, the maximum acceptable lengths of input
data differ. The signed data can't be longer than the key modulus with RSA. In
case of ECDSA and DSA the data shouldn't be longer than the field
size, otherwise it will be silently truncated to the field size. In any event
the input size must not be larger than the largest supported digest size.
In other words, if the value of digest is B<sha1> the input should be the 20
bytes long binary encoding of the SHA-1 hash function output.
The Ed25519 and Ed448 signature algorithms are not supported by this utility.
They accept non-hashed input, but this utility can only be used to sign hashed
input.
=head1 RSA ALGORITHM
The RSA algorithm generally supports the encrypt, decrypt, sign,
verify and verifyrecover operations. However, some padding modes
support only a subset of these operations. The following additional
B<pkeyopt> values are supported:
=over 4
=item B<rsa_padding_mode:mode>
This sets the RSA padding mode. Acceptable values for B<mode> are B<pkcs1> for
PKCS#1 padding, B<sslv23> for SSLv23 padding, B<none> for no padding, B<oaep>
for B<OAEP> mode, B<x931> for X9.31 mode and B<pss> for PSS.
In PKCS#1 padding if the message digest is not set then the supplied data is
signed or verified directly instead of using a B<DigestInfo> structure. If a
digest is set then the a B<DigestInfo> structure is used and its the length
must correspond to the digest type.
For B<oaep> mode only encryption and decryption is supported.
For B<x931> if the digest type is set it is used to format the block data
otherwise the first byte is used to specify the X9.31 digest ID. Sign,
verify and verifyrecover are can be performed in this mode.
For B<pss> mode only sign and verify are supported and the digest type must be
specified.
=item B<rsa_pss_saltlen:len>
For B<pss> mode only this option specifies the salt length. Three special
values are supported: "digest" sets the salt length to the digest length,
"max" sets the salt length to the maximum permissible value. When verifying
"auto" causes the salt length to be automatically determined based on the
B<PSS> block structure.
=item B<rsa_mgf1_md:digest>
For PSS and OAEP padding sets the MGF1 digest. If the MGF1 digest is not
explicitly set in PSS mode then the signing digest is used.
=back
=head1 RSA-PSS ALGORITHM
The RSA-PSS algorithm is a restricted version of the RSA algorithm which only
supports the sign and verify operations with PSS padding. The following
additional B<pkeyopt> values are supported:
=over 4
=item B<rsa_padding_mode:mode>, B<rsa_pss_saltlen:len>, B<rsa_mgf1_md:digest>
These have the same meaning as the B<RSA> algorithm with some additional
restrictions. The padding mode can only be set to B<pss> which is the
default value.
If the key has parameter restrictions than the digest, MGF1
digest and salt length are set to the values specified in the parameters.
The digest and MG cannot be changed and the salt length cannot be set to a
value less than the minimum restriction.
=back
=head1 DSA ALGORITHM
The DSA algorithm supports signing and verification operations only. Currently
-there are no additional options other than B<digest>. Only the SHA1
-digest can be used and this digest is assumed by default.
+there are no additional B<-pkeyopt> options other than B<digest>. The SHA1
+digest is assumed by default.
=head1 DH ALGORITHM
The DH algorithm only supports the derivation operation and no additional
-options.
+B<-pkeyopt> options.
=head1 EC ALGORITHM
The EC algorithm supports sign, verify and derive operations. The sign and
-verify operations use ECDSA and derive uses ECDH. Currently there are no
-additional options other than B<digest>. Only the SHA1 digest can be used and
-this digest is assumed by default.
+verify operations use ECDSA and derive uses ECDH. SHA1 is assumed by default for
+the B<-pkeyopt> B<digest> option.
=head1 X25519 and X448 ALGORITHMS
The X25519 and X448 algorithms support key derivation only. Currently there are
no additional options.
=head1 EXAMPLES
Sign some data using a private key:
openssl pkeyutl -sign -in file -inkey key.pem -out sig
Recover the signed data (e.g. if an RSA key is used):
openssl pkeyutl -verifyrecover -in sig -inkey key.pem
Verify the signature (e.g. a DSA key):
openssl pkeyutl -verify -in file -sigfile sig -inkey key.pem
Sign data using a message digest value (this is currently only valid for RSA):
openssl pkeyutl -sign -in file -inkey key.pem -out sig -pkeyopt digest:sha256
Derive a shared secret value:
openssl pkeyutl -derive -inkey key.pem -peerkey pubkey.pem -out secret
Hexdump 48 bytes of TLS1 PRF using digest B<SHA256> and shared secret and
seed consisting of the single byte 0xFF:
openssl pkeyutl -kdf TLS1-PRF -kdflen 48 -pkeyopt md:SHA256 \
-pkeyopt hexsecret:ff -pkeyopt hexseed:ff -hexdump
=head1 SEE ALSO
L<genpkey(1)>, L<pkey(1)>, L<rsautl(1)>
L<dgst(1)>, L<rsa(1)>, L<genrsa(1)>,
L<EVP_PKEY_CTX_set_hkdf_md(3)>, L<EVP_PKEY_CTX_set_tls1_prf_md(3)>
=head1 COPYRIGHT
-Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man1/s_client.pod b/doc/man1/s_client.pod
index 81d516ace146..15752b5e1613 100644
--- a/doc/man1/s_client.pod
+++ b/doc/man1/s_client.pod
@@ -1,838 +1,838 @@
=pod
=head1 NAME
openssl-s_client,
s_client - SSL/TLS client program
=head1 SYNOPSIS
B<openssl> B<s_client>
[B<-help>]
[B<-connect host:port>]
[B<-bind host:port>]
[B<-proxy host:port>]
[B<-unix path>]
[B<-4>]
[B<-6>]
[B<-servername name>]
[B<-noservername>]
[B<-verify depth>]
[B<-verify_return_error>]
[B<-cert filename>]
[B<-certform DER|PEM>]
[B<-key filename>]
[B<-keyform DER|PEM>]
[B<-cert_chain filename>]
[B<-build_chain>]
[B<-xkey>]
[B<-xcert>]
[B<-xchain>]
[B<-xchain_build>]
[B<-xcertform PEM|DER>]
[B<-xkeyform PEM|DER>]
[B<-pass arg>]
[B<-CApath directory>]
[B<-CAfile filename>]
[B<-chainCApath directory>]
[B<-chainCAfile filename>]
[B<-no-CAfile>]
[B<-no-CApath>]
[B<-requestCAfile filename>]
[B<-dane_tlsa_domain domain>]
[B<-dane_tlsa_rrdata rrdata>]
[B<-dane_ee_no_namechecks>]
[B<-attime timestamp>]
[B<-check_ss_sig>]
[B<-crl_check>]
[B<-crl_check_all>]
[B<-explicit_policy>]
[B<-extended_crl>]
[B<-ignore_critical>]
[B<-inhibit_any>]
[B<-inhibit_map>]
[B<-no_check_time>]
[B<-partial_chain>]
[B<-policy arg>]
[B<-policy_check>]
[B<-policy_print>]
[B<-purpose purpose>]
[B<-suiteB_128>]
[B<-suiteB_128_only>]
[B<-suiteB_192>]
[B<-trusted_first>]
[B<-no_alt_chains>]
[B<-use_deltas>]
[B<-auth_level num>]
[B<-nameopt option>]
[B<-verify_depth num>]
[B<-verify_email email>]
[B<-verify_hostname hostname>]
[B<-verify_ip ip>]
[B<-verify_name name>]
[B<-build_chain>]
[B<-x509_strict>]
[B<-reconnect>]
[B<-showcerts>]
[B<-debug>]
[B<-msg>]
[B<-nbio_test>]
[B<-state>]
[B<-nbio>]
[B<-crlf>]
[B<-ign_eof>]
[B<-no_ign_eof>]
[B<-psk_identity identity>]
[B<-psk key>]
[B<-psk_session file>]
[B<-quiet>]
[B<-ssl3>]
[B<-tls1>]
[B<-tls1_1>]
[B<-tls1_2>]
[B<-tls1_3>]
[B<-no_ssl3>]
[B<-no_tls1>]
[B<-no_tls1_1>]
[B<-no_tls1_2>]
[B<-no_tls1_3>]
[B<-dtls>]
[B<-dtls1>]
[B<-dtls1_2>]
[B<-sctp>]
[B<-sctp_label_bug>]
[B<-fallback_scsv>]
[B<-async>]
[B<-max_send_frag>]
[B<-split_send_frag>]
[B<-max_pipelines>]
[B<-read_buf>]
[B<-bugs>]
[B<-comp>]
[B<-no_comp>]
[B<-allow_no_dhe_kex>]
[B<-sigalgs sigalglist>]
[B<-curves curvelist>]
[B<-cipher cipherlist>]
[B<-ciphersuites val>]
[B<-serverpref>]
[B<-starttls protocol>]
[B<-xmpphost hostname>]
[B<-name hostname>]
[B<-engine id>]
[B<-tlsextdebug>]
[B<-no_ticket>]
[B<-sess_out filename>]
[B<-sess_in filename>]
[B<-rand file...>]
[B<-writerand file>]
[B<-serverinfo types>]
[B<-status>]
[B<-alpn protocols>]
[B<-nextprotoneg protocols>]
[B<-ct>]
[B<-noct>]
[B<-ctlogfile>]
[B<-keylogfile file>]
[B<-early_data file>]
[B<-enable_pha>]
[B<target>]
=head1 DESCRIPTION
The B<s_client> command implements a generic SSL/TLS client which connects
to a remote host using SSL/TLS. It is a I<very> useful diagnostic tool for
SSL servers.
=head1 OPTIONS
In addition to the options below the B<s_client> utility also supports the
common and client only options documented in the
in the "Supported Command Line Commands" section of the L<SSL_CONF_cmd(3)>
manual page.
=over 4
=item B<-help>
Print out a usage message.
=item B<-connect host:port>
This specifies the host and optional port to connect to. It is possible to
select the host and port using the optional target positional argument instead.
If neither this nor the target positional argument are specified then an attempt
is made to connect to the local host on port 4433.
=item B<-bind host:port>]
This specifies the host address and or port to bind as the source for the
connection. For Unix-domain sockets the port is ignored and the host is
used as the source socket address.
=item B<-proxy host:port>
When used with the B<-connect> flag, the program uses the host and port
specified with this flag and issues an HTTP CONNECT command to connect
to the desired server.
=item B<-unix path>
Connect over the specified Unix-domain socket.
=item B<-4>
Use IPv4 only.
=item B<-6>
Use IPv6 only.
=item B<-servername name>
Set the TLS SNI (Server Name Indication) extension in the ClientHello message to
the given value.
If B<-servername> is not provided, the TLS SNI extension will be populated with
the name given to B<-connect> if it follows a DNS name format. If B<-connect> is
not provided either, the SNI is set to "localhost".
This is the default since OpenSSL 1.1.1.
Even though SNI should normally be a DNS name and not an IP address, if
B<-servername> is provided then that name will be sent, regardless of whether
it is a DNS name or not.
-This option cannot be used in conjuction with B<-noservername>.
+This option cannot be used in conjunction with B<-noservername>.
=item B<-noservername>
Suppresses sending of the SNI (Server Name Indication) extension in the
ClientHello message. Cannot be used in conjunction with the B<-servername> or
<-dane_tlsa_domain> options.
=item B<-cert certname>
The certificate to use, if one is requested by the server. The default is
not to use a certificate.
=item B<-certform format>
The certificate format to use: DER or PEM. PEM is the default.
=item B<-key keyfile>
The private key to use. If not specified then the certificate file will
be used.
=item B<-keyform format>
The private format to use: DER or PEM. PEM is the default.
=item B<-cert_chain>
A file containing trusted certificates to use when attempting to build the
client/server certificate chain related to the certificate specified via the
B<-cert> option.
=item B<-build_chain>
Specify whether the application should build the certificate chain to be
provided to the server.
=item B<-xkey infile>, B<-xcert infile>, B<-xchain>
Specify an extra certificate, private key and certificate chain. These behave
in the same manner as the B<-cert>, B<-key> and B<-cert_chain> options. When
specified, the callback returning the first valid chain will be in use by the
client.
=item B<-xchain_build>
Specify whether the application should build the certificate chain to be
provided to the server for the extra certificates provided via B<-xkey infile>,
B<-xcert infile>, B<-xchain> options.
=item B<-xcertform PEM|DER>, B<-xkeyform PEM|DER>
Extra certificate and private key format respectively.
=item B<-pass arg>
the private key password source. For more information about the format of B<arg>
see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)>.
=item B<-verify depth>
The verify depth to use. This specifies the maximum length of the
server certificate chain and turns on server certificate verification.
Currently the verify operation continues after errors so all the problems
with a certificate chain can be seen. As a side effect the connection
will never fail due to a server certificate verify failure.
=item B<-verify_return_error>
Return verification errors instead of continuing. This will typically
abort the handshake with a fatal error.
=item B<-nameopt option>
Option which determines how the subject or issuer names are displayed. The
B<option> argument can be a single option or multiple options separated by
commas. Alternatively the B<-nameopt> switch may be used more than once to
set multiple options. See the L<x509(1)> manual page for details.
=item B<-CApath directory>
The directory to use for server certificate verification. This directory
must be in "hash format", see L<verify(1)> for more information. These are
also used when building the client certificate chain.
=item B<-CAfile file>
A file containing trusted certificates to use during server authentication
and to use when attempting to build the client certificate chain.
=item B<-chainCApath directory>
The directory to use for building the chain provided to the server. This
directory must be in "hash format", see L<verify(1)> for more information.
=item B<-chainCAfile file>
A file containing trusted certificates to use when attempting to build the
client certificate chain.
=item B<-no-CAfile>
Do not load the trusted CA certificates from the default file location
=item B<-no-CApath>
Do not load the trusted CA certificates from the default directory location
=item B<-requestCAfile file>
A file containing a list of certificates whose subject names will be sent
to the server in the B<certificate_authorities> extension. Only supported
for TLS 1.3
=item B<-dane_tlsa_domain domain>
Enable RFC6698/RFC7671 DANE TLSA authentication and specify the
TLSA base domain which becomes the default SNI hint and the primary
reference identifier for hostname checks. This must be used in
combination with at least one instance of the B<-dane_tlsa_rrdata>
option below.
When DANE authentication succeeds, the diagnostic output will include
the lowest (closest to 0) depth at which a TLSA record authenticated
a chain certificate. When that TLSA record is a "2 1 0" trust
anchor public key that signed (rather than matched) the top-most
certificate of the chain, the result is reported as "TA public key
verified". Otherwise, either the TLSA record "matched TA certificate"
at a positive depth or else "matched EE certificate" at depth 0.
=item B<-dane_tlsa_rrdata rrdata>
Use one or more times to specify the RRDATA fields of the DANE TLSA
RRset associated with the target service. The B<rrdata> value is
specied in "presentation form", that is four whitespace separated
fields that specify the usage, selector, matching type and associated
data, with the last of these encoded in hexadecimal. Optional
whitespace is ignored in the associated data field. For example:
$ openssl s_client -brief -starttls smtp \
-connect smtp.example.com:25 \
-dane_tlsa_domain smtp.example.com \
-dane_tlsa_rrdata "2 1 1
B111DD8A1C2091A89BD4FD60C57F0716CCE50FEEFF8137CDBEE0326E 02CF362B" \
-dane_tlsa_rrdata "2 1 1
60B87575447DCBA2A36B7D11AC09FB24A9DB406FEE12D2CC90180517 616E8A18"
...
Verification: OK
Verified peername: smtp.example.com
DANE TLSA 2 1 1 ...ee12d2cc90180517616e8a18 matched TA certificate at depth 1
...
=item B<-dane_ee_no_namechecks>
This disables server name checks when authenticating via DANE-EE(3) TLSA
records.
For some applications, primarily web browsers, it is not safe to disable name
checks due to "unknown key share" attacks, in which a malicious server can
convince a client that a connection to a victim server is instead a secure
connection to the malicious server.
The malicious server may then be able to violate cross-origin scripting
restrictions.
Thus, despite the text of RFC7671, name checks are by default enabled for
DANE-EE(3) TLSA records, and can be disabled in applications where it is safe
to do so.
In particular, SMTP and XMPP clients should set this option as SRV and MX
records already make it possible for a remote domain to redirect client
connections to any server of its choice, and in any case SMTP and XMPP clients
do not execute scripts downloaded from remote servers.
=item B<-attime>, B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,
B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
B<-inhibit_map>, B<-no_alt_chains>, B<-no_check_time>, B<-partial_chain>, B<-policy>,
B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
B<-verify_ip>, B<-verify_name>, B<-x509_strict>
Set various certificate chain validation options. See the
L<verify(1)> manual page for details.
=item B<-reconnect>
Reconnects to the same server 5 times using the same session ID, this can
be used as a test that session caching is working.
=item B<-showcerts>
Displays the server certificate list as sent by the server: it only consists of
certificates the server has sent (in the order the server has sent them). It is
B<not> a verified chain.
=item B<-prexit>
Print session information when the program exits. This will always attempt
to print out information even if the connection fails. Normally information
will only be printed out once if the connection succeeds. This option is useful
because the cipher in use may be renegotiated or the connection may fail
because a client certificate is required or is requested only after an
attempt is made to access a certain URL. Note: the output produced by this
option is not always accurate because a connection might never have been
established.
=item B<-state>
Prints out the SSL session states.
=item B<-debug>
Print extensive debugging information including a hex dump of all traffic.
=item B<-msg>
Show all protocol messages with hex dump.
=item B<-trace>
Show verbose trace output of protocol messages. OpenSSL needs to be compiled
with B<enable-ssl-trace> for this option to work.
=item B<-msgfile>
File to send output of B<-msg> or B<-trace> to, default standard output.
=item B<-nbio_test>
Tests non-blocking I/O
=item B<-nbio>
Turns on non-blocking I/O
=item B<-crlf>
This option translated a line feed from the terminal into CR+LF as required
by some servers.
=item B<-ign_eof>
Inhibit shutting down the connection when end of file is reached in the
input.
=item B<-quiet>
Inhibit printing of session and certificate information. This implicitly
turns on B<-ign_eof> as well.
=item B<-no_ign_eof>
Shut down the connection when end of file is reached in the input.
Can be used to override the implicit B<-ign_eof> after B<-quiet>.
=item B<-psk_identity identity>
Use the PSK identity B<identity> when using a PSK cipher suite.
The default value is "Client_identity" (without the quotes).
=item B<-psk key>
Use the PSK key B<key> when using a PSK cipher suite. The key is
given as a hexadecimal number without leading 0x, for example -psk
1a2b3c4d.
This option must be provided in order to use a PSK cipher.
=item B<-psk_session file>
Use the pem encoded SSL_SESSION data stored in B<file> as the basis of a PSK.
Note that this will only work if TLSv1.3 is negotiated.
=item B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>, B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
These options require or disable the use of the specified SSL or TLS protocols.
By default B<s_client> will negotiate the highest mutually supported protocol
version.
When a specific TLS version is required, only that version will be offered to
and accepted from the server.
Note that not all protocols and flags may be available, depending on how
OpenSSL was built.
=item B<-dtls>, B<-dtls1>, B<-dtls1_2>
These options make B<s_client> use DTLS protocols instead of TLS.
With B<-dtls>, B<s_client> will negotiate any supported DTLS protocol version,
whilst B<-dtls1> and B<-dtls1_2> will only support DTLS1.0 and DTLS1.2
respectively.
=item B<-sctp>
Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
available where OpenSSL has support for SCTP enabled.
=item B<-sctp_label_bug>
Use the incorrect behaviour of older OpenSSL implementations when computing
endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
older broken implementations but breaks interoperability with correct
implementations. Must be used in conjunction with B<-sctp>. This option is only
available where OpenSSL has support for SCTP enabled.
=item B<-fallback_scsv>
Send TLS_FALLBACK_SCSV in the ClientHello.
=item B<-async>
Switch on asynchronous mode. Cryptographic operations will be performed
asynchronously. This will only have an effect if an asynchronous capable engine
is also used via the B<-engine> option. For test purposes the dummy async engine
(dasync) can be used (if available).
=item B<-max_send_frag int>
The maximum size of data fragment to send.
See L<SSL_CTX_set_max_send_fragment(3)> for further information.
=item B<-split_send_frag int>
The size used to split data for encrypt pipelines. If more data is written in
one go than this value then it will be split into multiple pipelines, up to the
maximum number of pipelines defined by max_pipelines. This only has an effect if
a suitable cipher suite has been negotiated, an engine that supports pipelining
has been loaded, and max_pipelines is greater than 1. See
L<SSL_CTX_set_split_send_fragment(3)> for further information.
=item B<-max_pipelines int>
The maximum number of encrypt/decrypt pipelines to be used. This will only have
an effect if an engine has been loaded that supports pipelining (e.g. the dasync
engine) and a suitable cipher suite has been negotiated. The default value is 1.
See L<SSL_CTX_set_max_pipelines(3)> for further information.
=item B<-read_buf int>
The default read buffer size to be used for connections. This will only have an
effect if the buffer size is larger than the size that would otherwise be used
and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
further information).
=item B<-bugs>
-There are several known bug in SSL and TLS implementations. Adding this
+There are several known bugs in SSL and TLS implementations. Adding this
option enables various workarounds.
=item B<-comp>
Enables support for SSL/TLS compression.
This option was introduced in OpenSSL 1.1.0.
TLS compression is not recommended and is off by default as of
OpenSSL 1.1.0.
=item B<-no_comp>
Disables support for SSL/TLS compression.
TLS compression is not recommended and is off by default as of
OpenSSL 1.1.0.
=item B<-brief>
Only provide a brief summary of connection parameters instead of the
normal verbose output.
=item B<-sigalgs sigalglist>
Specifies the list of signature algorithms that are sent by the client.
The server selects one entry in the list based on its preferences.
For example strings, see L<SSL_CTX_set1_sigalgs(3)>
=item B<-curves curvelist>
Specifies the list of supported curves to be sent by the client. The curve is
ultimately selected by the server. For a list of all curves, use:
$ openssl ecparam -list_curves
=item B<-cipher cipherlist>
This allows the TLSv1.2 and below cipher list sent by the client to be modified.
This list will be combined with any TLSv1.3 ciphersuites that have been
configured. Although the server determines which ciphersuite is used it should
take the first supported cipher in the list sent by the client. See the
B<ciphers> command for more information.
=item B<-ciphersuites val>
This allows the TLSv1.3 ciphersuites sent by the client to be modified. This
list will be combined with any TLSv1.2 and below ciphersuites that have been
configured. Although the server determines which cipher suite is used it should
take the first supported cipher in the list sent by the client. See the
B<ciphers> command for more information. The format for this list is a simple
colon (":") separated list of TLSv1.3 ciphersuite names.
=item B<-starttls protocol>
Send the protocol-specific message(s) to switch to TLS for communication.
B<protocol> is a keyword for the intended protocol. Currently, the only
supported keywords are "smtp", "pop3", "imap", "ftp", "xmpp", "xmpp-server",
"irc", "postgres", "mysql", "lmtp", "nntp", "sieve" and "ldap".
=item B<-xmpphost hostname>
This option, when used with "-starttls xmpp" or "-starttls xmpp-server",
specifies the host for the "to" attribute of the stream element.
If this option is not specified, then the host specified with "-connect"
will be used.
This option is an alias of the B<-name> option for "xmpp" and "xmpp-server".
=item B<-name hostname>
This option is used to specify hostname information for various protocols
used with B<-starttls> option. Currently only "xmpp", "xmpp-server",
"smtp" and "lmtp" can utilize this B<-name> option.
If this option is used with "-starttls xmpp" or "-starttls xmpp-server",
if specifies the host for the "to" attribute of the stream element. If this
option is not specified, then the host specified with "-connect" will be used.
If this option is used with "-starttls lmtp" or "-starttls smtp", it specifies
the name to use in the "LMTP LHLO" or "SMTP EHLO" message, respectively. If
this option is not specified, then "mail.example.com" will be used.
=item B<-tlsextdebug>
Print out a hex dump of any TLS extensions received from the server.
=item B<-no_ticket>
Disable RFC4507bis session ticket support.
=item B<-sess_out filename>
Output SSL session to B<filename>.
=item B<-sess_in sess.pem>
Load SSL session from B<filename>. The client will attempt to resume a
connection from this session.
=item B<-engine id>
Specifying an engine (by its unique B<id> string) will cause B<s_client>
to attempt to obtain a functional reference to the specified engine,
thus initialising it if needed. The engine will then be set as the default
for all available algorithms.
=item B<-rand file...>
A file or files containing random data used to seed the random number
generator.
Multiple files can be specified separated by an OS-dependent character.
The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
all others.
=item [B<-writerand file>]
Writes random data to the specified I<file> upon exit.
This can be used with a subsequent B<-rand> flag.
=item B<-serverinfo types>
A list of comma-separated TLS Extension Types (numbers between 0 and
65535). Each type will be sent as an empty ClientHello TLS Extension.
The server's response (if any) will be encoded and displayed as a PEM
file.
=item B<-status>
Sends a certificate status request to the server (OCSP stapling). The server
response (if any) is printed out.
=item B<-alpn protocols>, B<-nextprotoneg protocols>
These flags enable the Enable the Application-Layer Protocol Negotiation
or Next Protocol Negotiation (NPN) extension, respectively. ALPN is the
IETF standard and replaces NPN.
The B<protocols> list is a comma-separated list of protocol names that
the client should advertise support for. The list should contain the most
desirable protocols first. Protocol names are printable ASCII strings,
for example "http/1.1" or "spdy/3".
An empty list of protocols is treated specially and will cause the
client to advertise support for the TLS extension but disconnect just
after receiving ServerHello with a list of server supported protocols.
The flag B<-nextprotoneg> cannot be specified if B<-tls1_3> is used.
=item B<-ct>, B<-noct>
Use one of these two options to control whether Certificate Transparency (CT)
is enabled (B<-ct>) or disabled (B<-noct>).
If CT is enabled, signed certificate timestamps (SCTs) will be requested from
the server and reported at handshake completion.
Enabling CT also enables OCSP stapling, as this is one possible delivery method
for SCTs.
=item B<-ctlogfile>
A file containing a list of known Certificate Transparency logs. See
L<SSL_CTX_set_ctlog_list_file(3)> for the expected file format.
=item B<-keylogfile file>
Appends TLS secrets to the specified keylog file such that external programs
(like Wireshark) can decrypt TLS connections.
=item B<-early_data file>
Reads the contents of the specified file and attempts to send it as early data
to the server. This will only work with resumed sessions that support early
data and when the server accepts the early data.
=item B<-enable_pha>
For TLSv1.3 only, send the Post-Handshake Authentication extension. This will
happen whether or not a certificate has been provided via B<-cert>.
=item B<[target]>
Rather than providing B<-connect>, the target hostname and optional port may
be provided as a single positional argument after all options. If neither this
nor B<-connect> are provided, falls back to attempting to connect to localhost
on port 4433.
=back
=head1 CONNECTED COMMANDS
If a connection is established with an SSL server then any data received
from the server is displayed and any key presses will be sent to the
server. If end of file is reached then the connection will be closed down. When
used interactively (which means neither B<-quiet> nor B<-ign_eof> have been
given), then certain commands are also recognized which perform special
operations. These commands are a letter which must appear at the start of a
line. They are listed below.
=over 4
=item B<Q>
End the current SSL connection and exit.
=item B<R>
Renegotiate the SSL session (TLSv1.2 and below only).
=item B<B>
Send a heartbeat message to the server (DTLS only)
=item B<k>
Send a key update message to the server (TLSv1.3 only)
=item B<K>
Send a key update message to the server and request one back (TLSv1.3 only)
=back
=head1 NOTES
B<s_client> can be used to debug SSL servers. To connect to an SSL HTTP
server the command:
openssl s_client -connect servername:443
would typically be used (https uses port 443). If the connection succeeds
then an HTTP command can be given such as "GET /" to retrieve a web page.
If the handshake fails then there are several possible causes, if it is
nothing obvious like no client certificate then the B<-bugs>,
B<-ssl3>, B<-tls1>, B<-no_ssl3>, B<-no_tls1> options can be tried
in case it is a buggy server. In particular you should play with these
options B<before> submitting a bug report to an OpenSSL mailing list.
A frequent problem when attempting to get client certificates working
is that a web client complains it has no certificates or gives an empty
list to choose from. This is normally because the server is not sending
the clients certificate authority in its "acceptable CA list" when it
requests a certificate. By using B<s_client> the CA list can be viewed
and checked. However some servers only request client authentication
after a specific URL is requested. To obtain the list in this case it
is necessary to use the B<-prexit> option and send an HTTP request
for an appropriate page.
If a certificate is specified on the command line using the B<-cert>
option it will not be used unless the server specifically requests
a client certificate. Therefor merely including a client certificate
on the command line is no guarantee that the certificate works.
If there are problems verifying a server certificate then the
B<-showcerts> option can be used to show all the certificates sent by the
server.
The B<s_client> utility is a test tool and is designed to continue the
handshake after any certificate verification errors. As a result it will
accept any certificate chain (trusted or not) sent by the peer. None test
applications should B<not> do this as it makes them vulnerable to a MITM
attack. This behaviour can be changed by with the B<-verify_return_error>
option: any verify errors are then returned aborting the handshake.
The B<-bind> option may be useful if the server or a firewall requires
connections to come from some particular address and or port.
=head1 BUGS
Because this program has a lot of options and also because some of the
techniques used are rather old, the C source of B<s_client> is rather hard to
read and not a model of how things should be done.
A typical SSL client program would be much simpler.
The B<-prexit> option is a bit of a hack. We should really report
information whenever a session is renegotiated.
=head1 SEE ALSO
L<SSL_CONF_cmd(3)>, L<sess_id(1)>, L<s_server(1)>, L<ciphers(1)>,
L<SSL_CTX_set_max_send_fragment(3)>, L<SSL_CTX_set_split_send_fragment(3)>,
L<SSL_CTX_set_max_pipelines(3)>
=head1 HISTORY
The B<-no_alt_chains> option was added in OpenSSL 1.1.0.
The B<-name> option was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man1/s_server.pod b/doc/man1/s_server.pod
index c4c014fdc18b..768789633e7f 100644
--- a/doc/man1/s_server.pod
+++ b/doc/man1/s_server.pod
@@ -1,855 +1,855 @@
=pod
=head1 NAME
openssl-s_server,
s_server - SSL/TLS server program
=head1 SYNOPSIS
B<openssl> B<s_server>
[B<-help>]
[B<-port +int>]
[B<-accept val>]
[B<-unix val>]
[B<-4>]
[B<-6>]
[B<-unlink>]
[B<-context val>]
[B<-verify int>]
[B<-Verify int>]
[B<-cert infile>]
[B<-nameopt val>]
[B<-naccept +int>]
[B<-serverinfo val>]
[B<-certform PEM|DER>]
[B<-key infile>]
[B<-keyform format>]
[B<-pass val>]
[B<-dcert infile>]
[B<-dcertform PEM|DER>]
[B<-dkey infile>]
[B<-dkeyform PEM|DER>]
[B<-dpass val>]
[B<-nbio_test>]
[B<-crlf>]
[B<-debug>]
[B<-msg>]
[B<-msgfile outfile>]
[B<-state>]
[B<-CAfile infile>]
[B<-CApath dir>]
[B<-no-CAfile>]
[B<-no-CApath>]
[B<-nocert>]
[B<-quiet>]
[B<-no_resume_ephemeral>]
[B<-www>]
[B<-WWW>]
[B<-servername>]
[B<-servername_fatal>]
[B<-cert2 infile>]
[B<-key2 infile>]
[B<-tlsextdebug>]
[B<-HTTP>]
[B<-id_prefix val>]
[B<-rand file...>]
[B<-writerand file>]
[B<-keymatexport val>]
[B<-keymatexportlen +int>]
[B<-CRL infile>]
[B<-crl_download>]
[B<-cert_chain infile>]
[B<-dcert_chain infile>]
[B<-chainCApath dir>]
[B<-verifyCApath dir>]
[B<-no_cache>]
[B<-ext_cache>]
[B<-CRLform PEM|DER>]
[B<-verify_return_error>]
[B<-verify_quiet>]
[B<-build_chain>]
[B<-chainCAfile infile>]
[B<-verifyCAfile infile>]
[B<-ign_eof>]
[B<-no_ign_eof>]
[B<-status>]
[B<-status_verbose>]
[B<-status_timeout int>]
[B<-status_url val>]
[B<-status_file infile>]
[B<-trace>]
[B<-security_debug>]
[B<-security_debug_verbose>]
[B<-brief>]
[B<-rev>]
[B<-async>]
[B<-ssl_config val>]
[B<-max_send_frag +int>]
[B<-split_send_frag +int>]
[B<-max_pipelines +int>]
[B<-read_buf +int>]
[B<-no_ssl3>]
[B<-no_tls1>]
[B<-no_tls1_1>]
[B<-no_tls1_2>]
[B<-no_tls1_3>]
[B<-bugs>]
[B<-no_comp>]
[B<-comp>]
[B<-no_ticket>]
[B<-num_tickets>]
[B<-serverpref>]
[B<-legacy_renegotiation>]
[B<-no_renegotiation>]
[B<-legacy_server_connect>]
[B<-no_resumption_on_reneg>]
[B<-no_legacy_server_connect>]
[B<-allow_no_dhe_kex>]
[B<-prioritize_chacha>]
[B<-strict>]
[B<-sigalgs val>]
[B<-client_sigalgs val>]
[B<-groups val>]
[B<-curves val>]
[B<-named_curve val>]
[B<-cipher val>]
[B<-ciphersuites val>]
[B<-dhparam infile>]
[B<-record_padding val>]
[B<-debug_broken_protocol>]
[B<-policy val>]
[B<-purpose val>]
[B<-verify_name val>]
[B<-verify_depth int>]
[B<-auth_level int>]
[B<-attime intmax>]
[B<-verify_hostname val>]
[B<-verify_email val>]
[B<-verify_ip>]
[B<-ignore_critical>]
[B<-issuer_checks>]
[B<-crl_check>]
[B<-crl_check_all>]
[B<-policy_check>]
[B<-explicit_policy>]
[B<-inhibit_any>]
[B<-inhibit_map>]
[B<-x509_strict>]
[B<-extended_crl>]
[B<-use_deltas>]
[B<-policy_print>]
[B<-check_ss_sig>]
[B<-trusted_first>]
[B<-suiteB_128_only>]
[B<-suiteB_128>]
[B<-suiteB_192>]
[B<-partial_chain>]
[B<-no_alt_chains>]
[B<-no_check_time>]
[B<-allow_proxy_certs>]
[B<-xkey>]
[B<-xcert>]
[B<-xchain>]
[B<-xchain_build>]
[B<-xcertform PEM|DER>]
[B<-xkeyform PEM|DER>]
[B<-nbio>]
[B<-psk_identity val>]
[B<-psk_hint val>]
[B<-psk val>]
[B<-psk_session file>]
[B<-srpvfile infile>]
[B<-srpuserseed val>]
[B<-ssl3>]
[B<-tls1>]
[B<-tls1_1>]
[B<-tls1_2>]
[B<-tls1_3>]
[B<-dtls>]
[B<-timeout>]
[B<-mtu +int>]
[B<-listen>]
[B<-dtls1>]
[B<-dtls1_2>]
[B<-sctp>]
[B<-sctp_label_bug>]
[B<-no_dhe>]
[B<-nextprotoneg val>]
[B<-use_srtp val>]
[B<-alpn val>]
[B<-engine val>]
[B<-keylogfile outfile>]
[B<-max_early_data int>]
[B<-early_data>]
[B<-anti_replay>]
[B<-no_anti_replay>]
=head1 DESCRIPTION
The B<s_server> command implements a generic SSL/TLS server which listens
for connections on a given port using SSL/TLS.
=head1 OPTIONS
In addition to the options below the B<s_server> utility also supports the
common and server only options documented in the
in the "Supported Command Line Commands" section of the L<SSL_CONF_cmd(3)>
manual page.
=over 4
=item B<-help>
Print out a usage message.
=item B<-port +int>
The TCP port to listen on for connections. If not specified 4433 is used.
=item B<-accept val>
The optional TCP host and port to listen on for connections. If not specified, *:4433 is used.
=item B<-unix val>
Unix domain socket to accept on.
=item B<-4>
Use IPv4 only.
=item B<-6>
Use IPv6 only.
=item B<-unlink>
For -unix, unlink any existing socket first.
=item B<-context val>
Sets the SSL context id. It can be given any string value. If this option
is not present a default value will be used.
=item B<-verify int>, B<-Verify int>
The verify depth to use. This specifies the maximum length of the
client certificate chain and makes the server request a certificate from
the client. With the B<-verify> option a certificate is requested but the
client does not have to send one, with the B<-Verify> option the client
must supply a certificate or an error occurs.
If the cipher suite cannot request a client certificate (for example an
anonymous cipher suite or PSK) this option has no effect.
=item B<-cert infile>
The certificate to use, most servers cipher suites require the use of a
certificate and some require a certificate with a certain public key type:
for example the DSS cipher suites require a certificate containing a DSS
(DSA) key. If not specified then the filename "server.pem" will be used.
=item B<-cert_chain>
A file containing trusted certificates to use when attempting to build the
client/server certificate chain related to the certificate specified via the
B<-cert> option.
=item B<-build_chain>
Specify whether the application should build the certificate chain to be
provided to the client.
=item B<-nameopt val>
Option which determines how the subject or issuer names are displayed. The
B<val> argument can be a single option or multiple options separated by
commas. Alternatively the B<-nameopt> switch may be used more than once to
set multiple options. See the L<x509(1)> manual page for details.
=item B<-naccept +int>
The server will exit after receiving the specified number of connections,
default unlimited.
=item B<-serverinfo val>
A file containing one or more blocks of PEM data. Each PEM block
must encode a TLS ServerHello extension (2 bytes type, 2 bytes length,
followed by "length" bytes of extension data). If the client sends
an empty TLS ClientHello extension matching the type, the corresponding
ServerHello extension will be returned.
=item B<-certform PEM|DER>
The certificate format to use: DER or PEM. PEM is the default.
=item B<-key infile>
The private key to use. If not specified then the certificate file will
be used.
=item B<-keyform format>
The private format to use: DER or PEM. PEM is the default.
=item B<-pass val>
The private key password source. For more information about the format of B<val>
see the B<PASS PHRASE ARGUMENTS> section in L<openssl(1)>.
=item B<-dcert infile>, B<-dkey infile>
Specify an additional certificate and private key, these behave in the
same manner as the B<-cert> and B<-key> options except there is no default
if they are not specified (no additional certificate and key is used). As
noted above some cipher suites require a certificate containing a key of
a certain type. Some cipher suites need a certificate carrying an RSA key
and some a DSS (DSA) key. By using RSA and DSS certificates and keys
a server can support clients which only support RSA or DSS cipher suites
by using an appropriate certificate.
=item B<-dcert_chain>
A file containing trusted certificates to use when attempting to build the
server certificate chain when a certificate specified via the B<-dcert> option
is in use.
=item B<-dcertform PEM|DER>, B<-dkeyform PEM|DER>, B<-dpass val>
Additional certificate and private key format and passphrase respectively.
=item B<-xkey infile>, B<-xcert infile>, B<-xchain>
Specify an extra certificate, private key and certificate chain. These behave
in the same manner as the B<-cert>, B<-key> and B<-cert_chain> options. When
specified, the callback returning the first valid chain will be in use by
the server.
=item B<-xchain_build>
Specify whether the application should build the certificate chain to be
provided to the client for the extra certificates provided via B<-xkey infile>,
B<-xcert infile>, B<-xchain> options.
=item B<-xcertform PEM|DER>, B<-xkeyform PEM|DER>
Extra certificate and private key format respectively.
=item B<-nbio_test>
Tests non blocking I/O.
=item B<-crlf>
This option translated a line feed from the terminal into CR+LF.
=item B<-debug>
Print extensive debugging information including a hex dump of all traffic.
=item B<-msg>
Show all protocol messages with hex dump.
=item B<-msgfile outfile>
File to send output of B<-msg> or B<-trace> to, default standard output.
=item B<-state>
Prints the SSL session states.
=item B<-CAfile infile>
A file containing trusted certificates to use during client authentication
and to use when attempting to build the server certificate chain. The list
is also used in the list of acceptable client CAs passed to the client when
a certificate is requested.
=item B<-CApath dir>
The directory to use for client certificate verification. This directory
must be in "hash format", see L<verify(1)> for more information. These are
also used when building the server certificate chain.
=item B<-chainCApath dir>
The directory to use for building the chain provided to the client. This
directory must be in "hash format", see L<verify(1)> for more information.
=item B<-chainCAfile file>
A file containing trusted certificates to use when attempting to build the
server certificate chain.
=item B<-no-CAfile>
Do not load the trusted CA certificates from the default file location.
=item B<-no-CApath>
Do not load the trusted CA certificates from the default directory location.
=item B<-nocert>
If this option is set then no certificate is used. This restricts the
cipher suites available to the anonymous ones (currently just anonymous
DH).
=item B<-quiet>
Inhibit printing of session and certificate information.
=item B<-www>
Sends a status message back to the client when it connects. This includes
information about the ciphers used and various session parameters.
The output is in HTML format so this option will normally be used with a
web browser. Cannot be used in conjunction with B<-early_data>.
=item B<-WWW>
Emulates a simple web server. Pages will be resolved relative to the
current directory, for example if the URL https://myhost/page.html is
requested the file ./page.html will be loaded. Cannot be used in conjunction
with B<-early_data>.
=item B<-tlsextdebug>
Print a hex dump of any TLS extensions received from the server.
=item B<-HTTP>
Emulates a simple web server. Pages will be resolved relative to the
current directory, for example if the URL https://myhost/page.html is
requested the file ./page.html will be loaded. The files loaded are
assumed to contain a complete and correct HTTP response (lines that
are part of the HTTP response line and headers must end with CRLF). Cannot be
used in conjunction with B<-early_data>.
=item B<-id_prefix val>
Generate SSL/TLS session IDs prefixed by B<val>. This is mostly useful
for testing any SSL/TLS code (eg. proxies) that wish to deal with multiple
servers, when each of which might be generating a unique range of session
IDs (eg. with a certain prefix).
=item B<-rand file...>
A file or files containing random data used to seed the random number
generator.
Multiple files can be specified separated by an OS-dependent character.
The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
all others.
=item [B<-writerand file>]
Writes random data to the specified I<file> upon exit.
This can be used with a subsequent B<-rand> flag.
=item B<-verify_return_error>
Verification errors normally just print a message but allow the
connection to continue, for debugging purposes.
If this option is used, then verification errors close the connection.
=item B<-status>
Enables certificate status request support (aka OCSP stapling).
=item B<-status_verbose>
Enables certificate status request support (aka OCSP stapling) and gives
a verbose printout of the OCSP response.
=item B<-status_timeout int>
Sets the timeout for OCSP response to B<int> seconds.
=item B<-status_url val>
Sets a fallback responder URL to use if no responder URL is present in the
server certificate. Without this option an error is returned if the server
certificate does not contain a responder address.
=item B<-status_file infile>
Overrides any OCSP responder URLs from the certificate and always provides the
OCSP Response stored in the file. The file must be in DER format.
=item B<-trace>
Show verbose trace output of protocol messages. OpenSSL needs to be compiled
with B<enable-ssl-trace> for this option to work.
=item B<-brief>
Provide a brief summary of connection parameters instead of the normal verbose
output.
=item B<-rev>
Simple test server which just reverses the text received from the client
and sends it back to the server. Also sets B<-brief>. Cannot be used in
conjunction with B<-early_data>.
=item B<-async>
Switch on asynchronous mode. Cryptographic operations will be performed
asynchronously. This will only have an effect if an asynchronous capable engine
is also used via the B<-engine> option. For test purposes the dummy async engine
(dasync) can be used (if available).
=item B<-max_send_frag +int>
The maximum size of data fragment to send.
See L<SSL_CTX_set_max_send_fragment(3)> for further information.
=item B<-split_send_frag +int>
The size used to split data for encrypt pipelines. If more data is written in
one go than this value then it will be split into multiple pipelines, up to the
maximum number of pipelines defined by max_pipelines. This only has an effect if
a suitable cipher suite has been negotiated, an engine that supports pipelining
has been loaded, and max_pipelines is greater than 1. See
L<SSL_CTX_set_split_send_fragment(3)> for further information.
=item B<-max_pipelines +int>
The maximum number of encrypt/decrypt pipelines to be used. This will only have
an effect if an engine has been loaded that supports pipelining (e.g. the dasync
engine) and a suitable cipher suite has been negotiated. The default value is 1.
See L<SSL_CTX_set_max_pipelines(3)> for further information.
=item B<-read_buf +int>
The default read buffer size to be used for connections. This will only have an
effect if the buffer size is larger than the size that would otherwise be used
and pipelining is in use (see L<SSL_CTX_set_default_read_buffer_len(3)> for
further information).
=item B<-ssl2>, B<-ssl3>, B<-tls1>, B<-tls1_1>, B<-tls1_2>, B<-tls1_3>, B<-no_ssl2>, B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
These options require or disable the use of the specified SSL or TLS protocols.
By default B<s_server> will negotiate the highest mutually supported protocol
version.
When a specific TLS version is required, only that version will be accepted
from the client.
Note that not all protocols and flags may be available, depending on how
OpenSSL was built.
=item B<-bugs>
-There are several known bug in SSL and TLS implementations. Adding this
+There are several known bugs in SSL and TLS implementations. Adding this
option enables various workarounds.
=item B<-no_comp>
Disable negotiation of TLS compression.
TLS compression is not recommended and is off by default as of
OpenSSL 1.1.0.
=item B<-comp>
Enable negotiation of TLS compression.
This option was introduced in OpenSSL 1.1.0.
TLS compression is not recommended and is off by default as of
OpenSSL 1.1.0.
=item B<-no_ticket>
Disable RFC4507bis session ticket support. This option has no effect if TLSv1.3
is negotiated. See B<-num_tickets>.
=item B<-num_tickets>
Control the number of tickets that will be sent to the client after a full
handshake in TLSv1.3. The default number of tickets is 2. This option does not
affect the number of tickets sent after a resumption handshake.
=item B<-serverpref>
Use the server's cipher preferences, rather than the client's preferences.
=item B<-prioritize_chacha>
Prioritize ChaCha ciphers when preferred by clients. Requires B<-serverpref>.
=item B<-no_resumption_on_reneg>
Set the B<SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION> option.
=item B<-client_sigalgs val>
Signature algorithms to support for client certificate authentication
(colon-separated list).
=item B<-named_curve val>
Specifies the elliptic curve to use. NOTE: this is single curve, not a list.
For a list of all possible curves, use:
$ openssl ecparam -list_curves
=item B<-cipher val>
This allows the list of TLSv1.2 and below ciphersuites used by the server to be
modified. This list is combined with any TLSv1.3 ciphersuites that have been
configured. When the client sends a list of supported ciphers the first client
cipher also included in the server list is used. Because the client specifies
the preference order, the order of the server cipherlist is irrelevant. See
the B<ciphers> command for more information.
=item B<-ciphersuites val>
This allows the list of TLSv1.3 ciphersuites used by the server to be modified.
This list is combined with any TLSv1.2 and below ciphersuites that have been
configured. When the client sends a list of supported ciphers the first client
cipher also included in the server list is used. Because the client specifies
the preference order, the order of the server cipherlist is irrelevant. See
the B<ciphers> command for more information. The format for this list is a
simple colon (":") separated list of TLSv1.3 ciphersuite names.
=item B<-dhparam infile>
The DH parameter file to use. The ephemeral DH cipher suites generate keys
using a set of DH parameters. If not specified then an attempt is made to
load the parameters from the server certificate file.
If this fails then a static set of parameters hard coded into the B<s_server>
program will be used.
=item B<-attime>, B<-check_ss_sig>, B<-crl_check>, B<-crl_check_all>,
B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>, B<-inhibit_any>,
B<-inhibit_map>, B<-no_alt_chains>, B<-no_check_time>, B<-partial_chain>, B<-policy>,
B<-policy_check>, B<-policy_print>, B<-purpose>, B<-suiteB_128>,
B<-suiteB_128_only>, B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>,
B<-auth_level>, B<-verify_depth>, B<-verify_email>, B<-verify_hostname>,
B<-verify_ip>, B<-verify_name>, B<-x509_strict>
Set different peer certificate verification options.
See the L<verify(1)> manual page for details.
=item B<-crl_check>, B<-crl_check_all>
Check the peer certificate has not been revoked by its CA.
The CRL(s) are appended to the certificate file. With the B<-crl_check_all>
option all CRLs of all CAs in the chain are checked.
=item B<-nbio>
Turns on non blocking I/O.
=item B<-psk_identity val>
Expect the client to send PSK identity B<val> when using a PSK
cipher suite, and warn if they do not. By default, the expected PSK
identity is the string "Client_identity".
=item B<-psk_hint val>
Use the PSK identity hint B<val> when using a PSK cipher suite.
=item B<-psk val>
Use the PSK key B<val> when using a PSK cipher suite. The key is
given as a hexadecimal number without leading 0x, for example -psk
1a2b3c4d.
This option must be provided in order to use a PSK cipher.
=item B<-psk_session file>
Use the pem encoded SSL_SESSION data stored in B<file> as the basis of a PSK.
Note that this will only work if TLSv1.3 is negotiated.
=item B<-listen>
This option can only be used in conjunction with one of the DTLS options above.
With this option B<s_server> will listen on a UDP port for incoming connections.
Any ClientHellos that arrive will be checked to see if they have a cookie in
them or not.
Any without a cookie will be responded to with a HelloVerifyRequest.
If a ClientHello with a cookie is received then B<s_server> will connect to
that peer and complete the handshake.
=item B<-dtls>, B<-dtls1>, B<-dtls1_2>
These options make B<s_server> use DTLS protocols instead of TLS.
With B<-dtls>, B<s_server> will negotiate any supported DTLS protocol version,
whilst B<-dtls1> and B<-dtls1_2> will only support DTLSv1.0 and DTLSv1.2
respectively.
=item B<-sctp>
Use SCTP for the transport protocol instead of UDP in DTLS. Must be used in
conjunction with B<-dtls>, B<-dtls1> or B<-dtls1_2>. This option is only
available where OpenSSL has support for SCTP enabled.
=item B<-sctp_label_bug>
Use the incorrect behaviour of older OpenSSL implementations when computing
endpoint-pair shared secrets for DTLS/SCTP. This allows communication with
older broken implementations but breaks interoperability with correct
implementations. Must be used in conjunction with B<-sctp>. This option is only
available where OpenSSL has support for SCTP enabled.
=item B<-no_dhe>
If this option is set then no DH parameters will be loaded effectively
disabling the ephemeral DH cipher suites.
=item B<-alpn val>, B<-nextprotoneg val>
These flags enable the Enable the Application-Layer Protocol Negotiation
or Next Protocol Negotiation (NPN) extension, respectively. ALPN is the
IETF standard and replaces NPN.
The B<val> list is a comma-separated list of supported protocol
names. The list should contain the most desirable protocols first.
Protocol names are printable ASCII strings, for example "http/1.1" or
"spdy/3".
The flag B<-nextprotoneg> cannot be specified if B<-tls1_3> is used.
=item B<-engine val>
Specifying an engine (by its unique id string in B<val>) will cause B<s_server>
to attempt to obtain a functional reference to the specified engine,
thus initialising it if needed. The engine will then be set as the default
for all available algorithms.
=item B<-keylogfile outfile>
Appends TLS secrets to the specified keylog file such that external programs
(like Wireshark) can decrypt TLS connections.
=item B<-max_early_data int>
Change the default maximum early data bytes that are specified for new sessions
and any incoming early data (when used in conjunction with the B<-early_data>
flag). The default value is approximately 16k. The argument must be an integer
greater than or equal to 0.
=item B<-early_data>
Accept early data where possible. Cannot be used in conjunction with B<-www>,
B<-WWW>, B<-HTTP> or B<-rev>.
=item B<-anti_replay>, B<-no_anti_replay>
Switches replay protection on or off, respectively. Replay protection is on by
default unless overridden by a configuration file. When it is on, OpenSSL will
automatically detect if a session ticket has been used more than once, TLSv1.3
has been negotiated, and early data is enabled on the server. A full handshake
is forced if a session ticket is used a second or subsequent time. Any early
data that was sent will be rejected.
=back
=head1 CONNECTED COMMANDS
If a connection request is established with an SSL client and neither the
B<-www> nor the B<-WWW> option has been used then normally any data received
from the client is displayed and any key presses will be sent to the client.
Certain commands are also recognized which perform special operations. These
commands are a letter which must appear at the start of a line. They are listed
below.
=over 4
=item B<q>
End the current SSL connection but still accept new connections.
=item B<Q>
End the current SSL connection and exit.
=item B<r>
Renegotiate the SSL session (TLSv1.2 and below only).
=item B<R>
Renegotiate the SSL session and request a client certificate (TLSv1.2 and below
only).
=item B<P>
Send some plain text down the underlying TCP connection: this should
cause the client to disconnect due to a protocol violation.
=item B<S>
Print out some session cache status information.
=item B<B>
Send a heartbeat message to the client (DTLS only)
=item B<k>
Send a key update message to the client (TLSv1.3 only)
=item B<K>
Send a key update message to the client and request one back (TLSv1.3 only)
=item B<c>
Send a certificate request to the client (TLSv1.3 only)
=back
=head1 NOTES
B<s_server> can be used to debug SSL clients. To accept connections from
a web browser the command:
openssl s_server -accept 443 -www
can be used for example.
Although specifying an empty list of CAs when requesting a client certificate
is strictly speaking a protocol violation, some SSL clients interpret this to
mean any CA is acceptable. This is useful for debugging purposes.
The session parameters can printed out using the B<sess_id> program.
=head1 BUGS
Because this program has a lot of options and also because some of the
techniques used are rather old, the C source of B<s_server> is rather hard to
read and not a model of how things should be done.
A typical SSL server program would be much simpler.
The output of common ciphers is wrong: it just gives the list of ciphers that
OpenSSL recognizes and the client supports.
There should be a way for the B<s_server> program to print out details of any
unknown cipher suites a client says it supports.
=head1 SEE ALSO
L<SSL_CONF_cmd(3)>, L<sess_id(1)>, L<s_client(1)>, L<ciphers(1)>
L<SSL_CTX_set_max_send_fragment(3)>,
L<SSL_CTX_set_split_send_fragment(3)>,
L<SSL_CTX_set_max_pipelines(3)>
=head1 HISTORY
The -no_alt_chains option was added in OpenSSL 1.1.0.
The
-allow-no-dhe-kex and -prioritize_chacha options were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man1/s_time.pod b/doc/man1/s_time.pod
index c08e44a431be..ac32f36bc789 100644
--- a/doc/man1/s_time.pod
+++ b/doc/man1/s_time.pod
@@ -1,212 +1,212 @@
=pod
=head1 NAME
openssl-s_time,
s_time - SSL/TLS performance timing program
=head1 SYNOPSIS
B<openssl> B<s_time>
[B<-help>]
[B<-connect host:port>]
[B<-www page>]
[B<-cert filename>]
[B<-key filename>]
[B<-CApath directory>]
[B<-cafile filename>]
[B<-no-CAfile>]
[B<-no-CApath>]
[B<-reuse>]
[B<-new>]
[B<-verify depth>]
[B<-nameopt option>]
[B<-time seconds>]
[B<-ssl3>]
[B<-bugs>]
[B<-cipher cipherlist>]
[B<-ciphersuites val>]
=head1 DESCRIPTION
The B<s_time> command implements a generic SSL/TLS client which connects to a
remote host using SSL/TLS. It can request a page from the server and includes
the time to transfer the payload data in its timing measurements. It measures
the number of connections within a given timeframe, the amount of data
transferred (if any), and calculates the average time spent for one connection.
=head1 OPTIONS
=over 4
=item B<-help>
Print out a usage message.
=item B<-connect host:port>
This specifies the host and optional port to connect to.
=item B<-www page>
This specifies the page to GET from the server. A value of '/' gets the
index.htm[l] page. If this parameter is not specified, then B<s_time> will only
perform the handshake to establish SSL connections but not transfer any
payload data.
=item B<-cert certname>
The certificate to use, if one is requested by the server. The default is
not to use a certificate. The file is in PEM format.
=item B<-key keyfile>
The private key to use. If not specified then the certificate file will
be used. The file is in PEM format.
=item B<-verify depth>
The verify depth to use. This specifies the maximum length of the
server certificate chain and turns on server certificate verification.
Currently the verify operation continues after errors so all the problems
with a certificate chain can be seen. As a side effect the connection
will never fail due to a server certificate verify failure.
=item B<-nameopt option>
Option which determines how the subject or issuer names are displayed. The
B<option> argument can be a single option or multiple options separated by
commas. Alternatively the B<-nameopt> switch may be used more than once to
set multiple options. See the L<x509(1)> manual page for details.
=item B<-CApath directory>
The directory to use for server certificate verification. This directory
must be in "hash format", see B<verify> for more information. These are
also used when building the client certificate chain.
=item B<-CAfile file>
A file containing trusted certificates to use during server authentication
and to use when attempting to build the client certificate chain.
=item B<-no-CAfile>
Do not load the trusted CA certificates from the default file location
=item B<-no-CApath>
Do not load the trusted CA certificates from the default directory location
=item B<-new>
Performs the timing test using a new session ID for each connection.
If neither B<-new> nor B<-reuse> are specified, they are both on by default
and executed in sequence.
=item B<-reuse>
Performs the timing test using the same session ID; this can be used as a test
that session caching is working. If neither B<-new> nor B<-reuse> are
specified, they are both on by default and executed in sequence.
=item B<-ssl3>
This option disables the use of SSL version 3. By default
the initial handshake uses a method which should be compatible with all
servers and permit them to use SSL v3 or TLS as appropriate.
The timing program is not as rich in options to turn protocols on and off as
the L<s_client(1)> program and may not connect to all servers.
Unfortunately there are a lot of ancient and broken servers in use which
cannot handle this technique and will fail to connect. Some servers only
work if TLS is turned off with the B<-ssl3> option.
Note that this option may not be available, depending on how
OpenSSL was built.
=item B<-bugs>
-There are several known bug in SSL and TLS implementations. Adding this
+There are several known bugs in SSL and TLS implementations. Adding this
option enables various workarounds.
=item B<-cipher cipherlist>
This allows the TLSv1.2 and below cipher list sent by the client to be modified.
This list will be combined with any TLSv1.3 ciphersuites that have been
configured. Although the server determines which cipher suite is used it should
take the first supported cipher in the list sent by the client. See
L<ciphers(1)> for more information.
=item B<-ciphersuites val>
This allows the TLSv1.3 ciphersuites sent by the client to be modified. This
list will be combined with any TLSv1.2 and below ciphersuites that have been
configured. Although the server determines which cipher suite is used it should
take the first supported cipher in the list sent by the client. See
L<ciphers(1)> for more information. The format for this list is a simple
colon (":") separated list of TLSv1.3 ciphersuite names.
=item B<-time length>
Specifies how long (in seconds) B<s_time> should establish connections and
optionally transfer payload data from a server. Server and client performance
and the link speed determine how many connections B<s_time> can establish.
=back
=head1 NOTES
B<s_time> can be used to measure the performance of an SSL connection.
To connect to an SSL HTTP server and get the default page the command
openssl s_time -connect servername:443 -www / -CApath yourdir -CAfile yourfile.pem -cipher commoncipher [-ssl3]
would typically be used (https uses port 443). 'commoncipher' is a cipher to
which both client and server can agree, see the L<ciphers(1)> command
for details.
If the handshake fails then there are several possible causes, if it is
nothing obvious like no client certificate then the B<-bugs> and
B<-ssl3> options can be tried
in case it is a buggy server. In particular you should play with these
options B<before> submitting a bug report to an OpenSSL mailing list.
A frequent problem when attempting to get client certificates working
is that a web client complains it has no certificates or gives an empty
list to choose from. This is normally because the server is not sending
the clients certificate authority in its "acceptable CA list" when it
requests a certificate. By using L<s_client(1)> the CA list can be
viewed and checked. However some servers only request client authentication
after a specific URL is requested. To obtain the list in this case it
is necessary to use the B<-prexit> option of L<s_client(1)> and
send an HTTP request for an appropriate page.
If a certificate is specified on the command line using the B<-cert>
option it will not be used unless the server specifically requests
a client certificate. Therefor merely including a client certificate
on the command line is no guarantee that the certificate works.
=head1 BUGS
Because this program does not have all the options of the
L<s_client(1)> program to turn protocols on and off, you may not be
able to measure the performance of all protocols with all servers.
The B<-verify> option should really exit if the server verification
fails.
=head1 SEE ALSO
L<s_client(1)>, L<s_server(1)>, L<ciphers(1)>
=head1 COPYRIGHT
-Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man1/ts.pod b/doc/man1/ts.pod
index eeccaf674c1a..ec57ec7ebbd4 100644
--- a/doc/man1/ts.pod
+++ b/doc/man1/ts.pod
@@ -1,674 +1,675 @@
=pod
=head1 NAME
openssl-ts,
ts - Time Stamping Authority tool (client/server)
=head1 SYNOPSIS
B<openssl> B<ts>
B<-query>
[B<-rand file...>]
[B<-writerand file>]
[B<-config> configfile]
[B<-data> file_to_hash]
[B<-digest> digest_bytes]
[B<-I<digest>>]
[B<-tspolicy> object_id]
[B<-no_nonce>]
[B<-cert>]
[B<-in> request.tsq]
[B<-out> request.tsq]
[B<-text>]
B<openssl> B<ts>
B<-reply>
[B<-config> configfile]
[B<-section> tsa_section]
[B<-queryfile> request.tsq]
[B<-passin> password_src]
[B<-signer> tsa_cert.pem]
[B<-inkey> file_or_id]
[B<-I<digest>>]
[B<-chain> certs_file.pem]
[B<-tspolicy> object_id]
[B<-in> response.tsr]
[B<-token_in>]
[B<-out> response.tsr]
[B<-token_out>]
[B<-text>]
[B<-engine> id]
B<openssl> B<ts>
B<-verify>
[B<-data> file_to_hash]
[B<-digest> digest_bytes]
[B<-queryfile> request.tsq]
[B<-in> response.tsr]
[B<-token_in>]
[B<-CApath> trusted_cert_path]
[B<-CAfile> trusted_certs.pem]
[B<-untrusted> cert_file.pem]
[I<verify options>]
I<verify options:>
[-attime timestamp]
[-check_ss_sig]
[-crl_check]
[-crl_check_all]
[-explicit_policy]
[-extended_crl]
[-ignore_critical]
[-inhibit_any]
[-inhibit_map]
[-issuer_checks]
[-no_alt_chains]
[-no_check_time]
[-partial_chain]
[-policy arg]
[-policy_check]
[-policy_print]
[-purpose purpose]
[-suiteB_128]
[-suiteB_128_only]
[-suiteB_192]
[-trusted_first]
[-use_deltas]
[-auth_level num]
[-verify_depth num]
[-verify_email email]
[-verify_hostname hostname]
[-verify_ip ip]
[-verify_name name]
[-x509_strict]
=head1 DESCRIPTION
The B<ts> command is a basic Time Stamping Authority (TSA) client and server
application as specified in RFC 3161 (Time-Stamp Protocol, TSP). A
TSA can be part of a PKI deployment and its role is to provide long
term proof of the existence of a certain datum before a particular
time. Here is a brief description of the protocol:
=over 4
=item 1.
The TSA client computes a one-way hash value for a data file and sends
the hash to the TSA.
=item 2.
The TSA attaches the current date and time to the received hash value,
signs them and sends the time stamp token back to the client. By
creating this token the TSA certifies the existence of the original
data file at the time of response generation.
=item 3.
The TSA client receives the time stamp token and verifies the
signature on it. It also checks if the token contains the same hash
value that it had sent to the TSA.
=back
There is one DER encoded protocol data unit defined for transporting a time
stamp request to the TSA and one for sending the time stamp response
back to the client. The B<ts> command has three main functions:
creating a time stamp request based on a data file,
creating a time stamp response based on a request, verifying if a
response corresponds to a particular request or a data file.
There is no support for sending the requests/responses automatically
over HTTP or TCP yet as suggested in RFC 3161. The users must send the
requests either by ftp or e-mail.
=head1 OPTIONS
=head2 Time Stamp Request generation
The B<-query> switch can be used for creating and printing a time stamp
request with the following options:
=over 4
=item B<-rand file...>
A file or files containing random data used to seed the random number
generator.
Multiple files can be specified separated by an OS-dependent character.
The separator is B<;> for MS-Windows, B<,> for OpenVMS, and B<:> for
all others.
=item [B<-writerand file>]
Writes random data to the specified I<file> upon exit.
This can be used with a subsequent B<-rand> flag.
=item B<-config> configfile
The configuration file to use.
Optional; for a description of the default value,
see L<openssl(1)/COMMAND SUMMARY>.
=item B<-data> file_to_hash
The data file for which the time stamp request needs to be
created. stdin is the default if neither the B<-data> nor the B<-digest>
parameter is specified. (Optional)
=item B<-digest> digest_bytes
It is possible to specify the message imprint explicitly without the data
file. The imprint must be specified in a hexadecimal format, two characters
per byte, the bytes optionally separated by colons (e.g. 1A:F6:01:... or
1AF601...). The number of bytes must match the message digest algorithm
in use. (Optional)
=item B<-I<digest>>
The message digest to apply to the data file.
Any digest supported by the OpenSSL B<dgst> command can be used.
The default is SHA-1. (Optional)
=item B<-tspolicy> object_id
The policy that the client expects the TSA to use for creating the
time stamp token. Either the dotted OID notation or OID names defined
in the config file can be used. If no policy is requested the TSA will
use its own default policy. (Optional)
=item B<-no_nonce>
No nonce is specified in the request if this option is
given. Otherwise a 64 bit long pseudo-random none is
included in the request. It is recommended to use nonce to
protect against replay-attacks. (Optional)
=item B<-cert>
The TSA is expected to include its signing certificate in the
response. (Optional)
=item B<-in> request.tsq
This option specifies a previously created time stamp request in DER
format that will be printed into the output file. Useful when you need
to examine the content of a request in human-readable
format. (Optional)
=item B<-out> request.tsq
Name of the output file to which the request will be written. Default
is stdout. (Optional)
=item B<-text>
If this option is specified the output is human-readable text format
instead of DER. (Optional)
=back
=head2 Time Stamp Response generation
A time stamp response (TimeStampResp) consists of a response status
and the time stamp token itself (ContentInfo), if the token generation was
successful. The B<-reply> command is for creating a time stamp
response or time stamp token based on a request and printing the
response/token in human-readable format. If B<-token_out> is not
specified the output is always a time stamp response (TimeStampResp),
otherwise it is a time stamp token (ContentInfo).
=over 4
=item B<-config> configfile
The configuration file to use.
Optional; for a description of the default value,
see L<openssl(1)/COMMAND SUMMARY>.
See B<CONFIGURATION FILE OPTIONS> for configurable variables.
=item B<-section> tsa_section
The name of the config file section containing the settings for the
response generation. If not specified the default TSA section is
used, see B<CONFIGURATION FILE OPTIONS> for details. (Optional)
=item B<-queryfile> request.tsq
The name of the file containing a DER encoded time stamp request. (Optional)
=item B<-passin> password_src
Specifies the password source for the private key of the TSA. See
B<PASS PHRASE ARGUMENTS> in L<openssl(1)>. (Optional)
=item B<-signer> tsa_cert.pem
The signer certificate of the TSA in PEM format. The TSA signing
certificate must have exactly one extended key usage assigned to it:
timeStamping. The extended key usage must also be critical, otherwise
the certificate is going to be refused. Overrides the B<signer_cert>
variable of the config file. (Optional)
=item B<-inkey> file_or_id
The signer private key of the TSA in PEM format. Overrides the
B<signer_key> config file option. (Optional)
If no engine is used, the argument is taken as a file; if an engine is
specified, the argument is given to the engine as a key identifier.
=item B<-I<digest>>
Signing digest to use. Overrides the B<signer_digest> config file
-option. (Optional)
+option. (Mandatory unless specified in the config file)
=item B<-chain> certs_file.pem
The collection of certificates in PEM format that will all
be included in the response in addition to the signer certificate if
the B<-cert> option was used for the request. This file is supposed to
contain the certificate chain for the signer certificate from its
issuer upwards. The B<-reply> command does not build a certificate
chain automatically. (Optional)
=item B<-tspolicy> object_id
The default policy to use for the response unless the client
explicitly requires a particular TSA policy. The OID can be specified
either in dotted notation or with its name. Overrides the
B<default_policy> config file option. (Optional)
=item B<-in> response.tsr
Specifies a previously created time stamp response or time stamp token
(if B<-token_in> is also specified) in DER format that will be written
to the output file. This option does not require a request, it is
useful e.g. when you need to examine the content of a response or
token or you want to extract the time stamp token from a response. If
the input is a token and the output is a time stamp response a default
'granted' status info is added to the token. (Optional)
=item B<-token_in>
This flag can be used together with the B<-in> option and indicates
that the input is a DER encoded time stamp token (ContentInfo) instead
of a time stamp response (TimeStampResp). (Optional)
=item B<-out> response.tsr
The response is written to this file. The format and content of the
file depends on other options (see B<-text>, B<-token_out>). The default is
stdout. (Optional)
=item B<-token_out>
The output is a time stamp token (ContentInfo) instead of time stamp
response (TimeStampResp). (Optional)
=item B<-text>
If this option is specified the output is human-readable text format
instead of DER. (Optional)
=item B<-engine> id
Specifying an engine (by its unique B<id> string) will cause B<ts>
to attempt to obtain a functional reference to the specified engine,
thus initialising it if needed. The engine will then be set as the default
for all available algorithms. Default is builtin. (Optional)
=back
=head2 Time Stamp Response verification
The B<-verify> command is for verifying if a time stamp response or time
stamp token is valid and matches a particular time stamp request or
data file. The B<-verify> command does not use the configuration file.
=over 4
=item B<-data> file_to_hash
The response or token must be verified against file_to_hash. The file
is hashed with the message digest algorithm specified in the token.
The B<-digest> and B<-queryfile> options must not be specified with this one.
(Optional)
=item B<-digest> digest_bytes
The response or token must be verified against the message digest specified
with this option. The number of bytes must match the message digest algorithm
specified in the token. The B<-data> and B<-queryfile> options must not be
specified with this one. (Optional)
=item B<-queryfile> request.tsq
The original time stamp request in DER format. The B<-data> and B<-digest>
options must not be specified with this one. (Optional)
=item B<-in> response.tsr
The time stamp response that needs to be verified in DER format. (Mandatory)
=item B<-token_in>
This flag can be used together with the B<-in> option and indicates
that the input is a DER encoded time stamp token (ContentInfo) instead
of a time stamp response (TimeStampResp). (Optional)
=item B<-CApath> trusted_cert_path
The name of the directory containing the trusted CA certificates of the
client. See the similar option of L<verify(1)> for additional
details. Either this option or B<-CAfile> must be specified. (Optional)
=item B<-CAfile> trusted_certs.pem
The name of the file containing a set of trusted self-signed CA
certificates in PEM format. See the similar option of
L<verify(1)> for additional details. Either this option
or B<-CApath> must be specified.
(Optional)
=item B<-untrusted> cert_file.pem
Set of additional untrusted certificates in PEM format which may be
needed when building the certificate chain for the TSA's signing
certificate. This file must contain the TSA signing certificate and
all intermediate CA certificates unless the response includes them.
(Optional)
=item I<verify options>
The options B<-attime timestamp>, B<-check_ss_sig>, B<-crl_check>,
B<-crl_check_all>, B<-explicit_policy>, B<-extended_crl>, B<-ignore_critical>,
B<-inhibit_any>, B<-inhibit_map>, B<-issuer_checks>, B<-no_alt_chains>,
B<-no_check_time>, B<-partial_chain>, B<-policy>, B<-policy_check>,
B<-policy_print>, B<-purpose>, B<-suiteB_128>, B<-suiteB_128_only>,
B<-suiteB_192>, B<-trusted_first>, B<-use_deltas>, B<-auth_level>,
B<-verify_depth>, B<-verify_email>, B<-verify_hostname>, B<-verify_ip>,
B<-verify_name>, and B<-x509_strict> can be used to control timestamp
verification. See L<verify(1)>.
=back
=head1 CONFIGURATION FILE OPTIONS
The B<-query> and B<-reply> commands make use of a configuration file.
See L<config(5)>
for a general description of the syntax of the config file. The
B<-query> command uses only the symbolic OID names section
and it can work without it. However, the B<-reply> command needs the
config file for its operation.
When there is a command line switch equivalent of a variable the
switch always overrides the settings in the config file.
=over 4
=item B<tsa> section, B<default_tsa>
This is the main section and it specifies the name of another section
that contains all the options for the B<-reply> command. This default
section can be overridden with the B<-section> command line switch. (Optional)
=item B<oid_file>
See L<ca(1)> for description. (Optional)
=item B<oid_section>
See L<ca(1)> for description. (Optional)
=item B<RANDFILE>
See L<ca(1)> for description. (Optional)
=item B<serial>
The name of the file containing the hexadecimal serial number of the
last time stamp response created. This number is incremented by 1 for
each response. If the file does not exist at the time of response
generation a new file is created with serial number 1. (Mandatory)
=item B<crypto_device>
Specifies the OpenSSL engine that will be set as the default for
all available algorithms. The default value is builtin, you can specify
any other engines supported by OpenSSL (e.g. use chil for the NCipher HSM).
(Optional)
=item B<signer_cert>
TSA signing certificate in PEM format. The same as the B<-signer>
command line option. (Optional)
=item B<certs>
A file containing a set of PEM encoded certificates that need to be
included in the response. The same as the B<-chain> command line
option. (Optional)
=item B<signer_key>
The private key of the TSA in PEM format. The same as the B<-inkey>
command line option. (Optional)
=item B<signer_digest>
Signing digest to use. The same as the
-B<-I<digest>> command line option. (Optional)
+B<-I<digest>> command line option. (Mandatory unless specified on the command
+line)
=item B<default_policy>
The default policy to use when the request does not mandate any
policy. The same as the B<-tspolicy> command line option. (Optional)
=item B<other_policies>
Comma separated list of policies that are also acceptable by the TSA
and used only if the request explicitly specifies one of them. (Optional)
=item B<digests>
The list of message digest algorithms that the TSA accepts. At least
one algorithm must be specified. (Mandatory)
=item B<accuracy>
The accuracy of the time source of the TSA in seconds, milliseconds
and microseconds. E.g. secs:1, millisecs:500, microsecs:100. If any of
the components is missing zero is assumed for that field. (Optional)
=item B<clock_precision_digits>
Specifies the maximum number of digits, which represent the fraction of
seconds, that need to be included in the time field. The trailing zeroes
must be removed from the time, so there might actually be fewer digits,
or no fraction of seconds at all. Supported only on UNIX platforms.
The maximum value is 6, default is 0.
(Optional)
=item B<ordering>
If this option is yes the responses generated by this TSA can always
be ordered, even if the time difference between two responses is less
than the sum of their accuracies. Default is no. (Optional)
=item B<tsa_name>
Set this option to yes if the subject name of the TSA must be included in
the TSA name field of the response. Default is no. (Optional)
=item B<ess_cert_id_chain>
The SignedData objects created by the TSA always contain the
certificate identifier of the signing certificate in a signed
attribute (see RFC 2634, Enhanced Security Services). If this option
is set to yes and either the B<certs> variable or the B<-chain> option
is specified then the certificate identifiers of the chain will also
be included in the SigningCertificate signed attribute. If this
variable is set to no, only the signing certificate identifier is
included. Default is no. (Optional)
=item B<ess_cert_id_alg>
This option specifies the hash function to be used to calculate the TSA's
public key certificate identifier. Default is sha1. (Optional)
=back
=head1 EXAMPLES
All the examples below presume that B<OPENSSL_CONF> is set to a proper
configuration file, e.g. the example configuration file
openssl/apps/openssl.cnf will do.
=head2 Time Stamp Request
To create a time stamp request for design1.txt with SHA-1
without nonce and policy and no certificate is required in the response:
openssl ts -query -data design1.txt -no_nonce \
-out design1.tsq
To create a similar time stamp request with specifying the message imprint
explicitly:
openssl ts -query -digest b7e5d3f93198b38379852f2c04e78d73abdd0f4b \
-no_nonce -out design1.tsq
To print the content of the previous request in human readable format:
openssl ts -query -in design1.tsq -text
To create a time stamp request which includes the MD-5 digest
of design2.txt, requests the signer certificate and nonce,
specifies a policy id (assuming the tsa_policy1 name is defined in the
OID section of the config file):
openssl ts -query -data design2.txt -md5 \
-tspolicy tsa_policy1 -cert -out design2.tsq
=head2 Time Stamp Response
Before generating a response a signing certificate must be created for
the TSA that contains the B<timeStamping> critical extended key usage extension
without any other key usage extensions. You can add this line to the
user certificate section of the config file to generate a proper certificate;
extendedKeyUsage = critical,timeStamping
See L<req(1)>, L<ca(1)>, and L<x509(1)> for instructions. The examples
below assume that cacert.pem contains the certificate of the CA,
tsacert.pem is the signing certificate issued by cacert.pem and
tsakey.pem is the private key of the TSA.
To create a time stamp response for a request:
openssl ts -reply -queryfile design1.tsq -inkey tsakey.pem \
-signer tsacert.pem -out design1.tsr
If you want to use the settings in the config file you could just write:
openssl ts -reply -queryfile design1.tsq -out design1.tsr
To print a time stamp reply to stdout in human readable format:
openssl ts -reply -in design1.tsr -text
To create a time stamp token instead of time stamp response:
openssl ts -reply -queryfile design1.tsq -out design1_token.der -token_out
To print a time stamp token to stdout in human readable format:
openssl ts -reply -in design1_token.der -token_in -text -token_out
To extract the time stamp token from a response:
openssl ts -reply -in design1.tsr -out design1_token.der -token_out
To add 'granted' status info to a time stamp token thereby creating a
valid response:
openssl ts -reply -in design1_token.der -token_in -out design1.tsr
=head2 Time Stamp Verification
To verify a time stamp reply against a request:
openssl ts -verify -queryfile design1.tsq -in design1.tsr \
-CAfile cacert.pem -untrusted tsacert.pem
To verify a time stamp reply that includes the certificate chain:
openssl ts -verify -queryfile design2.tsq -in design2.tsr \
-CAfile cacert.pem
To verify a time stamp token against the original data file:
openssl ts -verify -data design2.txt -in design2.tsr \
-CAfile cacert.pem
To verify a time stamp token against a message imprint:
openssl ts -verify -digest b7e5d3f93198b38379852f2c04e78d73abdd0f4b \
-in design2.tsr -CAfile cacert.pem
You could also look at the 'test' directory for more examples.
=head1 BUGS
=for comment foreign manuals: procmail(1), perl(1)
=over 2
=item *
No support for time stamps over SMTP, though it is quite easy
to implement an automatic e-mail based TSA with L<procmail(1)>
and L<perl(1)>. HTTP server support is provided in the form of
a separate apache module. HTTP client support is provided by
L<tsget(1)>. Pure TCP/IP protocol is not supported.
=item *
The file containing the last serial number of the TSA is not
locked when being read or written. This is a problem if more than one
instance of L<openssl(1)> is trying to create a time stamp
response at the same time. This is not an issue when using the apache
server module, it does proper locking.
=item *
Look for the FIXME word in the source files.
=item *
The source code should really be reviewed by somebody else, too.
=item *
More testing is needed, I have done only some basic tests (see
test/testtsa).
=back
=head1 SEE ALSO
L<tsget(1)>, L<openssl(1)>, L<req(1)>,
L<x509(1)>, L<ca(1)>, L<genrsa(1)>,
L<config(5)>
=head1 COPYRIGHT
-Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/ASN1_TIME_set.pod b/doc/man3/ASN1_TIME_set.pod
index a083ebfd1bd4..5ed817517dc6 100644
--- a/doc/man3/ASN1_TIME_set.pod
+++ b/doc/man3/ASN1_TIME_set.pod
@@ -1,258 +1,258 @@
=pod
=head1 NAME
ASN1_TIME_set, ASN1_UTCTIME_set, ASN1_GENERALIZEDTIME_set,
ASN1_TIME_adj, ASN1_UTCTIME_adj, ASN1_GENERALIZEDTIME_adj,
ASN1_TIME_check, ASN1_UTCTIME_check, ASN1_GENERALIZEDTIME_check,
ASN1_TIME_set_string, ASN1_UTCTIME_set_string, ASN1_GENERALIZEDTIME_set_string,
ASN1_TIME_set_string_X509,
ASN1_TIME_normalize,
ASN1_TIME_to_tm,
ASN1_TIME_print, ASN1_UTCTIME_print, ASN1_GENERALIZEDTIME_print,
ASN1_TIME_diff,
ASN1_TIME_cmp_time_t, ASN1_UTCTIME_cmp_time_t,
ASN1_TIME_compare,
ASN1_TIME_to_generalizedtime - ASN.1 Time functions
=head1 SYNOPSIS
ASN1_TIME *ASN1_TIME_set(ASN1_TIME *s, time_t t);
ASN1_UTCTIME *ASN1_UTCTIME_set(ASN1_UTCTIME *s, time_t t);
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_set(ASN1_GENERALIZEDTIME *s,
time_t t);
ASN1_TIME *ASN1_TIME_adj(ASN1_TIME *s, time_t t, int offset_day,
long offset_sec);
ASN1_UTCTIME *ASN1_UTCTIME_adj(ASN1_UTCTIME *s, time_t t,
int offset_day, long offset_sec);
ASN1_GENERALIZEDTIME *ASN1_GENERALIZEDTIME_adj(ASN1_GENERALIZEDTIME *s,
time_t t, int offset_day,
long offset_sec);
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str);
int ASN1_TIME_set_string_X509(ASN1_TIME *s, const char *str);
int ASN1_UTCTIME_set_string(ASN1_UTCTIME *s, const char *str);
int ASN1_GENERALIZEDTIME_set_string(ASN1_GENERALIZEDTIME *s,
const char *str);
int ASN1_TIME_normalize(ASN1_TIME *s);
int ASN1_TIME_check(const ASN1_TIME *t);
int ASN1_UTCTIME_check(const ASN1_UTCTIME *t);
int ASN1_GENERALIZEDTIME_check(const ASN1_GENERALIZEDTIME *t);
int ASN1_TIME_print(BIO *b, const ASN1_TIME *s);
int ASN1_UTCTIME_print(BIO *b, const ASN1_UTCTIME *s);
int ASN1_GENERALIZEDTIME_print(BIO *b, const ASN1_GENERALIZEDTIME *s);
int ASN1_TIME_to_tm(const ASN1_TIME *s, struct tm *tm);
int ASN1_TIME_diff(int *pday, int *psec, const ASN1_TIME *from,
const ASN1_TIME *to);
int ASN1_TIME_cmp_time_t(const ASN1_TIME *s, time_t t);
int ASN1_UTCTIME_cmp_time_t(const ASN1_UTCTIME *s, time_t t);
int ASN1_TIME_compare(const ASN1_TIME *a, const ASN1_TIME *b);
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
ASN1_GENERALIZEDTIME **out);
=head1 DESCRIPTION
The ASN1_TIME_set(), ASN1_UTCTIME_set() and ASN1_GENERALIZEDTIME_set()
functions set the structure B<s> to the time represented by the time_t
value B<t>. If B<s> is NULL a new time structure is allocated and returned.
The ASN1_TIME_adj(), ASN1_UTCTIME_adj() and ASN1_GENERALIZEDTIME_adj()
functions set the time structure B<s> to the time represented
by the time B<offset_day> and B<offset_sec> after the time_t value B<t>.
The values of B<offset_day> or B<offset_sec> can be negative to set a
time before B<t>. The B<offset_sec> value can also exceed the number of
seconds in a day. If B<s> is NULL a new structure is allocated
and returned.
The ASN1_TIME_set_string(), ASN1_UTCTIME_set_string() and
ASN1_GENERALIZEDTIME_set_string() functions set the time structure B<s>
to the time represented by string B<str> which must be in appropriate ASN.1
time format (for example YYMMDDHHMMSSZ or YYYYMMDDHHMMSSZ). If B<s> is NULL
this function performs a format check on B<str> only. The string B<str>
is copied into B<s>.
ASN1_TIME_set_string_X509() sets ASN1_TIME structure B<s> to the time
represented by string B<str> which must be in appropriate time format
that RFC 5280 requires, which means it only allows YYMMDDHHMMSSZ and
YYYYMMDDHHMMSSZ (leap second is rejected), all other ASN.1 time format
are not allowed. If B<s> is NULL this function performs a format check
on B<str> only.
The ASN1_TIME_normalize() function converts an ASN1_GENERALIZEDTIME or
ASN1_UTCTIME into a time value that can be used in a certificate. It
should be used after the ASN1_TIME_set_string() functions and before
ASN1_TIME_print() functions to get consistent (i.e. GMT) results.
The ASN1_TIME_check(), ASN1_UTCTIME_check() and ASN1_GENERALIZEDTIME_check()
functions check the syntax of the time structure B<s>.
The ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
functions print the time structure B<s> to BIO B<b> in human readable
format. It will be of the format MMM DD HH:MM:SS YYYY [GMT], for example
"Feb 3 00:55:52 2015 GMT" it does not include a newline. If the time
structure has invalid format it prints out "Bad time value" and returns
an error. The output for generalized time may include a fractional part
following the second.
ASN1_TIME_to_tm() converts the time B<s> to the standard B<tm> structure.
If B<s> is NULL, then the current time is converted. The output time is GMT.
The B<tm_sec>, B<tm_min>, B<tm_hour>, B<tm_mday>, B<tm_wday>, B<tm_yday>,
B<tm_mon> and B<tm_year> fields of B<tm> structure are set to proper values,
whereas all other fields are set to 0. If B<tm> is NULL this function performs
a format check on B<s> only. If B<s> is in Generalized format with fractional
seconds, e.g. YYYYMMDDHHMMSS.SSSZ, the fractional seconds will be lost while
converting B<s> to B<tm> structure.
ASN1_TIME_diff() sets B<*pday> and B<*psec> to the time difference between
B<from> and B<to>. If B<to> represents a time later than B<from> then
one or both (depending on the time difference) of B<*pday> and B<*psec>
will be positive. If B<to> represents a time earlier than B<from> then
one or both of B<*pday> and B<*psec> will be negative. If B<to> and B<from>
represent the same time then B<*pday> and B<*psec> will both be zero.
If both B<*pday> and B<*psec> are non-zero they will always have the same
sign. The value of B<*psec> will always be less than the number of seconds
in a day. If B<from> or B<to> is NULL the current time is used.
The ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() functions compare
the two times represented by the time structure B<s> and the time_t B<t>.
The ASN1_TIME_compare() function compares the two times represented by the
time structures B<a> and B<b>.
The ASN1_TIME_to_generalizedtime() function converts an ASN1_TIME to an
ASN1_GENERALIZEDTIME, regardless of year. If either B<out> or
B<*out> are NULL, then a new object is allocated and must be freed after use.
=head1 NOTES
The ASN1_TIME structure corresponds to the ASN.1 structure B<Time>
defined in RFC5280 et al. The time setting functions obey the rules outlined
in RFC5280: if the date can be represented by UTCTime it is used, else
GeneralizedTime is used.
The ASN1_TIME, ASN1_UTCTIME and ASN1_GENERALIZEDTIME structures are represented
as an ASN1_STRING internally and can be freed up using ASN1_STRING_free().
The ASN1_TIME structure can represent years from 0000 to 9999 but no attempt
is made to correct ancient calendar changes (for example from Julian to
Gregorian calendars).
ASN1_UTCTIME is limited to a year range of 1950 through 2049.
Some applications add offset times directly to a time_t value and pass the
results to ASN1_TIME_set() (or equivalent). This can cause problems as the
time_t value can overflow on some systems resulting in unexpected results.
New applications should use ASN1_TIME_adj() instead and pass the offset value
in the B<offset_sec> and B<offset_day> parameters instead of directly
manipulating a time_t value.
ASN1_TIME_adj() may change the type from ASN1_GENERALIZEDTIME to ASN1_UTCTIME,
or vice versa, based on the resulting year. The ASN1_GENERALIZEDTIME_adj() and
ASN1_UTCTIME_adj() functions will not modify the type of the return structure.
It is recommended that functions starting with ASN1_TIME be used instead of
those starting with ASN1_UTCTIME or ASN1_GENERALIZEDTIME. The functions
starting with ASN1_UTCTIME and ASN1_GENERALIZEDTIME act only on that specific
time format. The functions starting with ASN1_TIME will operate on either
format.
=head1 BUGS
ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print()
do not print out the time zone: it either prints out "GMT" or nothing. But all
certificates complying with RFC5280 et al use GMT anyway.
Use the ASN1_TIME_normalize() function to normalize the time value before
printing to get GMT results.
-=head1 EXAMPLES
-
-Set a time structure to one hour after the current time and print it out:
-
- #include <time.h>
- #include <openssl/asn1.h>
-
- ASN1_TIME *tm;
- time_t t;
- BIO *b;
-
- t = time(NULL);
- tm = ASN1_TIME_adj(NULL, t, 0, 60 * 60);
- b = BIO_new_fp(stdout, BIO_NOCLOSE);
- ASN1_TIME_print(b, tm);
- ASN1_STRING_free(tm);
- BIO_free(b);
-
-Determine if one time is later or sooner than the current time:
-
- int day, sec;
-
- if (!ASN1_TIME_diff(&day, &sec, NULL, to))
- /* Invalid time format */
-
- if (day > 0 || sec > 0)
- printf("Later\n");
- else if (day < 0 || sec < 0)
- printf("Sooner\n");
- else
- printf("Same\n");
-
=head1 RETURN VALUES
ASN1_TIME_set(), ASN1_UTCTIME_set(), ASN1_GENERALIZEDTIME_set(), ASN1_TIME_adj(),
ASN1_UTCTIME_adj and ASN1_GENERALIZEDTIME_set return a pointer to a time structure
or NULL if an error occurred.
ASN1_TIME_set_string(), ASN1_UTCTIME_set_string(), ASN1_GENERALIZEDTIME_set_string()
ASN1_TIME_set_string_X509() return 1 if the time value is successfully set and 0 otherwise.
ASN1_TIME_normalize() returns 1 on success, and 0 on error.
ASN1_TIME_check(), ASN1_UTCTIME_check and ASN1_GENERALIZEDTIME_check() return 1
if the structure is syntactically correct and 0 otherwise.
ASN1_TIME_print(), ASN1_UTCTIME_print() and ASN1_GENERALIZEDTIME_print() return 1
if the time is successfully printed out and 0 if an error occurred (I/O error or
invalid time format).
ASN1_TIME_to_tm() returns 1 if the time is successfully parsed and 0 if an
error occurred (invalid time format).
ASN1_TIME_diff() returns 1 for success and 0 for failure. It can fail if the
passed-in time structure has invalid syntax, for example.
ASN1_TIME_cmp_time_t() and ASN1_UTCTIME_cmp_time_t() return -1 if B<s> is
before B<t>, 0 if B<s> equals B<t>, or 1 if B<s> is after B<t>. -2 is returned
on error.
ASN1_TIME_compare() returns -1 if B<a> is before B<b>, 0 if B<a> equals B<b>, or 1 if B<a> is after B<b>. -2 is returned on error.
ASN1_TIME_to_generalizedtime() returns a pointer to
the appropriate time structure on success or NULL if an error occurred.
+=head1 EXAMPLES
+
+Set a time structure to one hour after the current time and print it out:
+
+ #include <time.h>
+ #include <openssl/asn1.h>
+
+ ASN1_TIME *tm;
+ time_t t;
+ BIO *b;
+
+ t = time(NULL);
+ tm = ASN1_TIME_adj(NULL, t, 0, 60 * 60);
+ b = BIO_new_fp(stdout, BIO_NOCLOSE);
+ ASN1_TIME_print(b, tm);
+ ASN1_STRING_free(tm);
+ BIO_free(b);
+
+Determine if one time is later or sooner than the current time:
+
+ int day, sec;
+
+ if (!ASN1_TIME_diff(&day, &sec, NULL, to))
+ /* Invalid time format */
+
+ if (day > 0 || sec > 0)
+ printf("Later\n");
+ else if (day < 0 || sec < 0)
+ printf("Sooner\n");
+ else
+ printf("Same\n");
+
=head1 HISTORY
The ASN1_TIME_to_tm() function was added in OpenSSL 1.1.1.
The ASN1_TIME_set_string_X509() function was added in OpenSSL 1.1.1.
The ASN1_TIME_normalize() function was added in OpenSSL 1.1.1.
The ASN1_TIME_cmp_time_t() function was added in OpenSSL 1.1.1.
The ASN1_TIME_compare() function was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/ASN1_generate_nconf.pod b/doc/man3/ASN1_generate_nconf.pod
index bf29af62f729..422bf7b7ed3d 100644
--- a/doc/man3/ASN1_generate_nconf.pod
+++ b/doc/man3/ASN1_generate_nconf.pod
@@ -1,270 +1,270 @@
=pod
=head1 NAME
ASN1_generate_nconf, ASN1_generate_v3 - ASN1 generation functions
=head1 SYNOPSIS
#include <openssl/asn1.h>
ASN1_TYPE *ASN1_generate_nconf(const char *str, CONF *nconf);
ASN1_TYPE *ASN1_generate_v3(const char *str, X509V3_CTX *cnf);
=head1 DESCRIPTION
These functions generate the ASN1 encoding of a string
in an B<ASN1_TYPE> structure.
B<str> contains the string to encode B<nconf> or B<cnf> contains
the optional configuration information where additional strings
will be read from. B<nconf> will typically come from a config
file whereas B<cnf> is obtained from an B<X509V3_CTX> structure
which will typically be used by X509 v3 certificate extension
functions. B<cnf> or B<nconf> can be set to B<NULL> if no additional
configuration will be used.
=head1 GENERATION STRING FORMAT
The actual data encoded is determined by the string B<str> and
the configuration information. The general format of the string
is:
=over 4
=item B<[modifier,]type[:value]>
=back
That is zero or more comma separated modifiers followed by a type
followed by an optional colon and a value. The formats of B<type>,
B<value> and B<modifier> are explained below.
=head2 Supported Types
The supported types are listed below. Unless otherwise specified
only the B<ASCII> format is permissible.
=over 4
=item B<BOOLEAN>, B<BOOL>
This encodes a boolean type. The B<value> string is mandatory and
should be B<TRUE> or B<FALSE>. Additionally B<TRUE>, B<true>, B<Y>,
B<y>, B<YES>, B<yes>, B<FALSE>, B<false>, B<N>, B<n>, B<NO> and B<no>
are acceptable.
=item B<NULL>
Encode the B<NULL> type, the B<value> string must not be present.
=item B<INTEGER>, B<INT>
Encodes an ASN1 B<INTEGER> type. The B<value> string represents
the value of the integer, it can be prefaced by a minus sign and
is normally interpreted as a decimal value unless the prefix B<0x>
is included.
=item B<ENUMERATED>, B<ENUM>
Encodes the ASN1 B<ENUMERATED> type, it is otherwise identical to
B<INTEGER>.
=item B<OBJECT>, B<OID>
Encodes an ASN1 B<OBJECT IDENTIFIER>, the B<value> string can be
a short name, a long name or numerical format.
=item B<UTCTIME>, B<UTC>
Encodes an ASN1 B<UTCTime> structure, the value should be in
the format B<YYMMDDHHMMSSZ>.
=item B<GENERALIZEDTIME>, B<GENTIME>
Encodes an ASN1 B<GeneralizedTime> structure, the value should be in
the format B<YYYYMMDDHHMMSSZ>.
=item B<OCTETSTRING>, B<OCT>
Encodes an ASN1 B<OCTET STRING>. B<value> represents the contents
of this structure, the format strings B<ASCII> and B<HEX> can be
used to specify the format of B<value>.
=item B<BITSTRING>, B<BITSTR>
Encodes an ASN1 B<BIT STRING>. B<value> represents the contents
of this structure, the format strings B<ASCII>, B<HEX> and B<BITLIST>
can be used to specify the format of B<value>.
If the format is anything other than B<BITLIST> the number of unused
bits is set to zero.
=item B<UNIVERSALSTRING>, B<UNIV>, B<IA5>, B<IA5STRING>, B<UTF8>,
B<UTF8String>, B<BMP>, B<BMPSTRING>, B<VISIBLESTRING>,
B<VISIBLE>, B<PRINTABLESTRING>, B<PRINTABLE>, B<T61>,
B<T61STRING>, B<TELETEXSTRING>, B<GeneralString>, B<NUMERICSTRING>,
B<NUMERIC>
These encode the corresponding string types. B<value> represents the
contents of this structure. The format can be B<ASCII> or B<UTF8>.
=item B<SEQUENCE>, B<SEQ>, B<SET>
Formats the result as an ASN1 B<SEQUENCE> or B<SET> type. B<value>
should be a section name which will contain the contents. The
field names in the section are ignored and the values are in the
generated string format. If B<value> is absent then an empty SEQUENCE
will be encoded.
=back
=head2 Modifiers
Modifiers affect the following structure, they can be used to
add EXPLICIT or IMPLICIT tagging, add wrappers or to change
the string format of the final type and value. The supported
formats are documented below.
=over 4
=item B<EXPLICIT>, B<EXP>
Add an explicit tag to the following structure. This string
should be followed by a colon and the tag value to use as a
decimal value.
By following the number with B<U>, B<A>, B<P> or B<C> UNIVERSAL,
APPLICATION, PRIVATE or CONTEXT SPECIFIC tagging can be used,
the default is CONTEXT SPECIFIC.
=item B<IMPLICIT>, B<IMP>
This is the same as B<EXPLICIT> except IMPLICIT tagging is used
instead.
=item B<OCTWRAP>, B<SEQWRAP>, B<SETWRAP>, B<BITWRAP>
The following structure is surrounded by an OCTET STRING, a SEQUENCE,
a SET or a BIT STRING respectively. For a BIT STRING the number of unused
bits is set to zero.
=item B<FORMAT>
This specifies the format of the ultimate value. It should be followed
by a colon and one of the strings B<ASCII>, B<UTF8>, B<HEX> or B<BITLIST>.
If no format specifier is included then B<ASCII> is used. If B<UTF8> is
specified then the value string must be a valid B<UTF8> string. For B<HEX> the
output must be a set of hex digits. B<BITLIST> (which is only valid for a BIT
STRING) is a comma separated list of the indices of the set bits, all other
bits are zero.
=back
+=head1 RETURN VALUES
+
+ASN1_generate_nconf() and ASN1_generate_v3() return the encoded
+data as an B<ASN1_TYPE> structure or B<NULL> if an error occurred.
+
+The error codes that can be obtained by L<ERR_get_error(3)>.
+
=head1 EXAMPLES
A simple IA5String:
IA5STRING:Hello World
An IA5String explicitly tagged:
EXPLICIT:0,IA5STRING:Hello World
An IA5String explicitly tagged using APPLICATION tagging:
EXPLICIT:0A,IA5STRING:Hello World
A BITSTRING with bits 1 and 5 set and all others zero:
FORMAT:BITLIST,BITSTRING:1,5
A more complex example using a config file to produce a
SEQUENCE consisting of a BOOL an OID and a UTF8String:
asn1 = SEQUENCE:seq_section
[seq_section]
field1 = BOOLEAN:TRUE
field2 = OID:commonName
field3 = UTF8:Third field
This example produces an RSAPrivateKey structure, this is the
key contained in the file client.pem in all OpenSSL distributions
(note: the field names such as 'coeff' are ignored and are present just
for clarity):
asn1=SEQUENCE:private_key
[private_key]
version=INTEGER:0
n=INTEGER:0xBB6FE79432CC6EA2D8F970675A5A87BFBE1AFF0BE63E879F2AFFB93644\
D4D2C6D000430DEC66ABF47829E74B8C5108623A1C0EE8BE217B3AD8D36D5EB4FCA1D9
e=INTEGER:0x010001
d=INTEGER:0x6F05EAD2F27FFAEC84BEC360C4B928FD5F3A9865D0FCAAD291E2A52F4A\
F810DC6373278C006A0ABBA27DC8C63BF97F7E666E27C5284D7D3B1FFFE16B7A87B51D
p=INTEGER:0xF3929B9435608F8A22C208D86795271D54EBDFB09DDEF539AB083DA912\
D4BD57
q=INTEGER:0xC50016F89DFF2561347ED1186A46E150E28BF2D0F539A1594BBD7FE467\
46EC4F
exp1=INTEGER:0x9E7D4326C924AFC1DEA40B45650134966D6F9DFA3A7F9D698CD4ABEA\
9C0A39B9
exp2=INTEGER:0xBA84003BB95355AFB7C50DF140C60513D0BA51D637272E355E397779\
E7B2458F
coeff=INTEGER:0x30B9E4F2AFA5AC679F920FC83F1F2DF1BAF1779CF989447FABC2F5\
628657053A
This example is the corresponding public key in a SubjectPublicKeyInfo
structure:
# Start with a SEQUENCE
asn1=SEQUENCE:pubkeyinfo
# pubkeyinfo contains an algorithm identifier and the public key wrapped
# in a BIT STRING
[pubkeyinfo]
algorithm=SEQUENCE:rsa_alg
pubkey=BITWRAP,SEQUENCE:rsapubkey
# algorithm ID for RSA is just an OID and a NULL
[rsa_alg]
algorithm=OID:rsaEncryption
parameter=NULL
# Actual public key: modulus and exponent
[rsapubkey]
n=INTEGER:0xBB6FE79432CC6EA2D8F970675A5A87BFBE1AFF0BE63E879F2AFFB93644\
D4D2C6D000430DEC66ABF47829E74B8C5108623A1C0EE8BE217B3AD8D36D5EB4FCA1D9
e=INTEGER:0x010001
-=head1 RETURN VALUES
-
-ASN1_generate_nconf() and ASN1_generate_v3() return the encoded
-data as an B<ASN1_TYPE> structure or B<NULL> if an error occurred.
-
-The error codes that can be obtained by L<ERR_get_error(3)>.
-
=head1 SEE ALSO
L<ERR_get_error(3)>
=head1 COPYRIGHT
-Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/BIO_connect.pod b/doc/man3/BIO_connect.pod
index 454832e7e032..2766c3d6c5b7 100644
--- a/doc/man3/BIO_connect.pod
+++ b/doc/man3/BIO_connect.pod
@@ -1,117 +1,117 @@
=pod
=head1 NAME
BIO_socket, BIO_bind, BIO_connect, BIO_listen, BIO_accept_ex, BIO_closesocket - BIO
socket communication setup routines
=head1 SYNOPSIS
#include <openssl/bio.h>
int BIO_socket(int domain, int socktype, int protocol, int options);
int BIO_bind(int sock, const BIO_ADDR *addr, int options);
int BIO_connect(int sock, const BIO_ADDR *addr, int options);
int BIO_listen(int sock, const BIO_ADDR *addr, int options);
int BIO_accept_ex(int accept_sock, BIO_ADDR *peer, int options);
int BIO_closesocket(int sock);
=head1 DESCRIPTION
BIO_socket() creates a socket in the domain B<domain>, of type
B<socktype> and B<protocol>. Socket B<options> are currently unused,
but is present for future use.
BIO_bind() binds the source address and service to a socket and
may be useful before calling BIO_connect(). The options may include
B<BIO_SOCK_REUSADDR>, which is described in L</FLAGS> below.
BIO_connect() connects B<sock> to the address and service given by
B<addr>. Connection B<options> may be zero or any combination of
B<BIO_SOCK_KEEPALIVE>, B<BIO_SOCK_NONBLOCK> and B<BIO_SOCK_NODELAY>.
The flags are described in L</FLAGS> below.
BIO_listen() has B<sock> start listening on the address and service
given by B<addr>. Connection B<options> may be zero or any
combination of B<BIO_SOCK_KEEPALIVE>, B<BIO_SOCK_NONBLOCK>,
B<BIO_SOCK_NODELAY>, B<BIO_SOCK_REUSEADDR> and B<BIO_SOCK_V6_ONLY>.
The flags are described in L</FLAGS> below.
BIO_accept_ex() waits for an incoming connections on the given
socket B<accept_sock>. When it gets a connection, the address and
port of the peer gets stored in B<peer> if that one is non-NULL.
Accept B<options> may be zero or B<BIO_SOCK_NONBLOCK>, and is applied
on the accepted socket. The flags are described in L</FLAGS> below.
BIO_closesocket() closes B<sock>.
=head1 FLAGS
=over 4
=item BIO_SOCK_KEEPALIVE
Enables regular sending of keep-alive messages.
=item BIO_SOCK_NONBLOCK
Sets the socket to non-blocking mode.
=item BIO_SOCK_NODELAY
Corresponds to B<TCP_NODELAY>, and disables the Nagle algorithm. With
this set, any data will be sent as soon as possible instead of being
buffered until there's enough for the socket to send out in one go.
=item BIO_SOCK_REUSEADDR
Try to reuse the address and port combination for a recently closed
port.
=item BIO_SOCK_V6_ONLY
When creating an IPv6 socket, make it only listen for IPv6 addresses
and not IPv4 addresses mapped to IPv6.
=back
These flags are bit flags, so they are to be combined with the
C<|> operator, for example:
BIO_connect(sock, addr, BIO_SOCK_KEEPALIVE | BIO_SOCK_NONBLOCK);
=head1 RETURN VALUES
BIO_socket() returns the socket number on success or B<INVALID_SOCKET>
(-1) on error. When an error has occurred, the OpenSSL error stack
will hold the error data and errno has the system error.
BIO_bind(), BIO_connect() and BIO_listen() return 1 on success or 0 on error.
When an error has occurred, the OpenSSL error stack will hold the error
data and errno has the system error.
BIO_accept_ex() returns the accepted socket on success or
B<INVALID_SOCKET> (-1) on error. When an error has occurred, the
OpenSSL error stack will hold the error data and errno has the system
error.
-=head1 HISTORY
-
-BIO_gethostname(), BIO_get_port(), BIO_get_host_ip(),
-BIO_get_accept_socket() and BIO_accept() were deprecated in
-OpenSSL 1.1.0. Use the functions described above instead.
-
=head1 SEE ALSO
L<BIO_ADDR(3)>
+=head1 HISTORY
+
+BIO_gethostname(), BIO_get_port(), BIO_get_host_ip(),
+BIO_get_accept_socket() and BIO_accept() were deprecated in OpenSSL 1.1.0.
+Use the functions described above instead.
+
=head1 COPYRIGHT
-Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/BIO_push.pod b/doc/man3/BIO_push.pod
index ce56db9836ff..93f2cc31fdae 100644
--- a/doc/man3/BIO_push.pod
+++ b/doc/man3/BIO_push.pod
@@ -1,89 +1,89 @@
=pod
=head1 NAME
BIO_push, BIO_pop, BIO_set_next - add and remove BIOs from a chain
=head1 SYNOPSIS
#include <openssl/bio.h>
BIO *BIO_push(BIO *b, BIO *append);
BIO *BIO_pop(BIO *b);
void BIO_set_next(BIO *b, BIO *next);
=head1 DESCRIPTION
The BIO_push() function appends the BIO B<append> to B<b>, it returns
B<b>.
BIO_pop() removes the BIO B<b> from a chain and returns the next BIO
in the chain, or NULL if there is no next BIO. The removed BIO then
becomes a single BIO with no association with the original chain,
it can thus be freed or attached to a different chain.
BIO_set_next() replaces the existing next BIO in a chain with the BIO pointed to
by B<next>. The new chain may include some of the same BIOs from the old chain
or it may be completely different.
=head1 NOTES
The names of these functions are perhaps a little misleading. BIO_push()
joins two BIO chains whereas BIO_pop() deletes a single BIO from a chain,
the deleted BIO does not need to be at the end of a chain.
The process of calling BIO_push() and BIO_pop() on a BIO may have additional
consequences (a control call is made to the affected BIOs) any effects will
be noted in the descriptions of individual BIOs.
+=head1 RETURN VALUES
+
+BIO_push() returns the end of the chain, B<b>.
+
+BIO_pop() returns the next BIO in the chain, or NULL if there is no next
+BIO.
+
=head1 EXAMPLES
For these examples suppose B<md1> and B<md2> are digest BIOs, B<b64> is
a base64 BIO and B<f> is a file BIO.
If the call:
BIO_push(b64, f);
is made then the new chain will be B<b64-f>. After making the calls
BIO_push(md2, b64);
BIO_push(md1, md2);
the new chain is B<md1-md2-b64-f>. Data written to B<md1> will be digested
by B<md1> and B<md2>, B<base64> encoded and written to B<f>.
It should be noted that reading causes data to pass in the reverse
direction, that is data is read from B<f>, base64 B<decoded> and digested
by B<md1> and B<md2>. If the call:
BIO_pop(md2);
The call will return B<b64> and the new chain will be B<md1-b64-f> data can
be written to B<md1> as before.
-=head1 RETURN VALUES
-
-BIO_push() returns the end of the chain, B<b>.
-
-BIO_pop() returns the next BIO in the chain, or NULL if there is no next
-BIO.
-
=head1 SEE ALSO
L<bio>
=head1 HISTORY
The BIO_set_next() function was added in OpenSSL 1.1.0.
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/BIO_s_file.pod b/doc/man3/BIO_s_file.pod
index 23cdc9b684a6..2ed0bb3c0f35 100644
--- a/doc/man3/BIO_s_file.pod
+++ b/doc/man3/BIO_s_file.pod
@@ -1,168 +1,168 @@
=pod
=head1 NAME
BIO_s_file, BIO_new_file, BIO_new_fp, BIO_set_fp, BIO_get_fp,
BIO_read_filename, BIO_write_filename, BIO_append_filename,
BIO_rw_filename - FILE bio
=head1 SYNOPSIS
#include <openssl/bio.h>
const BIO_METHOD *BIO_s_file(void);
BIO *BIO_new_file(const char *filename, const char *mode);
BIO *BIO_new_fp(FILE *stream, int flags);
BIO_set_fp(BIO *b, FILE *fp, int flags);
BIO_get_fp(BIO *b, FILE **fpp);
int BIO_read_filename(BIO *b, char *name)
int BIO_write_filename(BIO *b, char *name)
int BIO_append_filename(BIO *b, char *name)
int BIO_rw_filename(BIO *b, char *name)
=head1 DESCRIPTION
BIO_s_file() returns the BIO file method. As its name implies it
is a wrapper round the stdio FILE structure and it is a
source/sink BIO.
Calls to BIO_read_ex() and BIO_write_ex() read and write data to the
underlying stream. BIO_gets() and BIO_puts() are supported on file BIOs.
BIO_flush() on a file BIO calls the fflush() function on the wrapped
stream.
BIO_reset() attempts to change the file pointer to the start of file
using fseek(stream, 0, 0).
BIO_seek() sets the file pointer to position B<ofs> from start of file
using fseek(stream, ofs, 0).
BIO_eof() calls feof().
Setting the BIO_CLOSE flag calls fclose() on the stream when the BIO
is freed.
BIO_new_file() creates a new file BIO with mode B<mode> the meaning
of B<mode> is the same as the stdio function fopen(). The BIO_CLOSE
flag is set on the returned BIO.
BIO_new_fp() creates a file BIO wrapping B<stream>. Flags can be:
BIO_CLOSE, BIO_NOCLOSE (the close flag) BIO_FP_TEXT (sets the underlying
stream to text mode, default is binary: this only has any effect under
Win32).
BIO_set_fp() sets the fp of a file BIO to B<fp>. B<flags> has the same
meaning as in BIO_new_fp(), it is a macro.
BIO_get_fp() retrieves the fp of a file BIO, it is a macro.
BIO_seek() is a macro that sets the position pointer to B<offset> bytes
from the start of file.
BIO_tell() returns the value of the position pointer.
BIO_read_filename(), BIO_write_filename(), BIO_append_filename() and
BIO_rw_filename() set the file BIO B<b> to use file B<name> for
reading, writing, append or read write respectively.
=head1 NOTES
When wrapping stdout, stdin or stderr the underlying stream should not
normally be closed so the BIO_NOCLOSE flag should be set.
Because the file BIO calls the underlying stdio functions any quirks
in stdio behaviour will be mirrored by the corresponding BIO.
On Windows BIO_new_files reserves for the filename argument to be
UTF-8 encoded. In other words if you have to make it work in multi-
lingual environment, encode file names in UTF-8.
+=head1 RETURN VALUES
+
+BIO_s_file() returns the file BIO method.
+
+BIO_new_file() and BIO_new_fp() return a file BIO or NULL if an error
+occurred.
+
+BIO_set_fp() and BIO_get_fp() return 1 for success or 0 for failure
+(although the current implementation never return 0).
+
+BIO_seek() returns the same value as the underlying fseek() function:
+0 for success or -1 for failure.
+
+BIO_tell() returns the current file position.
+
+BIO_read_filename(), BIO_write_filename(), BIO_append_filename() and
+BIO_rw_filename() return 1 for success or 0 for failure.
+
=head1 EXAMPLES
File BIO "hello world":
BIO *bio_out;
bio_out = BIO_new_fp(stdout, BIO_NOCLOSE);
BIO_printf(bio_out, "Hello World\n");
Alternative technique:
BIO *bio_out;
bio_out = BIO_new(BIO_s_file());
if (bio_out == NULL)
/* Error */
if (!BIO_set_fp(bio_out, stdout, BIO_NOCLOSE))
/* Error */
BIO_printf(bio_out, "Hello World\n");
Write to a file:
BIO *out;
out = BIO_new_file("filename.txt", "w");
if (!out)
/* Error */
BIO_printf(out, "Hello World\n");
BIO_free(out);
Alternative technique:
BIO *out;
out = BIO_new(BIO_s_file());
if (out == NULL)
/* Error */
if (!BIO_write_filename(out, "filename.txt"))
/* Error */
BIO_printf(out, "Hello World\n");
BIO_free(out);
-=head1 RETURN VALUES
-
-BIO_s_file() returns the file BIO method.
-
-BIO_new_file() and BIO_new_fp() return a file BIO or NULL if an error
-occurred.
-
-BIO_set_fp() and BIO_get_fp() return 1 for success or 0 for failure
-(although the current implementation never return 0).
-
-BIO_seek() returns the same value as the underlying fseek() function:
-0 for success or -1 for failure.
-
-BIO_tell() returns the current file position.
-
-BIO_read_filename(), BIO_write_filename(), BIO_append_filename() and
-BIO_rw_filename() return 1 for success or 0 for failure.
-
=head1 BUGS
BIO_reset() and BIO_seek() are implemented using fseek() on the underlying
stream. The return value for fseek() is 0 for success or -1 if an error
occurred this differs from other types of BIO which will typically return
1 for success and a non positive value if an error occurred.
=head1 SEE ALSO
L<BIO_seek(3)>, L<BIO_tell(3)>,
L<BIO_reset(3)>, L<BIO_flush(3)>,
L<BIO_read_ex(3)>,
L<BIO_write_ex(3)>, L<BIO_puts(3)>,
L<BIO_gets(3)>, L<BIO_printf(3)>,
L<BIO_set_close(3)>, L<BIO_get_close(3)>
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/BIO_s_mem.pod b/doc/man3/BIO_s_mem.pod
index 050d7786a6cf..2a5d423648db 100644
--- a/doc/man3/BIO_s_mem.pod
+++ b/doc/man3/BIO_s_mem.pod
@@ -1,134 +1,150 @@
=pod
=head1 NAME
BIO_s_secmem,
BIO_s_mem, BIO_set_mem_eof_return, BIO_get_mem_data, BIO_set_mem_buf,
BIO_get_mem_ptr, BIO_new_mem_buf - memory BIO
=head1 SYNOPSIS
#include <openssl/bio.h>
const BIO_METHOD *BIO_s_mem(void);
const BIO_METHOD *BIO_s_secmem(void);
BIO_set_mem_eof_return(BIO *b, int v)
long BIO_get_mem_data(BIO *b, char **pp)
BIO_set_mem_buf(BIO *b, BUF_MEM *bm, int c)
BIO_get_mem_ptr(BIO *b, BUF_MEM **pp)
BIO *BIO_new_mem_buf(const void *buf, int len);
=head1 DESCRIPTION
BIO_s_mem() returns the memory BIO method function.
A memory BIO is a source/sink BIO which uses memory for its I/O. Data
written to a memory BIO is stored in a BUF_MEM structure which is extended
as appropriate to accommodate the stored data.
BIO_s_secmem() is like BIO_s_mem() except that the secure heap is used
for buffer storage.
Any data written to a memory BIO can be recalled by reading from it.
Unless the memory BIO is read only any data read from it is deleted from
the BIO.
Memory BIOs support BIO_gets() and BIO_puts().
If the BIO_CLOSE flag is set when a memory BIO is freed then the underlying
BUF_MEM structure is also freed.
Calling BIO_reset() on a read write memory BIO clears any data in it if the
flag BIO_FLAGS_NONCLEAR_RST is not set. On a read only BIO or if the flag
BIO_FLAGS_NONCLEAR_RST is set it restores the BIO to its original state and
the data can be read again.
BIO_eof() is true if no data is in the BIO.
BIO_ctrl_pending() returns the number of bytes currently stored.
BIO_set_mem_eof_return() sets the behaviour of memory BIO B<b> when it is
empty. If the B<v> is zero then an empty memory BIO will return EOF (that is
it will return zero and BIO_should_retry(b) will be false. If B<v> is non
zero then it will return B<v> when it is empty and it will set the read retry
flag (that is BIO_read_retry(b) is true). To avoid ambiguity with a normal
positive return value B<v> should be set to a negative value, typically -1.
BIO_get_mem_data() sets *B<pp> to a pointer to the start of the memory BIOs data
and returns the total amount of data available. It is implemented as a macro.
BIO_set_mem_buf() sets the internal BUF_MEM structure to B<bm> and sets the
close flag to B<c>, that is B<c> should be either BIO_CLOSE or BIO_NOCLOSE.
It is a macro.
BIO_get_mem_ptr() places the underlying BUF_MEM structure in *B<pp>. It is
a macro.
BIO_new_mem_buf() creates a memory BIO using B<len> bytes of data at B<buf>,
if B<len> is -1 then the B<buf> is assumed to be nul terminated and its
length is determined by B<strlen>. The BIO is set to a read only state and
as a result cannot be written to. This is useful when some data needs to be
made available from a static area of memory in the form of a BIO. The
supplied data is read directly from the supplied buffer: it is B<not> copied
first, so the supplied area of memory must be unchanged until the BIO is freed.
=head1 NOTES
Writes to memory BIOs will always succeed if memory is available: that is
their size can grow indefinitely.
Every read from a read write memory BIO will remove the data just read with
an internal copy operation, if a BIO contains a lot of data and it is
read in small chunks the operation can be very slow. The use of a read only
memory BIO avoids this problem. If the BIO must be read write then adding
a buffering BIO to the chain will speed up the process.
Calling BIO_set_mem_buf() on a BIO created with BIO_new_secmem() will
give undefined results, including perhaps a program crash.
+Switching the memory BIO from read write to read only is not supported and
+can give undefined results including a program crash. There are two notable
+exceptions to the rule. The first one is to assign a static memory buffer
+immediately after BIO creation and set the BIO as read only.
+
+The other supported sequence is to start with read write BIO then temporarily
+switch it to read only and call BIO_reset() on the read only BIO immediately
+before switching it back to read write. Before the BIO is freed it must be
+switched back to the read write mode.
+
+Calling BIO_get_mem_ptr() on read only BIO will return a BUF_MEM that
+contains only the remaining data to be read. If the close status of the
+BIO is set to BIO_NOCLOSE, before freeing the BUF_MEM the data pointer
+in it must be set to NULL as the data pointer does not point to an
+allocated memory.
+
=head1 BUGS
There should be an option to set the maximum size of a memory BIO.
=head1 EXAMPLE
Create a memory BIO and write some data to it:
BIO *mem = BIO_new(BIO_s_mem());
BIO_puts(mem, "Hello World\n");
Create a read only memory BIO:
char data[] = "Hello World";
BIO *mem = BIO_new_mem_buf(data, -1);
Extract the BUF_MEM structure from a memory BIO and then free up the BIO:
BUF_MEM *bptr;
BIO_get_mem_ptr(mem, &bptr);
BIO_set_close(mem, BIO_NOCLOSE); /* So BIO_free() leaves BUF_MEM alone */
BIO_free(mem);
=head1 RETURN VALUES
BIO_s_mem() and BIO_s_secmem() return a valid memory B<BIO_METHOD> structure.
BIO_set_mem_eof_return(), BIO_get_mem_data(), BIO_set_mem_buf() and BIO_get_mem_ptr()
return 1 on success or a value which is less than or equal to 0 if an error occurred.
BIO_new_mem_buf() returns a valid B<BIO> structure on success or NULL on error.
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/BN_CTX_start.pod b/doc/man3/BN_CTX_start.pod
index 372da506d9d3..bb039e5539cd 100644
--- a/doc/man3/BN_CTX_start.pod
+++ b/doc/man3/BN_CTX_start.pod
@@ -1,57 +1,58 @@
=pod
=head1 NAME
BN_CTX_start, BN_CTX_get, BN_CTX_end - use temporary BIGNUM variables
=head1 SYNOPSIS
#include <openssl/bn.h>
void BN_CTX_start(BN_CTX *ctx);
BIGNUM *BN_CTX_get(BN_CTX *ctx);
void BN_CTX_end(BN_CTX *ctx);
=head1 DESCRIPTION
These functions are used to obtain temporary B<BIGNUM> variables from
a B<BN_CTX> (which can been created by using L<BN_CTX_new(3)>)
in order to save the overhead of repeatedly creating and
freeing B<BIGNUM>s in functions that are called from inside a loop.
A function must call BN_CTX_start() first. Then, BN_CTX_get() may be
called repeatedly to obtain temporary B<BIGNUM>s. All BN_CTX_get()
calls must be made before calling any other functions that use the
B<ctx> as an argument.
Finally, BN_CTX_end() must be called before returning from the function.
+If B<ctx> is NULL, nothing is done.
When BN_CTX_end() is called, the B<BIGNUM> pointers obtained from
BN_CTX_get() become invalid.
=head1 RETURN VALUES
BN_CTX_start() and BN_CTX_end() return no values.
BN_CTX_get() returns a pointer to the B<BIGNUM>, or B<NULL> on error.
Once BN_CTX_get() has failed, the subsequent calls will return B<NULL>
as well, so it is sufficient to check the return value of the last
BN_CTX_get() call. In case of an error, an error code is set, which
can be obtained by L<ERR_get_error(3)>.
=head1 SEE ALSO
L<BN_CTX_new(3)>
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/BN_new.pod b/doc/man3/BN_new.pod
index 08aae5e91915..1fab6d26eb19 100644
--- a/doc/man3/BN_new.pod
+++ b/doc/man3/BN_new.pod
@@ -1,63 +1,64 @@
=pod
=head1 NAME
BN_new, BN_secure_new, BN_clear, BN_free, BN_clear_free - allocate and free BIGNUMs
=head1 SYNOPSIS
#include <openssl/bn.h>
BIGNUM *BN_new(void);
BIGNUM *BN_secure_new(void);
void BN_clear(BIGNUM *a);
void BN_free(BIGNUM *a);
void BN_clear_free(BIGNUM *a);
=head1 DESCRIPTION
BN_new() allocates and initializes a B<BIGNUM> structure.
BN_secure_new() does the same except that the secure heap
OPENSSL_secure_malloc(3) is used to store the value.
BN_clear() is used to destroy sensitive data such as keys when they
are no longer needed. It erases the memory used by B<a> and sets it
to the value 0.
+If B<a> is NULL, nothing is done.
BN_free() frees the components of the B<BIGNUM>, and if it was created
by BN_new(), also the structure itself. BN_clear_free() additionally
overwrites the data before the memory is returned to the system.
If B<a> is NULL, nothing is done.
=head1 RETURN VALUES
BN_new() and BN_secure_new()
return a pointer to the B<BIGNUM> initialised to the value 0.
If the allocation fails,
they return B<NULL> and set an error code that can be obtained
by L<ERR_get_error(3)>.
BN_clear(), BN_free() and BN_clear_free() have no return values.
=head1 SEE ALSO
L<ERR_get_error(3)>
=head1 HISTORY
BN_init() was removed in OpenSSL 1.1.0; use BN_new() instead.
=head1 COPYRIGHT
-Copyright 2000-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/BN_rand.pod b/doc/man3/BN_rand.pod
index 90b50ffc311e..d57348e62b8c 100644
--- a/doc/man3/BN_rand.pod
+++ b/doc/man3/BN_rand.pod
@@ -1,99 +1,99 @@
=pod
=head1 NAME
BN_rand, BN_priv_rand, BN_pseudo_rand,
BN_rand_range, BN_priv_rand_range, BN_pseudo_rand_range
- generate pseudo-random number
=head1 SYNOPSIS
#include <openssl/bn.h>
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
int BN_priv_rand(BIGNUM *rnd, int bits, int top, int bottom);
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
int BN_rand_range(BIGNUM *rnd, BIGNUM *range);
int BN_priv_rand_range(BIGNUM *rnd, BIGNUM *range);
int BN_pseudo_rand_range(BIGNUM *rnd, BIGNUM *range);
=head1 DESCRIPTION
BN_rand() generates a cryptographically strong pseudo-random number of
B<bits> in length and stores it in B<rnd>.
If B<bits> is less than zero, or too small to
accommodate the requirements specified by the B<top> and B<bottom>
parameters, an error is returned.
The B<top> parameters specifies
requirements on the most significant bit of the generated number.
If it is B<BN_RAND_TOP_ANY>, there is no constraint.
If it is B<BN_RAND_TOP_ONE>, the top bit must be one.
If it is B<BN_RAND_TOP_TWO>, the two most significant bits of
the number will be set to 1, so that the product of two such random
numbers will always have 2*B<bits> length.
If B<bottom> is B<BN_RAND_BOTTOM_ODD>, the number will be odd; if it
is B<BN_RAND_BOTTOM_ANY> it can be odd or even.
If B<bits> is 1 then B<top> cannot also be B<BN_RAND_FLG_TOPTWO>.
BN_rand_range() generates a cryptographically strong pseudo-random
number B<rnd> in the range 0 E<lt>= B<rnd> E<lt> B<range>.
BN_priv_rand() and BN_priv_rand_range() have the same semantics as
BN_rand() and BN_rand_range() respectively. They are intended to be
used for generating values that should remain private, and mirror the
same difference between L<RAND_bytes(3)> and L<RAND_priv_bytes(3)>.
=head1 NOTES
Always check the error return value of these functions and do not take
randomness for granted: an error occurs if the CSPRNG has not been
seeded with enough randomness to ensure an unpredictable byte sequence.
=head1 RETURN VALUES
The functions return 1 on success, 0 on error.
The error codes can be obtained by L<ERR_get_error(3)>.
+=head1 SEE ALSO
+
+L<ERR_get_error(3)>,
+L<RAND_add(3)>,
+L<RAND_bytes(3)>,
+L<RAND_priv_bytes(3)>,
+L<RAND(7)>,
+L<RAND_DRBG(7)>
+
=head1 HISTORY
=over 2
=item *
Starting with OpenSSL release 1.1.0, BN_pseudo_rand() has been identical
to BN_rand() and BN_pseudo_rand_range() has been identical to
BN_rand_range().
The "pseudo" functions should not be used and may be deprecated in
a future release.
=item *
The
BN_priv_rand() and BN_priv_rand_range() functions were added in OpenSSL 1.1.1.
=back
-=head1 SEE ALSO
-
-L<ERR_get_error(3)>,
-L<RAND_add(3)>,
-L<RAND_bytes(3)>,
-L<RAND_priv_bytes(3)>,
-L<RAND(7)>,
-L<RAND_DRBG(7)>
-
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/BN_security_bits.pod b/doc/man3/BN_security_bits.pod
index f6e5857a4eed..acf59027ba24 100644
--- a/doc/man3/BN_security_bits.pod
+++ b/doc/man3/BN_security_bits.pod
@@ -1,51 +1,51 @@
=pod
=head1 NAME
BN_security_bits - returns bits of security based on given numbers
=head1 SYNOPSIS
#include <openssl/bn.h>
int BN_security_bits(int L, int N);
=head1 DESCRIPTION
BN_security_bits() returns the number of bits of security provided by a
specific algorithm and a particular key size. The bits of security is
defined in NIST SP800-57. Currently, BN_security_bits() support two types
of asymmetric algorithms: the FFC (Finite Field Cryptography) and IFC
(Integer Factorization Cryptography). For FFC, e.g., DSA and DH, both
parameters B<L> and B<N> are used to decide the bits of security, where
B<L> is the size of the public key and B<N> is the size of the private
key. For IFC, e.g., RSA, only B<L> is used and it's commonly considered
to be the key size (modulus).
=head1 RETURN VALUES
Number of security bits.
=head1 NOTES
ECC (Elliptic Curve Cryptography) is not covered by the BN_security_bits()
function. The symmetric algorithms are not covered neither.
-=head1 HISTORY
-
-The BN_security_bits() function was added in OpenSSL 1.1.0.
-
=head1 SEE ALSO
L<DH_security_bits(3)>, L<DSA_security_bits(3)>, L<RSA_security_bits(3)>
+=head1 HISTORY
+
+The BN_security_bits() function was added in OpenSSL 1.1.0.
+
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/CMS_verify.pod b/doc/man3/CMS_verify.pod
index 7187d9840ab6..be688681cbc6 100644
--- a/doc/man3/CMS_verify.pod
+++ b/doc/man3/CMS_verify.pod
@@ -1,132 +1,132 @@
=pod
=head1 NAME
CMS_verify, CMS_get0_signers - verify a CMS SignedData structure
=head1 SYNOPSIS
#include <openssl/cms.h>
int CMS_verify(CMS_ContentInfo *cms, STACK_OF(X509) *certs, X509_STORE *store,
BIO *indata, BIO *out, unsigned int flags);
STACK_OF(X509) *CMS_get0_signers(CMS_ContentInfo *cms);
=head1 DESCRIPTION
CMS_verify() verifies a CMS SignedData structure. B<cms> is the CMS_ContentInfo
structure to verify. B<certs> is a set of certificates in which to search for
the signing certificate(s). B<store> is a trusted certificate store used for
chain verification. B<indata> is the detached content if the content is not
present in B<cms>. The content is written to B<out> if it is not NULL.
B<flags> is an optional set of flags, which can be used to modify the verify
operation.
CMS_get0_signers() retrieves the signing certificate(s) from B<cms>, it must
be called after a successful CMS_verify() operation.
=head1 VERIFY PROCESS
Normally the verify process proceeds as follows.
Initially some sanity checks are performed on B<cms>. The type of B<cms> must
be SignedData. There must be at least one signature on the data and if
the content is detached B<indata> cannot be B<NULL>.
An attempt is made to locate all the signing certificate(s), first looking in
the B<certs> parameter (if it is not NULL) and then looking in any
certificates contained in the B<cms> structure itself. If any signing
certificate cannot be located the operation fails.
Each signing certificate is chain verified using the B<smimesign> purpose and
the supplied trusted certificate store. Any internal certificates in the message
are used as untrusted CAs. If CRL checking is enabled in B<store> any internal
CRLs are used in addition to attempting to look them up in B<store>. If any
chain verify fails an error code is returned.
-Finally the signed content is read (and written to B<out> is it is not NULL)
+Finally the signed content is read (and written to B<out> if it is not NULL)
and the signature's checked.
If all signature's verify correctly then the function is successful.
Any of the following flags (ored together) can be passed in the B<flags>
parameter to change the default verify behaviour.
If B<CMS_NOINTERN> is set the certificates in the message itself are not
searched when locating the signing certificate(s). This means that all the
signing certificates must be in the B<certs> parameter.
If B<CMS_NOCRL> is set and CRL checking is enabled in B<store> then any
CRLs in the message itself are ignored.
If the B<CMS_TEXT> flag is set MIME headers for type B<text/plain> are deleted
from the content. If the content is not of type B<text/plain> then an error is
returned.
If B<CMS_NO_SIGNER_CERT_VERIFY> is set the signing certificates are not
verified.
If B<CMS_NO_ATTR_VERIFY> is set the signed attributes signature is not
verified.
If B<CMS_NO_CONTENT_VERIFY> is set then the content digest is not checked.
=head1 NOTES
One application of B<CMS_NOINTERN> is to only accept messages signed by
a small number of certificates. The acceptable certificates would be passed
in the B<certs> parameter. In this case if the signer is not one of the
certificates supplied in B<certs> then the verify will fail because the
signer cannot be found.
In some cases the standard techniques for looking up and validating
certificates are not appropriate: for example an application may wish to
lookup certificates in a database or perform customised verification. This
can be achieved by setting and verifying the signers certificates manually
using the signed data utility functions.
Care should be taken when modifying the default verify behaviour, for example
setting B<CMS_NO_CONTENT_VERIFY> will totally disable all content verification
and any modified content will be considered valid. This combination is however
useful if one merely wishes to write the content to B<out> and its validity
is not considered important.
Chain verification should arguably be performed using the signing time rather
than the current time. However since the signing time is supplied by the
signer it cannot be trusted without additional evidence (such as a trusted
timestamp).
=head1 RETURN VALUES
CMS_verify() returns 1 for a successful verification and zero if an error
occurred.
CMS_get0_signers() returns all signers or NULL if an error occurred.
The error can be obtained from L<ERR_get_error(3)>
=head1 BUGS
The trusted certificate store is not searched for the signing certificate,
this is primarily due to the inadequacies of the current B<X509_STORE>
functionality.
The lack of single pass processing means that the signed content must all
be held in memory if it is not detached.
=head1 SEE ALSO
L<ERR_get_error(3)>, L<CMS_sign(3)>
=head1 COPYRIGHT
-Copyright 2008-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2008-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/CONF_modules_load_file.pod b/doc/man3/CONF_modules_load_file.pod
index 485cf797b12e..04fbd60f40b7 100644
--- a/doc/man3/CONF_modules_load_file.pod
+++ b/doc/man3/CONF_modules_load_file.pod
@@ -1,144 +1,144 @@
=pod
=head1 NAME
CONF_modules_load_file, CONF_modules_load - OpenSSL configuration functions
=head1 SYNOPSIS
#include <openssl/conf.h>
int CONF_modules_load_file(const char *filename, const char *appname,
unsigned long flags);
int CONF_modules_load(const CONF *cnf, const char *appname,
unsigned long flags);
=head1 DESCRIPTION
The function CONF_modules_load_file() configures OpenSSL using file
B<filename> and application name B<appname>. If B<filename> is NULL
the standard OpenSSL configuration file is used. If B<appname> is
NULL the standard OpenSSL application name B<openssl_conf> is used.
The behaviour can be customized using B<flags>.
CONF_modules_load() is identical to CONF_modules_load_file() except it
reads configuration information from B<cnf>.
=head1 NOTES
The following B<flags> are currently recognized:
If B<CONF_MFLAGS_IGNORE_ERRORS> is set errors returned by individual
configuration modules are ignored. If not set the first module error is
considered fatal and no further modules are loaded.
Normally any modules errors will add error information to the error queue. If
B<CONF_MFLAGS_SILENT> is set no error information is added.
If B<CONF_MFLAGS_IGNORE_RETURN_CODES> is set the function unconditionally
returns success.
This is used by default in L<OPENSSL_init_crypto(3)> to ignore any errors in
the default system-wide configuration file, as having all OpenSSL applications
fail to start when there are potentially minor issues in the file is too risky.
Applications calling B<CONF_modules_load_file> explicitly should not generally
set this flag.
If B<CONF_MFLAGS_NO_DSO> is set configuration module loading from DSOs is
disabled.
B<CONF_MFLAGS_IGNORE_MISSING_FILE> if set will make CONF_load_modules_file()
ignore missing configuration files. Normally a missing configuration file
return an error.
B<CONF_MFLAGS_DEFAULT_SECTION> if set and B<appname> is not NULL will use the
default section pointed to by B<openssl_conf> if B<appname> does not exist.
By using CONF_modules_load_file() with appropriate flags an application can
customise application configuration to best suit its needs. In some cases the
use of a configuration file is optional and its absence is not an error: in
this case B<CONF_MFLAGS_IGNORE_MISSING_FILE> would be set.
Errors during configuration may also be handled differently by different
applications. For example in some cases an error may simply print out a warning
message and the application continue. In other cases an application might
consider a configuration file error as fatal and exit immediately.
Applications can use the CONF_modules_load() function if they wish to load a
configuration file themselves and have finer control over how errors are
treated.
+=head1 RETURN VALUES
+
+These functions return 1 for success and a zero or negative value for
+failure. If module errors are not ignored the return code will reflect the
+return value of the failing module (this will always be zero or negative).
+
=head1 EXAMPLES
Load a configuration file and print out any errors and exit (missing file
considered fatal):
if (CONF_modules_load_file(NULL, NULL, 0) <= 0) {
fprintf(stderr, "FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr);
exit(1);
}
Load default configuration file using the section indicated by "myapp",
tolerate missing files, but exit on other errors:
if (CONF_modules_load_file(NULL, "myapp",
CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
fprintf(stderr, "FATAL: error loading configuration file\n");
ERR_print_errors_fp(stderr);
exit(1);
}
Load custom configuration file and section, only print warnings on error,
missing configuration file ignored:
if (CONF_modules_load_file("/something/app.cnf", "myapp",
CONF_MFLAGS_IGNORE_MISSING_FILE) <= 0) {
fprintf(stderr, "WARNING: error loading configuration file\n");
ERR_print_errors_fp(stderr);
}
Load and parse configuration file manually, custom error handling:
FILE *fp;
CONF *cnf = NULL;
long eline;
fp = fopen("/somepath/app.cnf", "r");
if (fp == NULL) {
fprintf(stderr, "Error opening configuration file\n");
/* Other missing configuration file behaviour */
} else {
cnf = NCONF_new(NULL);
if (NCONF_load_fp(cnf, fp, &eline) == 0) {
fprintf(stderr, "Error on line %ld of configuration file\n", eline);
ERR_print_errors_fp(stderr);
/* Other malformed configuration file behaviour */
} else if (CONF_modules_load(cnf, "appname", 0) <= 0) {
fprintf(stderr, "Error configuring application\n");
ERR_print_errors_fp(stderr);
/* Other configuration error behaviour */
}
fclose(fp);
NCONF_free(cnf);
}
-=head1 RETURN VALUES
-
-These functions return 1 for success and a zero or negative value for
-failure. If module errors are not ignored the return code will reflect the
-return value of the failing module (this will always be zero or negative).
-
=head1 SEE ALSO
L<config(5)>, L<OPENSSL_config(3)>
=head1 COPYRIGHT
Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/DES_random_key.pod b/doc/man3/DES_random_key.pod
index 6e0394d637b2..bd4bd9750cd3 100644
--- a/doc/man3/DES_random_key.pod
+++ b/doc/man3/DES_random_key.pod
@@ -1,321 +1,321 @@
=pod
=head1 NAME
DES_random_key, DES_set_key, DES_key_sched, DES_set_key_checked,
DES_set_key_unchecked, DES_set_odd_parity, DES_is_weak_key,
DES_ecb_encrypt, DES_ecb2_encrypt, DES_ecb3_encrypt, DES_ncbc_encrypt,
DES_cfb_encrypt, DES_ofb_encrypt, DES_pcbc_encrypt, DES_cfb64_encrypt,
DES_ofb64_encrypt, DES_xcbc_encrypt, DES_ede2_cbc_encrypt,
DES_ede2_cfb64_encrypt, DES_ede2_ofb64_encrypt, DES_ede3_cbc_encrypt,
DES_ede3_cfb64_encrypt, DES_ede3_ofb64_encrypt,
DES_cbc_cksum, DES_quad_cksum, DES_string_to_key, DES_string_to_2keys,
DES_fcrypt, DES_crypt - DES encryption
=head1 SYNOPSIS
#include <openssl/des.h>
void DES_random_key(DES_cblock *ret);
int DES_set_key(const_DES_cblock *key, DES_key_schedule *schedule);
int DES_key_sched(const_DES_cblock *key, DES_key_schedule *schedule);
int DES_set_key_checked(const_DES_cblock *key, DES_key_schedule *schedule);
void DES_set_key_unchecked(const_DES_cblock *key, DES_key_schedule *schedule);
void DES_set_odd_parity(DES_cblock *key);
int DES_is_weak_key(const_DES_cblock *key);
void DES_ecb_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schedule *ks, int enc);
void DES_ecb2_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schedule *ks1, DES_key_schedule *ks2, int enc);
void DES_ecb3_encrypt(const_DES_cblock *input, DES_cblock *output,
DES_key_schedule *ks1, DES_key_schedule *ks2,
DES_key_schedule *ks3, int enc);
void DES_ncbc_encrypt(const unsigned char *input, unsigned char *output,
long length, DES_key_schedule *schedule, DES_cblock *ivec,
int enc);
void DES_cfb_encrypt(const unsigned char *in, unsigned char *out,
int numbits, long length, DES_key_schedule *schedule,
DES_cblock *ivec, int enc);
void DES_ofb_encrypt(const unsigned char *in, unsigned char *out,
int numbits, long length, DES_key_schedule *schedule,
DES_cblock *ivec);
void DES_pcbc_encrypt(const unsigned char *input, unsigned char *output,
long length, DES_key_schedule *schedule, DES_cblock *ivec,
int enc);
void DES_cfb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *schedule, DES_cblock *ivec,
int *num, int enc);
void DES_ofb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *schedule, DES_cblock *ivec,
int *num);
void DES_xcbc_encrypt(const unsigned char *input, unsigned char *output,
long length, DES_key_schedule *schedule, DES_cblock *ivec,
const_DES_cblock *inw, const_DES_cblock *outw, int enc);
void DES_ede2_cbc_encrypt(const unsigned char *input, unsigned char *output,
long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_cblock *ivec, int enc);
void DES_ede2_cfb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_cblock *ivec,
int *num, int enc);
void DES_ede2_ofb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_cblock *ivec, int *num);
void DES_ede3_cbc_encrypt(const unsigned char *input, unsigned char *output,
long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_key_schedule *ks3,
DES_cblock *ivec, int enc);
void DES_ede3_cfb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_key_schedule *ks3,
DES_cblock *ivec, int *num, int enc);
void DES_ede3_ofb64_encrypt(const unsigned char *in, unsigned char *out,
long length, DES_key_schedule *ks1,
DES_key_schedule *ks2, DES_key_schedule *ks3,
DES_cblock *ivec, int *num);
DES_LONG DES_cbc_cksum(const unsigned char *input, DES_cblock *output,
long length, DES_key_schedule *schedule,
const_DES_cblock *ivec);
DES_LONG DES_quad_cksum(const unsigned char *input, DES_cblock output[],
long length, int out_count, DES_cblock *seed);
void DES_string_to_key(const char *str, DES_cblock *key);
void DES_string_to_2keys(const char *str, DES_cblock *key1, DES_cblock *key2);
char *DES_fcrypt(const char *buf, const char *salt, char *ret);
char *DES_crypt(const char *buf, const char *salt);
=head1 DESCRIPTION
This library contains a fast implementation of the DES encryption
algorithm.
There are two phases to the use of DES encryption. The first is the
generation of a I<DES_key_schedule> from a key, the second is the
actual encryption. A DES key is of type I<DES_cblock>. This type
consists of 8 bytes with odd parity. The least significant bit in
each byte is the parity bit. The key schedule is an expanded form of
the key; it is used to speed the encryption process.
DES_random_key() generates a random key. The PRNG must be seeded
prior to using this function (see L<RAND_bytes(3)>). If the PRNG
could not generate a secure key, 0 is returned.
Before a DES key can be used, it must be converted into the
architecture dependent I<DES_key_schedule> via the
DES_set_key_checked() or DES_set_key_unchecked() function.
DES_set_key_checked() will check that the key passed is of odd parity
and is not a weak or semi-weak key. If the parity is wrong, then -1
is returned. If the key is a weak key, then -2 is returned. If an
error is returned, the key schedule is not generated.
DES_set_key() works like
DES_set_key_checked() if the I<DES_check_key> flag is non-zero,
otherwise like DES_set_key_unchecked(). These functions are available
for compatibility; it is recommended to use a function that does not
depend on a global variable.
DES_set_odd_parity() sets the parity of the passed I<key> to odd.
DES_is_weak_key() returns 1 if the passed key is a weak key, 0 if it
is ok.
The following routines mostly operate on an input and output stream of
I<DES_cblock>s.
DES_ecb_encrypt() is the basic DES encryption routine that encrypts or
decrypts a single 8-byte I<DES_cblock> in I<electronic code book>
(ECB) mode. It always transforms the input data, pointed to by
I<input>, into the output data, pointed to by the I<output> argument.
If the I<encrypt> argument is non-zero (DES_ENCRYPT), the I<input>
(cleartext) is encrypted in to the I<output> (ciphertext) using the
key_schedule specified by the I<schedule> argument, previously set via
I<DES_set_key>. If I<encrypt> is zero (DES_DECRYPT), the I<input> (now
ciphertext) is decrypted into the I<output> (now cleartext). Input
and output may overlap. DES_ecb_encrypt() does not return a value.
DES_ecb3_encrypt() encrypts/decrypts the I<input> block by using
three-key Triple-DES encryption in ECB mode. This involves encrypting
the input with I<ks1>, decrypting with the key schedule I<ks2>, and
then encrypting with I<ks3>. This routine greatly reduces the chances
of brute force breaking of DES and has the advantage of if I<ks1>,
I<ks2> and I<ks3> are the same, it is equivalent to just encryption
using ECB mode and I<ks1> as the key.
The macro DES_ecb2_encrypt() is provided to perform two-key Triple-DES
encryption by using I<ks1> for the final encryption.
DES_ncbc_encrypt() encrypts/decrypts using the I<cipher-block-chaining>
(CBC) mode of DES. If the I<encrypt> argument is non-zero, the
routine cipher-block-chain encrypts the cleartext data pointed to by
the I<input> argument into the ciphertext pointed to by the I<output>
argument, using the key schedule provided by the I<schedule> argument,
and initialization vector provided by the I<ivec> argument. If the
I<length> argument is not an integral multiple of eight bytes, the
last block is copied to a temporary area and zero filled. The output
is always an integral multiple of eight bytes.
DES_xcbc_encrypt() is RSA's DESX mode of DES. It uses I<inw> and
I<outw> to 'whiten' the encryption. I<inw> and I<outw> are secret
(unlike the iv) and are as such, part of the key. So the key is sort
of 24 bytes. This is much better than CBC DES.
DES_ede3_cbc_encrypt() implements outer triple CBC DES encryption with
three keys. This means that each DES operation inside the CBC mode is
C<C=E(ks3,D(ks2,E(ks1,M)))>. This mode is used by SSL.
The DES_ede2_cbc_encrypt() macro implements two-key Triple-DES by
reusing I<ks1> for the final encryption. C<C=E(ks1,D(ks2,E(ks1,M)))>.
This form of Triple-DES is used by the RSAREF library.
DES_pcbc_encrypt() encrypts/decrypts using the propagating cipher block
chaining mode used by Kerberos v4. Its parameters are the same as
DES_ncbc_encrypt().
DES_cfb_encrypt() encrypts/decrypts using cipher feedback mode. This
method takes an array of characters as input and outputs an array of
characters. It does not require any padding to 8 character groups.
Note: the I<ivec> variable is changed and the new changed value needs to
be passed to the next call to this function. Since this function runs
a complete DES ECB encryption per I<numbits>, this function is only
suggested for use when sending a small number of characters.
DES_cfb64_encrypt()
implements CFB mode of DES with 64-bit feedback. Why is this
useful you ask? Because this routine will allow you to encrypt an
arbitrary number of bytes, without 8 byte padding. Each call to this
routine will encrypt the input bytes to output and then update ivec
and num. num contains 'how far' we are though ivec. If this does
not make much sense, read more about CFB mode of DES.
DES_ede3_cfb64_encrypt() and DES_ede2_cfb64_encrypt() is the same as
DES_cfb64_encrypt() except that Triple-DES is used.
DES_ofb_encrypt() encrypts using output feedback mode. This method
takes an array of characters as input and outputs an array of
characters. It does not require any padding to 8 character groups.
Note: the I<ivec> variable is changed and the new changed value needs to
be passed to the next call to this function. Since this function runs
a complete DES ECB encryption per I<numbits>, this function is only
suggested for use when sending a small number of characters.
DES_ofb64_encrypt() is the same as DES_cfb64_encrypt() using Output
Feed Back mode.
DES_ede3_ofb64_encrypt() and DES_ede2_ofb64_encrypt() is the same as
DES_ofb64_encrypt(), using Triple-DES.
The following functions are included in the DES library for
compatibility with the MIT Kerberos library.
DES_cbc_cksum() produces an 8 byte checksum based on the input stream
(via CBC encryption). The last 4 bytes of the checksum are returned
and the complete 8 bytes are placed in I<output>. This function is
used by Kerberos v4. Other applications should use
L<EVP_DigestInit(3)> etc. instead.
DES_quad_cksum() is a Kerberos v4 function. It returns a 4 byte
checksum from the input bytes. The algorithm can be iterated over the
input, depending on I<out_count>, 1, 2, 3 or 4 times. If I<output> is
non-NULL, the 8 bytes generated by each pass are written into
I<output>.
The following are DES-based transformations:
DES_fcrypt() is a fast version of the Unix crypt(3) function. This
version takes only a small amount of space relative to other fast
crypt() implementations. This is different to the normal crypt() in
that the third parameter is the buffer that the return value is
written into. It needs to be at least 14 bytes long. This function
is thread safe, unlike the normal crypt().
DES_crypt() is a faster replacement for the normal system crypt().
This function calls DES_fcrypt() with a static array passed as the
third parameter. This mostly emulates the normal non-thread-safe semantics
of crypt(3).
The B<salt> must be two ASCII characters.
The values returned by DES_fcrypt() and DES_crypt() are terminated by NUL
character.
DES_enc_write() writes I<len> bytes to file descriptor I<fd> from
buffer I<buf>. The data is encrypted via I<pcbc_encrypt> (default)
using I<sched> for the key and I<iv> as a starting vector. The actual
data send down I<fd> consists of 4 bytes (in network byte order)
containing the length of the following encrypted data. The encrypted
data then follows, padded with random data out to a multiple of 8
bytes.
=head1 BUGS
DES_cbc_encrypt() does not modify B<ivec>; use DES_ncbc_encrypt()
instead.
DES_cfb_encrypt() and DES_ofb_encrypt() operates on input of 8 bits.
What this means is that if you set numbits to 12, and length to 2, the
first 12 bits will come from the 1st input byte and the low half of
the second input byte. The second 12 bits will have the low 8 bits
taken from the 3rd input byte and the top 4 bits taken from the 4th
input byte. The same holds for output. This function has been
implemented this way because most people will be using a multiple of 8
and because once you get into pulling bytes input bytes apart things
get ugly!
DES_string_to_key() is available for backward compatibility with the
MIT library. New applications should use a cryptographic hash function.
The same applies for DES_string_to_2key().
=head1 NOTES
The B<des> library was written to be source code compatible with
the MIT Kerberos library.
Applications should use the higher level functions
L<EVP_EncryptInit(3)> etc. instead of calling these
functions directly.
Single-key DES is insecure due to its short key size. ECB mode is
not suitable for most applications; see L<des_modes(7)>.
=head1 RETURN VALUES
DES_set_key(), DES_key_sched(), DES_set_key_checked() and DES_is_weak_key()
return 0 on success or negative values on error.
DES_cbc_cksum() and DES_quad_cksum() return 4-byte integer representing the
last 4 bytes of the checksum of the input.
DES_fcrypt() returns a pointer to the caller-provided buffer and DES_crypt() -
to a static buffer on success; otherwise they return NULL.
+=head1 SEE ALSO
+
+L<des_modes(7)>,
+L<EVP_EncryptInit(3)>
+
=head1 HISTORY
The requirement that the B<salt> parameter to DES_crypt() and DES_fcrypt()
be two ASCII characters was first enforced in
OpenSSL 1.1.0. Previous versions tried to use the letter uppercase B<A>
if both character were not present, and could crash when given non-ASCII
on some platforms.
-=head1 SEE ALSO
-
-L<des_modes(7)>,
-L<EVP_EncryptInit(3)>
-
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/ECDSA_SIG_new.pod b/doc/man3/ECDSA_SIG_new.pod
index 0bf63f8bde80..8d6cda5e7a3c 100644
--- a/doc/man3/ECDSA_SIG_new.pod
+++ b/doc/man3/ECDSA_SIG_new.pod
@@ -1,216 +1,216 @@
=pod
=head1 NAME
ECDSA_SIG_get0, ECDSA_SIG_get0_r, ECDSA_SIG_get0_s, ECDSA_SIG_set0,
ECDSA_SIG_new, ECDSA_SIG_free, i2d_ECDSA_SIG, d2i_ECDSA_SIG, ECDSA_size,
ECDSA_sign, ECDSA_do_sign, ECDSA_verify, ECDSA_do_verify, ECDSA_sign_setup,
ECDSA_sign_ex, ECDSA_do_sign_ex - low level elliptic curve digital signature
algorithm (ECDSA) functions
=head1 SYNOPSIS
#include <openssl/ecdsa.h>
ECDSA_SIG *ECDSA_SIG_new(void);
void ECDSA_SIG_free(ECDSA_SIG *sig);
void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps);
const BIGNUM *ECDSA_SIG_get0_r(const ECDSA_SIG *sig);
const BIGNUM *ECDSA_SIG_get0_s(const ECDSA_SIG *sig);
int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s);
int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **pp);
ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **sig, const unsigned char **pp, long len);
int ECDSA_size(const EC_KEY *eckey);
int ECDSA_sign(int type, const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen, EC_KEY *eckey);
ECDSA_SIG *ECDSA_do_sign(const unsigned char *dgst, int dgst_len,
EC_KEY *eckey);
int ECDSA_verify(int type, const unsigned char *dgst, int dgstlen,
const unsigned char *sig, int siglen, EC_KEY *eckey);
int ECDSA_do_verify(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY* eckey);
ECDSA_SIG *ECDSA_do_sign_ex(const unsigned char *dgst, int dgstlen,
const BIGNUM *kinv, const BIGNUM *rp,
EC_KEY *eckey);
int ECDSA_sign_setup(EC_KEY *eckey, BN_CTX *ctx, BIGNUM **kinv, BIGNUM **rp);
int ECDSA_sign_ex(int type, const unsigned char *dgst, int dgstlen,
unsigned char *sig, unsigned int *siglen,
const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey);
=head1 DESCRIPTION
Note: these functions provide a low level interface to ECDSA. Most
applications should use the higher level B<EVP> interface such as
L<EVP_DigestSignInit(3)> or L<EVP_DigestVerifyInit(3)> instead.
B<ECDSA_SIG> is an opaque structure consisting of two BIGNUMs for the
B<r> and B<s> value of an ECDSA signature (see X9.62 or FIPS 186-2).
ECDSA_SIG_new() allocates an empty B<ECDSA_SIG> structure. Note: before
OpenSSL 1.1.0 the: the B<r> and B<s> components were initialised.
ECDSA_SIG_free() frees the B<ECDSA_SIG> structure B<sig>.
ECDSA_SIG_get0() returns internal pointers the B<r> and B<s> values contained
in B<sig> and stores them in B<*pr> and B<*ps>, respectively.
The pointer B<pr> or B<ps> can be NULL, in which case the corresponding value
is not returned.
The values B<r>, B<s> can also be retrieved separately by the corresponding
function ECDSA_SIG_get0_r() and ECDSA_SIG_get0_s(), respectively.
The B<r> and B<s> values can be set by calling ECDSA_SIG_set0() and passing the
new values for B<r> and B<s> as parameters to the function. Calling this
function transfers the memory management of the values to the ECDSA_SIG object,
and therefore the values that have been passed in should not be freed directly
after this function has been called.
i2d_ECDSA_SIG() creates the DER encoding of the ECDSA signature B<sig> and
writes the encoded signature to B<*pp> (note: if B<pp> is NULL i2d_ECDSA_SIG()
returns the expected length in bytes of the DER encoded signature).
i2d_ECDSA_SIG() returns the length of the DER encoded signature (or 0 on
error).
d2i_ECDSA_SIG() decodes a DER encoded ECDSA signature and returns the decoded
signature in a newly allocated B<ECDSA_SIG> structure. B<*sig> points to the
buffer containing the DER encoded signature of size B<len>.
ECDSA_size() returns the maximum length of a DER encoded ECDSA signature
created with the private EC key B<eckey>.
ECDSA_sign() computes a digital signature of the B<dgstlen> bytes hash value
B<dgst> using the private EC key B<eckey>. The DER encoded signatures is
stored in B<sig> and its length is returned in B<sig_len>. Note: B<sig> must
point to ECDSA_size(eckey) bytes of memory. The parameter B<type> is currently
ignored. ECDSA_sign() is wrapper function for ECDSA_sign_ex() with B<kinv>
and B<rp> set to NULL.
ECDSA_do_sign() is similar to ECDSA_sign() except the signature is returned
as a newly allocated B<ECDSA_SIG> structure (or NULL on error). ECDSA_do_sign()
is a wrapper function for ECDSA_do_sign_ex() with B<kinv> and B<rp> set to
NULL.
ECDSA_verify() verifies that the signature in B<sig> of size B<siglen> is a
valid ECDSA signature of the hash value B<dgst> of size B<dgstlen> using the
public key B<eckey>. The parameter B<type> is ignored.
ECDSA_do_verify() is similar to ECDSA_verify() except the signature is
presented in the form of a pointer to an B<ECDSA_SIG> structure.
The remaining functions utilise the internal B<kinv> and B<r> values used
during signature computation. Most applications will never need to call these
and some external ECDSA ENGINE implementations may not support them at all if
either B<kinv> or B<r> is not B<NULL>.
ECDSA_sign_setup() may be used to precompute parts of the signing operation.
B<eckey> is the private EC key and B<ctx> is a pointer to B<BN_CTX> structure
(or NULL). The precomputed values or returned in B<kinv> and B<rp> and can be
used in a later call to ECDSA_sign_ex() or ECDSA_do_sign_ex().
ECDSA_sign_ex() computes a digital signature of the B<dgstlen> bytes hash value
B<dgst> using the private EC key B<eckey> and the optional pre-computed values
B<kinv> and B<rp>. The DER encoded signature is stored in B<sig> and its
length is returned in B<sig_len>. Note: B<sig> must point to ECDSA_size(eckey)
bytes of memory. The parameter B<type> is ignored.
ECDSA_do_sign_ex() is similar to ECDSA_sign_ex() except the signature is
returned as a newly allocated B<ECDSA_SIG> structure (or NULL on error).
=head1 RETURN VALUES
ECDSA_SIG_new() returns NULL if the allocation fails.
ECDSA_SIG_set0() returns 1 on success or 0 on failure.
ECDSA_SIG_get0_r() and ECDSA_SIG_get0_s() return the corresponding value,
or NULL if it is unset.
ECDSA_size() returns the maximum length signature or 0 on error.
ECDSA_sign(), ECDSA_sign_ex() and ECDSA_sign_setup() return 1 if successful
or 0 on error.
ECDSA_do_sign() and ECDSA_do_sign_ex() return a pointer to an allocated
B<ECDSA_SIG> structure or NULL on error.
ECDSA_verify() and ECDSA_do_verify() return 1 for a valid
signature, 0 for an invalid signature and -1 on error.
The error codes can be obtained by L<ERR_get_error(3)>.
=head1 EXAMPLES
Creating an ECDSA signature of a given SHA-256 hash value using the
named curve prime256v1 (aka P-256).
First step: create an EC_KEY object (note: this part is B<not> ECDSA
specific)
int ret;
ECDSA_SIG *sig;
EC_KEY *eckey;
eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (eckey == NULL)
/* error */
if (EC_KEY_generate_key(eckey) == 0)
/* error */
Second step: compute the ECDSA signature of a SHA-256 hash value
using ECDSA_do_sign():
sig = ECDSA_do_sign(digest, 32, eckey);
if (sig == NULL)
/* error */
or using ECDSA_sign():
unsigned char *buffer, *pp;
int buf_len;
buf_len = ECDSA_size(eckey);
buffer = OPENSSL_malloc(buf_len);
pp = buffer;
if (ECDSA_sign(0, dgst, dgstlen, pp, &buf_len, eckey) == 0)
/* error */
Third step: verify the created ECDSA signature using ECDSA_do_verify():
ret = ECDSA_do_verify(digest, 32, sig, eckey);
or using ECDSA_verify():
ret = ECDSA_verify(0, digest, 32, buffer, buf_len, eckey);
and finally evaluate the return value:
if (ret == 1)
/* signature ok */
else if (ret == 0)
/* incorrect signature */
else
/* error */
=head1 CONFORMING TO
ANSI X9.62, US Federal Information Processing Standard FIPS 186-2
(Digital Signature Standard, DSS)
=head1 SEE ALSO
-L<DSA_new(3)>,
+L<EC_KEY_new(3)>,
L<EVP_DigestSignInit(3)>,
L<EVP_DigestVerifyInit(3)>
=head1 COPYRIGHT
-Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_DigestVerifyInit.pod b/doc/man3/EVP_DigestVerifyInit.pod
index 98a0987a3aaa..592a7508dce0 100644
--- a/doc/man3/EVP_DigestVerifyInit.pod
+++ b/doc/man3/EVP_DigestVerifyInit.pod
@@ -1,112 +1,112 @@
=pod
=head1 NAME
EVP_DigestVerifyInit, EVP_DigestVerifyUpdate, EVP_DigestVerifyFinal,
EVP_DigestVerify - EVP signature verification functions
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e, EVP_PKEY *pkey);
int EVP_DigestVerifyUpdate(EVP_MD_CTX *ctx, const void *d, size_t cnt);
int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen);
int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
size_t siglen, const unsigned char *tbs, size_t tbslen);
=head1 DESCRIPTION
The EVP signature routines are a high level interface to digital signatures.
EVP_DigestVerifyInit() sets up verification context B<ctx> to use digest
B<type> from ENGINE B<e> and public key B<pkey>. B<ctx> must be created
with EVP_MD_CTX_new() before calling this function. If B<pctx> is not NULL, the
EVP_PKEY_CTX of the verification operation will be written to B<*pctx>: this
can be used to set alternative verification options. Note that any existing
value in B<*pctx> is overwritten. The EVP_PKEY_CTX value returned must not be freed
directly by the application if B<ctx> is not assigned an EVP_PKEY_CTX value before
-being passed to EVP_DigestSignInit() (which means the EVP_PKEY_CTX is created
-inside EVP_DigestSignInit() and it will be freed automatically when the
+being passed to EVP_DigestVerifyInit() (which means the EVP_PKEY_CTX is created
+inside EVP_DigestVerifyInit() and it will be freed automatically when the
EVP_MD_CTX is freed).
No B<EVP_PKEY_CTX> will be created by EVP_DigsetSignInit() if the passed B<ctx>
has already been assigned one via L<EVP_MD_CTX_set_ctx(3)>. See also L<SM2(7)>.
EVP_DigestVerifyUpdate() hashes B<cnt> bytes of data at B<d> into the
verification context B<ctx>. This function can be called several times on the
same B<ctx> to include additional data. This function is currently implemented
using a macro.
EVP_DigestVerifyFinal() verifies the data in B<ctx> against the signature in
B<sig> of length B<siglen>.
EVP_DigestVerify() verifies B<tbslen> bytes at B<tbs> against the signature
in B<sig> of length B<siglen>.
=head1 RETURN VALUES
EVP_DigestVerifyInit() and EVP_DigestVerifyUpdate() return 1 for success and 0
for failure.
EVP_DigestVerifyFinal() and EVP_DigestVerify() return 1 for success; any other
value indicates failure. A return value of zero indicates that the signature
did not verify successfully (that is, B<tbs> did not match the original data or
the signature had an invalid form), while other values indicate a more serious
error (and sometimes also indicate an invalid signature form).
The error codes can be obtained from L<ERR_get_error(3)>.
=head1 NOTES
The B<EVP> interface to digital signatures should almost always be used in
preference to the low level interfaces. This is because the code then becomes
transparent to the algorithm used and much more flexible.
EVP_DigestVerify() is a one shot operation which verifies a single block of
data in one function. For algorithms that support streaming it is equivalent
to calling EVP_DigestVerifyUpdate() and EVP_DigestVerifyFinal(). For
algorithms which do not support streaming (e.g. PureEdDSA) it is the only way
to verify data.
In previous versions of OpenSSL there was a link between message digest types
and public key algorithms. This meant that "clone" digests such as EVP_dss1()
needed to be used to sign using SHA1 and DSA. This is no longer necessary and
the use of clone digest is now discouraged.
For some key types and parameters the random number generator must be seeded
or the operation will fail.
The call to EVP_DigestVerifyFinal() internally finalizes a copy of the digest
context. This means that EVP_VerifyUpdate() and EVP_VerifyFinal() can
be called later to digest and verify additional data.
Since only a copy of the digest context is ever finalized, the context must
be cleaned up after use by calling EVP_MD_CTX_free() or a memory leak
will occur.
=head1 SEE ALSO
L<EVP_DigestSignInit(3)>,
L<EVP_DigestInit(3)>,
L<evp(7)>, L<HMAC(3)>, L<MD2(3)>,
L<MD5(3)>, L<MDC2(3)>, L<RIPEMD160(3)>,
L<SHA1(3)>, L<dgst(1)>
=head1 HISTORY
EVP_DigestVerifyInit(), EVP_DigestVerifyUpdate() and EVP_DigestVerifyFinal()
were added in OpenSSL 1.0.0.
=head1 COPYRIGHT
-Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2006-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod
index b43a3e5468ca..6b068617b0ad 100644
--- a/doc/man3/EVP_EncryptInit.pod
+++ b/doc/man3/EVP_EncryptInit.pod
@@ -1,651 +1,655 @@
=pod
=head1 NAME
EVP_CIPHER_CTX_new,
EVP_CIPHER_CTX_reset,
EVP_CIPHER_CTX_free,
EVP_EncryptInit_ex,
EVP_EncryptUpdate,
EVP_EncryptFinal_ex,
EVP_DecryptInit_ex,
EVP_DecryptUpdate,
EVP_DecryptFinal_ex,
EVP_CipherInit_ex,
EVP_CipherUpdate,
EVP_CipherFinal_ex,
EVP_CIPHER_CTX_set_key_length,
EVP_CIPHER_CTX_ctrl,
EVP_EncryptInit,
EVP_EncryptFinal,
EVP_DecryptInit,
EVP_DecryptFinal,
EVP_CipherInit,
EVP_CipherFinal,
EVP_get_cipherbyname,
EVP_get_cipherbynid,
EVP_get_cipherbyobj,
EVP_CIPHER_nid,
EVP_CIPHER_block_size,
EVP_CIPHER_key_length,
EVP_CIPHER_iv_length,
EVP_CIPHER_flags,
EVP_CIPHER_mode,
EVP_CIPHER_type,
EVP_CIPHER_CTX_cipher,
EVP_CIPHER_CTX_nid,
EVP_CIPHER_CTX_block_size,
EVP_CIPHER_CTX_key_length,
EVP_CIPHER_CTX_iv_length,
EVP_CIPHER_CTX_get_app_data,
EVP_CIPHER_CTX_set_app_data,
EVP_CIPHER_CTX_type,
EVP_CIPHER_CTX_flags,
EVP_CIPHER_CTX_mode,
EVP_CIPHER_param_to_asn1,
EVP_CIPHER_asn1_to_param,
EVP_CIPHER_CTX_set_padding,
EVP_enc_null
- EVP cipher routines
=head1 SYNOPSIS
=for comment generic
#include <openssl/evp.h>
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *ctx);
int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv);
int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv);
int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv);
int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv);
int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *key, const unsigned char *iv, int enc);
int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm, int *outl);
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *x, int padding);
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
const EVP_CIPHER *EVP_get_cipherbynid(int nid);
const EVP_CIPHER *EVP_get_cipherbyobj(const ASN1_OBJECT *a);
int EVP_CIPHER_nid(const EVP_CIPHER *e);
int EVP_CIPHER_block_size(const EVP_CIPHER *e);
int EVP_CIPHER_key_length(const EVP_CIPHER *e);
int EVP_CIPHER_iv_length(const EVP_CIPHER *e);
unsigned long EVP_CIPHER_flags(const EVP_CIPHER *e);
unsigned long EVP_CIPHER_mode(const EVP_CIPHER *e);
int EVP_CIPHER_type(const EVP_CIPHER *ctx);
const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_set_app_data(const EVP_CIPHER_CTX *ctx, void *data);
int EVP_CIPHER_CTX_type(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_mode(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
=head1 DESCRIPTION
The EVP cipher routines are a high level interface to certain
symmetric ciphers.
EVP_CIPHER_CTX_new() creates a cipher context.
EVP_CIPHER_CTX_free() clears all information from a cipher context
and free up any allocated memory associate with it, including B<ctx>
itself. This function should be called after all operations using a
cipher are complete so sensitive information does not remain in
memory.
EVP_EncryptInit_ex() sets up cipher context B<ctx> for encryption
with cipher B<type> from ENGINE B<impl>. B<ctx> must be created
before calling this function. B<type> is normally supplied
by a function such as EVP_aes_256_cbc(). If B<impl> is NULL then the
default implementation is used. B<key> is the symmetric key to use
and B<iv> is the IV to use (if necessary), the actual number of bytes
used for the key and IV depends on the cipher. It is possible to set
all parameters to NULL except B<type> in an initial call and supply
the remaining parameters in subsequent calls, all of which have B<type>
set to NULL. This is done when the default cipher parameters are not
appropriate.
EVP_EncryptUpdate() encrypts B<inl> bytes from the buffer B<in> and
writes the encrypted version to B<out>. This function can be called
multiple times to encrypt successive blocks of data. The amount
of data written depends on the block alignment of the encrypted data:
as a result the amount of data written may be anything from zero bytes
to (inl + cipher_block_size - 1) so B<out> should contain sufficient
room. The actual number of bytes written is placed in B<outl>. It also
checks if B<in> and B<out> are partially overlapping, and if they are
0 is returned to indicate failure.
If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts
the "final" data, that is any data that remains in a partial block.
It uses standard block padding (aka PKCS padding) as described in
the NOTES section, below. The encrypted
final data is written to B<out> which should have sufficient space for
one cipher block. The number of bytes written is placed in B<outl>. After
this function is called the encryption operation is finished and no further
calls to EVP_EncryptUpdate() should be made.
If padding is disabled then EVP_EncryptFinal_ex() will not encrypt any more
data and it will return an error if any data remains in a partial block:
that is if the total data length is not a multiple of the block size.
EVP_DecryptInit_ex(), EVP_DecryptUpdate() and EVP_DecryptFinal_ex() are the
corresponding decryption operations. EVP_DecryptFinal() will return an
error code if padding is enabled and the final block is not correctly
formatted. The parameters and restrictions are identical to the encryption
operations except that if padding is enabled the decrypted data buffer B<out>
passed to EVP_DecryptUpdate() should have sufficient room for
(B<inl> + cipher_block_size) bytes unless the cipher block size is 1 in
which case B<inl> bytes is sufficient.
EVP_CipherInit_ex(), EVP_CipherUpdate() and EVP_CipherFinal_ex() are
functions that can be used for decryption or encryption. The operation
performed depends on the value of the B<enc> parameter. It should be set
to 1 for encryption, 0 for decryption and -1 to leave the value unchanged
(the actual value of 'enc' being supplied in a previous call).
EVP_CIPHER_CTX_reset() clears all information from a cipher context
and free up any allocated memory associate with it, except the B<ctx>
itself. This function should be called anytime B<ctx> is to be reused
for another EVP_CipherInit() / EVP_CipherUpdate() / EVP_CipherFinal()
series of calls.
EVP_EncryptInit(), EVP_DecryptInit() and EVP_CipherInit() behave in a
similar way to EVP_EncryptInit_ex(), EVP_DecryptInit_ex() and
EVP_CipherInit_ex() except they always use the default cipher implementation.
EVP_EncryptFinal(), EVP_DecryptFinal() and EVP_CipherFinal() are
identical to EVP_EncryptFinal_ex(), EVP_DecryptFinal_ex() and
EVP_CipherFinal_ex(). In previous releases they also cleaned up
the B<ctx>, but this is no longer done and EVP_CIPHER_CTX_clean()
must be called to free any context resources.
EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj()
return an EVP_CIPHER structure when passed a cipher name, a NID or an
ASN1_OBJECT structure.
EVP_CIPHER_nid() and EVP_CIPHER_CTX_nid() return the NID of a cipher when
passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX> structure. The actual NID
value is an internal value which may not have a corresponding OBJECT
IDENTIFIER.
EVP_CIPHER_CTX_set_padding() enables or disables padding. This
function should be called after the context is set up for encryption
or decryption with EVP_EncryptInit_ex(), EVP_DecryptInit_ex() or
EVP_CipherInit_ex(). By default encryption operations are padded using
standard block padding and the padding is checked and removed when
decrypting. If the B<pad> parameter is zero then no padding is
performed, the total amount of data encrypted or decrypted must then
be a multiple of the block size or an error will occur.
EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key
length of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>
structure. The constant B<EVP_MAX_KEY_LENGTH> is the maximum key length
for all ciphers. Note: although EVP_CIPHER_key_length() is fixed for a
given cipher, the value of EVP_CIPHER_CTX_key_length() may be different
for variable key length ciphers.
EVP_CIPHER_CTX_set_key_length() sets the key length of the cipher ctx.
If the cipher is a fixed length cipher then attempting to set the key
length to any value other than the fixed value is an error.
EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV
length of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>.
It will return zero if the cipher does not use an IV. The constant
B<EVP_MAX_IV_LENGTH> is the maximum IV length for all ciphers.
EVP_CIPHER_block_size() and EVP_CIPHER_CTX_block_size() return the block
size of a cipher when passed an B<EVP_CIPHER> or B<EVP_CIPHER_CTX>
structure. The constant B<EVP_MAX_BLOCK_LENGTH> is also the maximum block
length for all ciphers.
EVP_CIPHER_type() and EVP_CIPHER_CTX_type() return the type of the passed
cipher or context. This "type" is the actual NID of the cipher OBJECT
IDENTIFIER as such it ignores the cipher parameters and 40 bit RC2 and
128 bit RC2 have the same NID. If the cipher does not have an object
identifier or does not have ASN1 support this function will return
B<NID_undef>.
EVP_CIPHER_CTX_cipher() returns the B<EVP_CIPHER> structure when passed
an B<EVP_CIPHER_CTX> structure.
EVP_CIPHER_mode() and EVP_CIPHER_CTX_mode() return the block cipher mode:
EVP_CIPH_ECB_MODE, EVP_CIPH_CBC_MODE, EVP_CIPH_CFB_MODE, EVP_CIPH_OFB_MODE,
EVP_CIPH_CTR_MODE, EVP_CIPH_GCM_MODE, EVP_CIPH_CCM_MODE, EVP_CIPH_XTS_MODE,
EVP_CIPH_WRAP_MODE or EVP_CIPH_OCB_MODE. If the cipher is a stream cipher then
EVP_CIPH_STREAM_CIPHER is returned.
EVP_CIPHER_param_to_asn1() sets the AlgorithmIdentifier "parameter" based
on the passed cipher. This will typically include any parameters and an
IV. The cipher IV (if any) must be set when this call is made. This call
should be made before the cipher is actually "used" (before any
EVP_EncryptUpdate(), EVP_DecryptUpdate() calls for example). This function
may fail if the cipher does not have any ASN1 support.
EVP_CIPHER_asn1_to_param() sets the cipher parameters based on an ASN1
AlgorithmIdentifier "parameter". The precise effect depends on the cipher
In the case of RC2, for example, it will set the IV and effective key length.
This function should be called after the base cipher type is set but before
the key is set. For example EVP_CipherInit() will be called with the IV and
key set to NULL, EVP_CIPHER_asn1_to_param() will be called and finally
EVP_CipherInit() again with all parameters except the key set to NULL. It is
possible for this function to fail if the cipher does not have any ASN1 support
or the parameters cannot be set (for example the RC2 effective key length
is not supported.
EVP_CIPHER_CTX_ctrl() allows various cipher specific parameters to be determined
and set.
EVP_CIPHER_CTX_rand_key() generates a random key of the appropriate length
based on the cipher context. The EVP_CIPHER can provide its own random key
generation routine to support keys of a specific form. B<Key> must point to a
buffer at least as big as the value returned by EVP_CIPHER_CTX_key_length().
=head1 RETURN VALUES
EVP_CIPHER_CTX_new() returns a pointer to a newly created
B<EVP_CIPHER_CTX> for success and B<NULL> for failure.
EVP_EncryptInit_ex(), EVP_EncryptUpdate() and EVP_EncryptFinal_ex()
return 1 for success and 0 for failure.
EVP_DecryptInit_ex() and EVP_DecryptUpdate() return 1 for success and 0 for failure.
EVP_DecryptFinal_ex() returns 0 if the decrypt failed or 1 for success.
EVP_CipherInit_ex() and EVP_CipherUpdate() return 1 for success and 0 for failure.
EVP_CipherFinal_ex() returns 0 for a decryption failure or 1 for success.
EVP_CIPHER_CTX_reset() returns 1 for success and 0 for failure.
EVP_get_cipherbyname(), EVP_get_cipherbynid() and EVP_get_cipherbyobj()
return an B<EVP_CIPHER> structure or NULL on error.
EVP_CIPHER_nid() and EVP_CIPHER_CTX_nid() return a NID.
EVP_CIPHER_block_size() and EVP_CIPHER_CTX_block_size() return the block
size.
EVP_CIPHER_key_length() and EVP_CIPHER_CTX_key_length() return the key
length.
EVP_CIPHER_CTX_set_padding() always returns 1.
EVP_CIPHER_iv_length() and EVP_CIPHER_CTX_iv_length() return the IV
length or zero if the cipher does not use an IV.
EVP_CIPHER_type() and EVP_CIPHER_CTX_type() return the NID of the cipher's
OBJECT IDENTIFIER or NID_undef if it has no defined OBJECT IDENTIFIER.
EVP_CIPHER_CTX_cipher() returns an B<EVP_CIPHER> structure.
EVP_CIPHER_param_to_asn1() and EVP_CIPHER_asn1_to_param() return greater
than zero for success and zero or a negative number on failure.
EVP_CIPHER_CTX_rand_key() returns 1 for success.
=head1 CIPHER LISTING
All algorithms have a fixed key length unless otherwise stated.
Refer to L<SEE ALSO> for the full list of ciphers available through the EVP
interface.
=over 4
=item EVP_enc_null()
Null cipher: does nothing.
=back
=head1 AEAD Interface
The EVP interface for Authenticated Encryption with Associated Data (AEAD)
modes are subtly altered and several additional I<ctrl> operations are supported
depending on the mode specified.
To specify additional authenticated data (AAD), a call to EVP_CipherUpdate(),
EVP_EncryptUpdate() or EVP_DecryptUpdate() should be made with the output
parameter B<out> set to B<NULL>.
When decrypting, the return value of EVP_DecryptFinal() or EVP_CipherFinal()
indicates whether the operation was successful. If it does not indicate success,
the authentication operation has failed and any output data B<MUST NOT> be used
as it is corrupted.
=head2 GCM and OCB Modes
The following I<ctrl>s are supported in GCM and OCB modes.
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
Sets the IV length. This call can only be made before specifying an IV. If
not called a default IV length is used.
For GCM AES and OCB AES the default is 12 (i.e. 96 bits). For OCB mode the
maximum is 15.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag)
Writes C<taglen> bytes of the tag value to the buffer indicated by C<tag>.
This call can only be made when encrypting data and B<after> all data has been
processed (e.g. after an EVP_EncryptFinal() call).
For OCB, C<taglen> must either be 16 or the value previously set via
B<EVP_CTRL_AEAD_SET_TAG>.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag)
Sets the expected tag to C<taglen> bytes from C<tag>.
The tag length can only be set before specifying an IV.
C<taglen> must be between 1 and 16 inclusive.
For GCM, this call is only valid when decrypting data.
For OCB, this call is valid when decrypting data to set the expected tag,
and before encryption to set the desired tag length.
In OCB mode, calling this before encryption with C<tag> set to C<NULL> sets the
tag length. If this is not called prior to encryption, a default tag length is
used.
For OCB AES, the default tag length is 16 (i.e. 128 bits). It is also the
maximum tag length for OCB.
=back
=head2 CCM Mode
The EVP interface for CCM mode is similar to that of the GCM mode but with a
few additional requirements and different I<ctrl> values.
For CCM mode, the total plaintext or ciphertext length B<MUST> be passed to
EVP_CipherUpdate(), EVP_EncryptUpdate() or EVP_DecryptUpdate() with the output
and input parameters (B<in> and B<out>) set to B<NULL> and the length passed in
the B<inl> parameter.
The following I<ctrl>s are supported in CCM mode.
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag)
This call is made to set the expected B<CCM> tag value when decrypting or
the length of the tag (with the C<tag> parameter set to NULL) when encrypting.
The tag length is often referred to as B<M>. If not set a default value is
-used (12 for AES).
+used (12 for AES). When decrypting, the tag needs to be set before passing
+in data to be decrypted, but as in GCM and OCB mode, it can be set after
+passing additional authenticated data (see L<AEAD Interface>).
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, ivlen, NULL)
Sets the CCM B<L> value. If not set a default is used (8 for AES).
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
Sets the CCM nonce (IV) length. This call can only be made before specifying an
nonce value. The nonce length is given by B<15 - L> so it is 7 by default for
AES.
=back
=head2 ChaCha20-Poly1305
The following I<ctrl>s are supported for the ChaCha20-Poly1305 AEAD algorithm.
=over 4
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivlen, NULL)
Sets the nonce length. This call can only be made before specifying the nonce.
If not called a default nonce length of 12 (i.e. 96 bits) is used. The maximum
-nonce length is 16 (B<CHACHA_CTR_SIZE>, i.e. 128-bits).
+nonce length is 12 bytes (i.e. 96-bits). If a nonce of less than 12 bytes is set
+then the nonce is automatically padded with leading 0 bytes to make it 12 bytes
+in length.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, taglen, tag)
Writes C<taglen> bytes of the tag value to the buffer indicated by C<tag>.
This call can only be made when encrypting data and B<after> all data has been
processed (e.g. after an EVP_EncryptFinal() call).
C<taglen> specified here must be 16 (B<POLY1305_BLOCK_SIZE>, i.e. 128-bits) or
less.
=item EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, taglen, tag)
Sets the expected tag to C<taglen> bytes from C<tag>.
The tag length can only be set before specifying an IV.
C<taglen> must be between 1 and 16 (B<POLY1305_BLOCK_SIZE>) inclusive.
This call is only valid when decrypting data.
=back
=head1 NOTES
Where possible the B<EVP> interface to symmetric ciphers should be used in
preference to the low level interfaces. This is because the code then becomes
transparent to the cipher used and much more flexible. Additionally, the
B<EVP> interface will ensure the use of platform specific cryptographic
acceleration such as AES-NI (the low level interfaces do not provide the
guarantee).
PKCS padding works by adding B<n> padding bytes of value B<n> to make the total
length of the encrypted data a multiple of the block size. Padding is always
added so if the data is already a multiple of the block size B<n> will equal
the block size. For example if the block size is 8 and 11 bytes are to be
encrypted then 5 padding bytes of value 5 will be added.
When decrypting the final block is checked to see if it has the correct form.
Although the decryption operation can produce an error if padding is enabled,
it is not a strong test that the input data or key is correct. A random block
has better than 1 in 256 chance of being of the correct format and problems with
the input data earlier on will not produce a final decrypt error.
If padding is disabled then the decryption operation will always succeed if
the total amount of data decrypted is a multiple of the block size.
The functions EVP_EncryptInit(), EVP_EncryptFinal(), EVP_DecryptInit(),
EVP_CipherInit() and EVP_CipherFinal() are obsolete but are retained for
compatibility with existing code. New code should use EVP_EncryptInit_ex(),
EVP_EncryptFinal_ex(), EVP_DecryptInit_ex(), EVP_DecryptFinal_ex(),
EVP_CipherInit_ex() and EVP_CipherFinal_ex() because they can reuse an
existing context without allocating and freeing it up on each call.
EVP_get_cipherbynid(), and EVP_get_cipherbyobj() are implemented as macros.
=head1 BUGS
B<EVP_MAX_KEY_LENGTH> and B<EVP_MAX_IV_LENGTH> only refer to the internal
ciphers with default key lengths. If custom ciphers exceed these values the
results are unpredictable. This is because it has become standard practice to
define a generic key as a fixed unsigned char array containing
B<EVP_MAX_KEY_LENGTH> bytes.
The ASN1 code is incomplete (and sometimes inaccurate) it has only been tested
for certain common S/MIME ciphers (RC2, DES, triple DES) in CBC mode.
=head1 EXAMPLES
Encrypt a string using IDEA:
int do_crypt(char *outfile)
{
unsigned char outbuf[1024];
int outlen, tmplen;
/*
* Bogus key and IV: we'd normally set these from
* another source.
*/
unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
unsigned char iv[] = {1,2,3,4,5,6,7,8};
char intext[] = "Some Crypto Text";
EVP_CIPHER_CTX *ctx;
FILE *out;
ctx = EVP_CIPHER_CTX_new();
EVP_EncryptInit_ex(ctx, EVP_idea_cbc(), NULL, key, iv);
if (!EVP_EncryptUpdate(ctx, outbuf, &outlen, intext, strlen(intext))) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
/*
* Buffer passed to EVP_EncryptFinal() must be after data just
* encrypted to avoid overwriting it.
*/
if (!EVP_EncryptFinal_ex(ctx, outbuf + outlen, &tmplen)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
outlen += tmplen;
EVP_CIPHER_CTX_free(ctx);
/*
* Need binary mode for fopen because encrypted data is
* binary data. Also cannot use strlen() on it because
* it won't be NUL terminated and may contain embedded
* NULs.
*/
out = fopen(outfile, "wb");
if (out == NULL) {
/* Error */
return 0;
}
fwrite(outbuf, 1, outlen, out);
fclose(out);
return 1;
}
The ciphertext from the above example can be decrypted using the B<openssl>
utility with the command line (shown on two lines for clarity):
openssl idea -d \
-K 000102030405060708090A0B0C0D0E0F -iv 0102030405060708 <filename
General encryption and decryption function example using FILE I/O and AES128
with a 128-bit key:
int do_crypt(FILE *in, FILE *out, int do_encrypt)
{
/* Allow enough space in output buffer for additional block */
unsigned char inbuf[1024], outbuf[1024 + EVP_MAX_BLOCK_LENGTH];
int inlen, outlen;
EVP_CIPHER_CTX *ctx;
/*
* Bogus key and IV: we'd normally set these from
* another source.
*/
unsigned char key[] = "0123456789abcdeF";
unsigned char iv[] = "1234567887654321";
/* Don't set key or IV right away; we want to check lengths */
ctx = EVP_CIPHER_CTX_new();
EVP_CipherInit_ex(&ctx, EVP_aes_128_cbc(), NULL, NULL, NULL,
do_encrypt);
OPENSSL_assert(EVP_CIPHER_CTX_key_length(ctx) == 16);
OPENSSL_assert(EVP_CIPHER_CTX_iv_length(ctx) == 16);
/* Now we can set key and IV */
EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, do_encrypt);
for (;;) {
inlen = fread(inbuf, 1, 1024, in);
if (inlen <= 0)
break;
if (!EVP_CipherUpdate(ctx, outbuf, &outlen, inbuf, inlen)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
}
if (!EVP_CipherFinal_ex(ctx, outbuf, &outlen)) {
/* Error */
EVP_CIPHER_CTX_free(ctx);
return 0;
}
fwrite(outbuf, 1, outlen, out);
EVP_CIPHER_CTX_free(ctx);
return 1;
}
=head1 SEE ALSO
L<evp(7)>
Supported ciphers are listed in:
L<EVP_aes(3)>,
L<EVP_aria(3)>,
L<EVP_bf(3)>,
L<EVP_camellia(3)>,
L<EVP_cast5(3)>,
L<EVP_chacha20(3)>,
L<EVP_des(3)>,
L<EVP_desx(3)>,
L<EVP_idea(3)>,
L<EVP_rc2(3)>,
L<EVP_rc4(3)>,
L<EVP_rc5(3)>,
L<EVP_seed(3)>,
L<EVP_sm4(3)>
=head1 HISTORY
Support for OCB mode was added in OpenSSL 1.1.0.
B<EVP_CIPHER_CTX> was made opaque in OpenSSL 1.1.0. As a result,
EVP_CIPHER_CTX_reset() appeared and EVP_CIPHER_CTX_cleanup()
disappeared. EVP_CIPHER_CTX_init() remains as an alias for
EVP_CIPHER_CTX_reset().
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_PKEY_meth_new.pod b/doc/man3/EVP_PKEY_meth_new.pod
index db803fc2a268..8a167ce0d6ff 100644
--- a/doc/man3/EVP_PKEY_meth_new.pod
+++ b/doc/man3/EVP_PKEY_meth_new.pod
@@ -1,424 +1,424 @@
=pod
=head1 NAME
EVP_PKEY_meth_new, EVP_PKEY_meth_free, EVP_PKEY_meth_copy, EVP_PKEY_meth_find,
EVP_PKEY_meth_add0, EVP_PKEY_METHOD,
EVP_PKEY_meth_set_init, EVP_PKEY_meth_set_copy, EVP_PKEY_meth_set_cleanup,
EVP_PKEY_meth_set_paramgen, EVP_PKEY_meth_set_keygen, EVP_PKEY_meth_set_sign,
EVP_PKEY_meth_set_verify, EVP_PKEY_meth_set_verify_recover, EVP_PKEY_meth_set_signctx,
EVP_PKEY_meth_set_verifyctx, EVP_PKEY_meth_set_encrypt, EVP_PKEY_meth_set_decrypt,
EVP_PKEY_meth_set_derive, EVP_PKEY_meth_set_ctrl, EVP_PKEY_meth_set_check,
EVP_PKEY_meth_set_public_check, EVP_PKEY_meth_set_param_check,
EVP_PKEY_meth_set_digest_custom,
EVP_PKEY_meth_get_init, EVP_PKEY_meth_get_copy, EVP_PKEY_meth_get_cleanup,
EVP_PKEY_meth_get_paramgen, EVP_PKEY_meth_get_keygen, EVP_PKEY_meth_get_sign,
EVP_PKEY_meth_get_verify, EVP_PKEY_meth_get_verify_recover, EVP_PKEY_meth_get_signctx,
EVP_PKEY_meth_get_verifyctx, EVP_PKEY_meth_get_encrypt, EVP_PKEY_meth_get_decrypt,
EVP_PKEY_meth_get_derive, EVP_PKEY_meth_get_ctrl, EVP_PKEY_meth_get_check,
EVP_PKEY_meth_get_public_check, EVP_PKEY_meth_get_param_check,
EVP_PKEY_meth_get_digest_custom,
EVP_PKEY_meth_remove
- manipulating EVP_PKEY_METHOD structure
=head1 SYNOPSIS
#include <openssl/evp.h>
typedef struct evp_pkey_method_st EVP_PKEY_METHOD;
EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags);
void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth);
void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src);
const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth);
int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth);
void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
int (*init) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
int (*copy) (EVP_PKEY_CTX *dst,
EVP_PKEY_CTX *src));
void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
void (*cleanup) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
int (*paramgen_init) (EVP_PKEY_CTX *ctx),
int (*paramgen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey));
void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
int (*keygen_init) (EVP_PKEY_CTX *ctx),
int (*keygen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey));
void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
int (*sign_init) (EVP_PKEY_CTX *ctx),
int (*sign) (EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen));
void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
int (*verify_init) (EVP_PKEY_CTX *ctx),
int (*verify) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen));
void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
int (*verify_recover_init) (EVP_PKEY_CTX
*ctx),
int (*verify_recover) (EVP_PKEY_CTX
*ctx,
unsigned char
*sig,
size_t *siglen,
const unsigned
char *tbs,
size_t tbslen));
void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
int (*signctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (*signctx) (EVP_PKEY_CTX *ctx,
unsigned char *sig,
size_t *siglen,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
int (*verifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (*verifyctx) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
int siglen,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
int (*encrypt_init) (EVP_PKEY_CTX *ctx),
int (*encryptfn) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen));
void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
int (*decrypt_init) (EVP_PKEY_CTX *ctx),
int (*decrypt) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen));
void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
int (*derive_init) (EVP_PKEY_CTX *ctx),
int (*derive) (EVP_PKEY_CTX *ctx,
unsigned char *key,
size_t *keylen));
void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
void *p2),
int (*ctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value));
void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth,
int (*digest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth,
int (**pinit) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth,
int (**pcopy) (EVP_PKEY_CTX *dst,
EVP_PKEY_CTX *src));
void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth,
void (**pcleanup) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_get_paramgen(const EVP_PKEY_METHOD *pmeth,
int (**pparamgen_init) (EVP_PKEY_CTX *ctx),
int (**pparamgen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey));
void EVP_PKEY_meth_get_keygen(const EVP_PKEY_METHOD *pmeth,
int (**pkeygen_init) (EVP_PKEY_CTX *ctx),
int (**pkeygen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey));
void EVP_PKEY_meth_get_sign(const EVP_PKEY_METHOD *pmeth,
int (**psign_init) (EVP_PKEY_CTX *ctx),
int (**psign) (EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen));
void EVP_PKEY_meth_get_verify(const EVP_PKEY_METHOD *pmeth,
int (**pverify_init) (EVP_PKEY_CTX *ctx),
int (**pverify) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen));
void EVP_PKEY_meth_get_verify_recover(const EVP_PKEY_METHOD *pmeth,
int (**pverify_recover_init) (EVP_PKEY_CTX
*ctx),
int (**pverify_recover) (EVP_PKEY_CTX
*ctx,
unsigned char
*sig,
size_t *siglen,
const unsigned
char *tbs,
size_t tbslen));
void EVP_PKEY_meth_get_signctx(const EVP_PKEY_METHOD *pmeth,
int (**psignctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (**psignctx) (EVP_PKEY_CTX *ctx,
unsigned char *sig,
size_t *siglen,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_get_verifyctx(const EVP_PKEY_METHOD *pmeth,
int (**pverifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (**pverifyctx) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
int siglen,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_get_encrypt(const EVP_PKEY_METHOD *pmeth,
int (**pencrypt_init) (EVP_PKEY_CTX *ctx),
int (**pencryptfn) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen));
void EVP_PKEY_meth_get_decrypt(const EVP_PKEY_METHOD *pmeth,
int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
int (**pdecrypt) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen));
void EVP_PKEY_meth_get_derive(const EVP_PKEY_METHOD *pmeth,
int (**pderive_init) (EVP_PKEY_CTX *ctx),
int (**pderive) (EVP_PKEY_CTX *ctx,
unsigned char *key,
size_t *keylen));
void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth,
int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
void *p2),
int (**pctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value));
void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey));
void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey));
void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey));
void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth,
int (**pdigest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx));
=head1 DESCRIPTION
B<EVP_PKEY_METHOD> is a structure which holds a set of methods for a
specific public key cryptographic algorithm. Those methods are usually
used to perform different jobs, such as generating a key, signing or
verifying, encrypting or decrypting, etc.
There are two places where the B<EVP_PKEY_METHOD> objects are stored: one
is a built-in static array representing the standard methods for different
algorithms, and the other one is a stack of user-defined application-specific
methods, which can be manipulated by using L<EVP_PKEY_meth_add0(3)>.
The B<EVP_PKEY_METHOD> objects are usually referenced by B<EVP_PKEY_CTX>
objects.
=head2 Methods
The methods are the underlying implementations of a particular public key
algorithm present by the B<EVP_PKEY_CTX> object.
int (*init) (EVP_PKEY_CTX *ctx);
int (*copy) (EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src);
void (*cleanup) (EVP_PKEY_CTX *ctx);
The init() method is called to initialize algorithm-specific data when a new
B<EVP_PKEY_CTX> is created. As opposed to init(), the cleanup() method is called
when an B<EVP_PKEY_CTX> is freed. The copy() method is called when an B<EVP_PKEY_CTX>
is being duplicated. Refer to L<EVP_PKEY_CTX_new(3)>, L<EVP_PKEY_CTX_new_id(3)>,
L<EVP_PKEY_CTX_free(3)> and L<EVP_PKEY_CTX_dup(3)>.
int (*paramgen_init) (EVP_PKEY_CTX *ctx);
int (*paramgen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
The paramgen_init() and paramgen() methods deal with key parameter generation.
They are called by L<EVP_PKEY_paramgen_init(3)> and L<EVP_PKEY_paramgen(3)> to
handle the parameter generation process.
int (*keygen_init) (EVP_PKEY_CTX *ctx);
int (*keygen) (EVP_PKEY_CTX *ctx, EVP_PKEY *pkey);
The keygen_init() and keygen() methods are used to generate the actual key for
the specified algorithm. They are called by L<EVP_PKEY_keygen_init(3)> and
L<EVP_PKEY_keygen(3)>.
int (*sign_init) (EVP_PKEY_CTX *ctx);
int (*sign) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen);
The sign_init() and sign() methods are used to generate the signature of a
piece of data using a private key. They are called by L<EVP_PKEY_sign_init(3)>
and L<EVP_PKEY_sign(3)>.
int (*verify_init) (EVP_PKEY_CTX *ctx);
int (*verify) (EVP_PKEY_CTX *ctx,
const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen);
The verify_init() and verify() methods are used to verify whether a signature is
valid. They are called by L<EVP_PKEY_verify_init(3)> and L<EVP_PKEY_verify(3)>.
int (*verify_recover_init) (EVP_PKEY_CTX *ctx);
int (*verify_recover) (EVP_PKEY_CTX *ctx,
unsigned char *rout, size_t *routlen,
const unsigned char *sig, size_t siglen);
The verify_recover_init() and verify_recover() methods are used to verify a
signature and then recover the digest from the signature (for instance, a
signature that was generated by RSA signing algorithm). They are called by
L<EVP_PKEY_verify_recover_init(3)> and L<EVP_PKEY_verify_recover(3)>.
int (*signctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
int (*signctx) (EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
EVP_MD_CTX *mctx);
The signctx_init() and signctx() methods are used to sign a digest present by
a B<EVP_MD_CTX> object. They are called by the EVP_DigestSign functions. See
-L<EVP_DigestSignInit(3)> for detail.
+L<EVP_DigestSignInit(3)> for details.
int (*verifyctx_init) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
int (*verifyctx) (EVP_PKEY_CTX *ctx, const unsigned char *sig, int siglen,
EVP_MD_CTX *mctx);
The verifyctx_init() and verifyctx() methods are used to verify a signature
against the data in a B<EVP_MD_CTX> object. They are called by the various
-EVP_DigestVerify functions. See L<EVP_DigestVerifyInit(3)> for detail.
+EVP_DigestVerify functions. See L<EVP_DigestVerifyInit(3)> for details.
int (*encrypt_init) (EVP_PKEY_CTX *ctx);
int (*encrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen);
The encrypt_init() and encrypt() methods are used to encrypt a piece of data.
They are called by L<EVP_PKEY_encrypt_init(3)> and L<EVP_PKEY_encrypt(3)>.
int (*decrypt_init) (EVP_PKEY_CTX *ctx);
int (*decrypt) (EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen);
The decrypt_init() and decrypt() methods are used to decrypt a piece of data.
They are called by L<EVP_PKEY_decrypt_init(3)> and L<EVP_PKEY_decrypt(3)>.
int (*derive_init) (EVP_PKEY_CTX *ctx);
int (*derive) (EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
The derive_init() and derive() methods are used to derive the shared secret
from a public key algorithm (for instance, the DH algorithm). They are called by
L<EVP_PKEY_derive_init(3)> and L<EVP_PKEY_derive(3)>.
int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1, void *p2);
int (*ctrl_str) (EVP_PKEY_CTX *ctx, const char *type, const char *value);
The ctrl() and ctrl_str() methods are used to adjust algorithm-specific
-settings. See L<EVP_PKEY_CTX_ctrl(3)> and related functions for detail.
+settings. See L<EVP_PKEY_CTX_ctrl(3)> and related functions for details.
int (*digestsign) (EVP_MD_CTX *ctx, unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen);
int (*digestverify) (EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen, const unsigned char *tbs,
size_t tbslen);
The digestsign() and digestverify() methods are used to generate or verify
-a signature in a one-shot mode. They could be called by L<EVP_DigetSign(3)>
+a signature in a one-shot mode. They could be called by L<EVP_DigestSign(3)>
and L<EVP_DigestVerify(3)>.
int (*check) (EVP_PKEY *pkey);
int (*public_check) (EVP_PKEY *pkey);
int (*param_check) (EVP_PKEY *pkey);
The check(), public_check() and param_check() methods are used to validate a
key-pair, the public component and parameters respectively for a given B<pkey>.
They could be called by L<EVP_PKEY_check(3)>, L<EVP_PKEY_public_check(3)> and
L<EVP_PKEY_param_check(3)> respectively.
int (*digest_custom) (EVP_PKEY_CTX *ctx, EVP_MD_CTX *mctx);
The digest_custom() method is used to generate customized digest content before
the real message is passed to functions like L<EVP_DigestSignUpdate(3)> or
L<EVP_DigestVerifyInit(3)>. This is usually required by some public key
signature algorithms like SM2 which requires a hashed prefix to the message to
be signed. The digest_custom() function will be called by L<EVP_DigestSignInit(3)>
and L<EVP_DigestVerifyInit(3)>.
=head2 Functions
EVP_PKEY_meth_new() creates and returns a new B<EVP_PKEY_METHOD> object,
and associates the given B<id> and B<flags>. The following flags are
supported:
EVP_PKEY_FLAG_AUTOARGLEN
EVP_PKEY_FLAG_SIGCTX_CUSTOM
If an B<EVP_PKEY_METHOD> is set with the B<EVP_PKEY_FLAG_AUTOARGLEN> flag, the
maximum size of the output buffer will be automatically calculated or checked
in corresponding EVP methods by the EVP framework. Thus the implementations of
these methods don't need to care about handling the case of returning output
buffer size by themselves. For details on the output buffer size, refer to
L<EVP_PKEY_sign(3)>.
The B<EVP_PKEY_FLAG_SIGCTX_CUSTOM> is used to indicate the signctx() method
of an B<EVP_PKEY_METHOD> is always called by the EVP framework while doing a
digest signing operation by calling L<EVP_DigestSignFinal(3)>.
EVP_PKEY_meth_free() frees an existing B<EVP_PKEY_METHOD> pointed by
B<pmeth>.
EVP_PKEY_meth_copy() copies an B<EVP_PKEY_METHOD> object from B<src>
to B<dst>.
EVP_PKEY_meth_find() finds an B<EVP_PKEY_METHOD> object with the B<id>.
This function first searches through the user-defined method objects and
then the built-in objects.
EVP_PKEY_meth_add0() adds B<pmeth> to the user defined stack of methods.
EVP_PKEY_meth_remove() removes an B<EVP_PKEY_METHOD> object added by
EVP_PKEY_meth_add0().
The EVP_PKEY_meth_set functions set the corresponding fields of
B<EVP_PKEY_METHOD> structure with the arguments passed.
The EVP_PKEY_meth_get functions get the corresponding fields of
B<EVP_PKEY_METHOD> structure to the arguments provided.
=head1 RETURN VALUES
EVP_PKEY_meth_new() returns a pointer to a new B<EVP_PKEY_METHOD>
object or returns NULL on error.
EVP_PKEY_meth_free() and EVP_PKEY_meth_copy() do not return values.
EVP_PKEY_meth_find() returns a pointer to the found B<EVP_PKEY_METHOD>
object or returns NULL if not found.
EVP_PKEY_meth_add0() returns 1 if method is added successfully or 0
if an error occurred.
EVP_PKEY_meth_remove() returns 1 if method is removed successfully or
0 if an error occurred.
All EVP_PKEY_meth_set and EVP_PKEY_meth_get functions have no return
values. For the 'get' functions, function pointers are returned by
arguments.
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_PKEY_set1_RSA.pod b/doc/man3/EVP_PKEY_set1_RSA.pod
index d10fc59d8bcc..d571e58d95ba 100644
--- a/doc/man3/EVP_PKEY_set1_RSA.pod
+++ b/doc/man3/EVP_PKEY_set1_RSA.pod
@@ -1,154 +1,157 @@
=pod
=head1 NAME
EVP_PKEY_set1_RSA, EVP_PKEY_set1_DSA, EVP_PKEY_set1_DH, EVP_PKEY_set1_EC_KEY,
EVP_PKEY_get1_RSA, EVP_PKEY_get1_DSA, EVP_PKEY_get1_DH, EVP_PKEY_get1_EC_KEY,
EVP_PKEY_get0_RSA, EVP_PKEY_get0_DSA, EVP_PKEY_get0_DH, EVP_PKEY_get0_EC_KEY,
EVP_PKEY_assign_RSA, EVP_PKEY_assign_DSA, EVP_PKEY_assign_DH,
EVP_PKEY_assign_EC_KEY, EVP_PKEY_assign_POLY1305, EVP_PKEY_assign_SIPHASH,
EVP_PKEY_get0_hmac, EVP_PKEY_get0_poly1305, EVP_PKEY_get0_siphash,
EVP_PKEY_type, EVP_PKEY_id, EVP_PKEY_base_id, EVP_PKEY_set_alias_type,
-EVP_PKEY_set1_engine - EVP_PKEY assignment functions
+EVP_PKEY_set1_engine, EVP_PKEY_get0_engine - EVP_PKEY assignment functions
=head1 SYNOPSIS
#include <openssl/evp.h>
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, RSA *key);
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, DSA *key);
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, DH *key);
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
RSA *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
DSA *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
DH *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
EC_KEY *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len);
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len);
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len);
RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
DSA *EVP_PKEY_get0_DSA(EVP_PKEY *pkey);
DH *EVP_PKEY_get0_DH(EVP_PKEY *pkey);
EC_KEY *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey);
int EVP_PKEY_assign_RSA(EVP_PKEY *pkey, RSA *key);
int EVP_PKEY_assign_DSA(EVP_PKEY *pkey, DSA *key);
int EVP_PKEY_assign_DH(EVP_PKEY *pkey, DH *key);
int EVP_PKEY_assign_EC_KEY(EVP_PKEY *pkey, EC_KEY *key);
int EVP_PKEY_assign_POLY1305(EVP_PKEY *pkey, ASN1_OCTET_STRING *key);
int EVP_PKEY_assign_SIPHASH(EVP_PKEY *pkey, ASN1_OCTET_STRING *key);
int EVP_PKEY_id(const EVP_PKEY *pkey);
int EVP_PKEY_base_id(const EVP_PKEY *pkey);
int EVP_PKEY_type(int type);
int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type);
+ ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey);
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *engine);
=head1 DESCRIPTION
EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
EVP_PKEY_set1_EC_KEY() set the key referenced by B<pkey> to B<key>.
EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
EVP_PKEY_get1_EC_KEY() return the referenced key in B<pkey> or
B<NULL> if the key is not of the correct type.
EVP_PKEY_get0_hmac(), EVP_PKEY_get0_poly1305(), EVP_PKEY_get0_siphash(),
EVP_PKEY_get0_RSA(), EVP_PKEY_get0_DSA(), EVP_PKEY_get0_DH()
and EVP_PKEY_get0_EC_KEY() also return the referenced key in B<pkey> or B<NULL>
if the key is not of the correct type but the reference count of the
returned key is B<not> incremented and so must not be freed up after use.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305() and
EVP_PKEY_assign_SIPHASH() also set the referenced key to B<key>
however these use the supplied B<key> internally and so B<key>
will be freed when the parent B<pkey> is freed.
EVP_PKEY_base_id() returns the type of B<pkey>. For example
an RSA key will return B<EVP_PKEY_RSA>.
EVP_PKEY_id() returns the actual OID associated with B<pkey>. Historically keys
using the same algorithm could use different OIDs. For example an RSA key could
use the OIDs corresponding to the NIDs B<NID_rsaEncryption> (equivalent to
B<EVP_PKEY_RSA>) or B<NID_rsa> (equivalent to B<EVP_PKEY_RSA2>). The use of
alternative non-standard OIDs is now rare so B<EVP_PKEY_RSA2> et al are not
often seen in practice.
EVP_PKEY_type() returns the underlying type of the NID B<type>. For example
EVP_PKEY_type(EVP_PKEY_RSA2) will return B<EVP_PKEY_RSA>.
+EVP_PKEY_get0_engine() returns a reference to the ENGINE handling B<pkey>.
+
EVP_PKEY_set1_engine() sets the ENGINE handling B<pkey> to B<engine>. It
must be called after the key algorithm and components are set up.
If B<engine> does not include an B<EVP_PKEY_METHOD> for B<pkey> an
error occurs.
EVP_PKEY_set_alias_type() allows modifying a EVP_PKEY to use a
different set of algorithms than the default. This is currently used
to support SM2 keys, which use an identical encoding to ECDSA.
=head1 NOTES
In accordance with the OpenSSL naming convention the key obtained
from or assigned to the B<pkey> using the B<1> functions must be
freed as well as B<pkey>.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305()
and EVP_PKEY_assign_SIPHASH() are implemented as macros.
Most applications wishing to know a key type will simply call
EVP_PKEY_base_id() and will not care about the actual type:
which will be identical in almost all cases.
Previous versions of this document suggested using EVP_PKEY_type(pkey->type)
to determine the type of a key. Since B<EVP_PKEY> is now opaque this
is no longer possible: the equivalent is EVP_PKEY_base_id(pkey).
EVP_PKEY_set1_engine() is typically used by an ENGINE returning an HSM
key as part of its routine to load a private key.
-=head1 EXAMPLES
-
-After loading an ECC key, it is possible to convert it to using SM2
-algorithms with EVP_PKEY_set_alias_type:
-
- EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
-
=head1 RETURN VALUES
EVP_PKEY_set1_RSA(), EVP_PKEY_set1_DSA(), EVP_PKEY_set1_DH() and
EVP_PKEY_set1_EC_KEY() return 1 for success or 0 for failure.
EVP_PKEY_get1_RSA(), EVP_PKEY_get1_DSA(), EVP_PKEY_get1_DH() and
EVP_PKEY_get1_EC_KEY() return the referenced key or B<NULL> if
an error occurred.
EVP_PKEY_assign_RSA(), EVP_PKEY_assign_DSA(), EVP_PKEY_assign_DH(),
EVP_PKEY_assign_EC_KEY(), EVP_PKEY_assign_POLY1305()
and EVP_PKEY_assign_SIPHASH() return 1 for success and 0 for failure.
EVP_PKEY_base_id(), EVP_PKEY_id() and EVP_PKEY_type() return a key
type or B<NID_undef> (equivalently B<EVP_PKEY_NONE>) on error.
EVP_PKEY_set1_engine() returns 1 for success and 0 for failure.
EVP_PKEY_set_alias_type() returns 1 for success and 0 for error.
+=head1 EXAMPLES
+
+After loading an ECC key, it is possible to convert it to using SM2
+algorithms with EVP_PKEY_set_alias_type:
+
+ EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
+
=head1 SEE ALSO
L<EVP_PKEY_new(3)>
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/EVP_chacha20.pod b/doc/man3/EVP_chacha20.pod
index 96da825cded4..a21b64859568 100644
--- a/doc/man3/EVP_chacha20.pod
+++ b/doc/man3/EVP_chacha20.pod
@@ -1,57 +1,65 @@
=pod
=head1 NAME
EVP_chacha20,
EVP_chacha20_poly1305
- EVP ChaCha20 stream cipher
=head1 SYNOPSIS
#include <openssl/evp.h>
const EVP_CIPHER *EVP_chacha20(void)
const EVP_CIPHER *EVP_chacha20_poly1305(void)
=head1 DESCRIPTION
The ChaCha20 stream cipher for EVP.
=over 4
=item EVP_chacha20()
-The ChaCha20 stream cipher. The key length is 256 bits, the IV is 96 bits long.
+The ChaCha20 stream cipher. The key length is 256 bits, the IV is 128 bits long.
+The first 32 bits consists of a counter in little-endian order followed by a 96
+bit nonce. For example a nonce of:
+
+000000000000000000000002
+
+With an initial counter of 42 (2a in hex) would be expressed as:
+
+2a000000000000000000000000000002
=item EVP_chacha20_poly1305()
Authenticated encryption with ChaCha20-Poly1305. Like EVP_chacha20(), the key
is 256 bits and the IV is 96 bits. This supports additional authenticated data
(AAD) and produces a 128-bit authentication tag. See the
L<EVP_EncryptInit(3)/AEAD Interface> section for more information.
=back
=head1 RETURN VALUES
These functions return an B<EVP_CIPHER> structure that contains the
implementation of the symmetric cipher. See L<EVP_CIPHER_meth_new(3)> for
details of the B<EVP_CIPHER> structure.
=head1 SEE ALSO
L<evp(7)>,
L<EVP_EncryptInit(3)>,
L<EVP_CIPHER_meth_new(3)>
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/HMAC.pod b/doc/man3/HMAC.pod
index 65386a7baa31..30c0e6bac392 100644
--- a/doc/man3/HMAC.pod
+++ b/doc/man3/HMAC.pod
@@ -1,157 +1,159 @@
=pod
=head1 NAME
HMAC,
HMAC_CTX_new,
HMAC_CTX_reset,
HMAC_CTX_free,
HMAC_Init,
HMAC_Init_ex,
HMAC_Update,
HMAC_Final,
HMAC_CTX_copy,
HMAC_CTX_set_flags,
HMAC_CTX_get_md,
HMAC_size
- HMAC message authentication code
=head1 SYNOPSIS
#include <openssl/hmac.h>
unsigned char *HMAC(const EVP_MD *evp_md, const void *key,
int key_len, const unsigned char *d, int n,
unsigned char *md, unsigned int *md_len);
HMAC_CTX *HMAC_CTX_new(void);
int HMAC_CTX_reset(HMAC_CTX *ctx);
int HMAC_Init_ex(HMAC_CTX *ctx, const void *key, int key_len,
const EVP_MD *md, ENGINE *impl);
int HMAC_Update(HMAC_CTX *ctx, const unsigned char *data, int len);
int HMAC_Final(HMAC_CTX *ctx, unsigned char *md, unsigned int *len);
void HMAC_CTX_free(HMAC_CTX *ctx);
int HMAC_CTX_copy(HMAC_CTX *dctx, HMAC_CTX *sctx);
void HMAC_CTX_set_flags(HMAC_CTX *ctx, unsigned long flags);
const EVP_MD *HMAC_CTX_get_md(const HMAC_CTX *ctx);
size_t HMAC_size(const HMAC_CTX *e);
Deprecated:
#if OPENSSL_API_COMPAT < 0x10100000L
int HMAC_Init(HMAC_CTX *ctx, const void *key, int key_len,
const EVP_MD *md);
#endif
=head1 DESCRIPTION
HMAC is a MAC (message authentication code), i.e. a keyed hash
function used for message authentication, which is based on a hash
function.
HMAC() computes the message authentication code of the B<n> bytes at
B<d> using the hash function B<evp_md> and the key B<key> which is
B<key_len> bytes long.
It places the result in B<md> (which must have space for the output of
the hash function, which is no more than B<EVP_MAX_MD_SIZE> bytes).
If B<md> is NULL, the digest is placed in a static array. The size of
the output is placed in B<md_len>, unless it is B<NULL>. Note: passing a NULL
value for B<md> to use the static array is not thread safe.
-B<evp_md> can be EVP_sha1(), EVP_ripemd160() etc.
+B<evp_md> is a message digest such as EVP_sha1(), EVP_ripemd160() etc. HMAC does
+not support variable output length digests such as EVP_shake128() and
+EVP_shake256().
HMAC_CTX_new() creates a new HMAC_CTX in heap memory.
HMAC_CTX_reset() zeroes an existing B<HMAC_CTX> and associated
resources, making it suitable for new computations as if it was newly
created with HMAC_CTX_new().
HMAC_CTX_free() erases the key and other data from the B<HMAC_CTX>,
releases any associated resources and finally frees the B<HMAC_CTX>
itself.
The following functions may be used if the message is not completely
stored in memory:
HMAC_Init_ex() initializes or reuses a B<HMAC_CTX> structure to use the hash
function B<evp_md> and key B<key>. If both are NULL, or if B<key> is NULL
and B<evp_md> is the same as the previous call, then the
existing key is
reused. B<ctx> must have been created with HMAC_CTX_new() before the first use
of an B<HMAC_CTX> in this function.
If HMAC_Init_ex() is called with B<key> NULL and B<evp_md> is not the
same as the previous digest used by B<ctx> then an error is returned
because reuse of an existing key with a different digest is not supported.
HMAC_Init() initializes a B<HMAC_CTX> structure to use the hash
function B<evp_md> and the key B<key> which is B<key_len> bytes
long.
HMAC_Update() can be called repeatedly with chunks of the message to
be authenticated (B<len> bytes at B<data>).
HMAC_Final() places the message authentication code in B<md>, which
must have space for the hash function output.
HMAC_CTX_copy() copies all of the internal state from B<sctx> into B<dctx>.
HMAC_CTX_set_flags() applies the specified flags to the internal EVP_MD_CTXs.
These flags have the same meaning as for L<EVP_MD_CTX_set_flags(3)>.
HMAC_CTX_get_md() returns the EVP_MD that has previously been set for the
supplied HMAC_CTX.
HMAC_size() returns the length in bytes of the underlying hash function output.
=head1 RETURN VALUES
HMAC() returns a pointer to the message authentication code or NULL if
an error occurred.
HMAC_CTX_new() returns a pointer to a new B<HMAC_CTX> on success or
B<NULL> if an error occurred.
HMAC_CTX_reset(), HMAC_Init_ex(), HMAC_Update(), HMAC_Final() and
HMAC_CTX_copy() return 1 for success or 0 if an error occurred.
HMAC_CTX_get_md() return the EVP_MD previously set for the supplied HMAC_CTX or
NULL if no EVP_MD has been set.
HMAC_size() returns the length in bytes of the underlying hash function output
or zero on error.
=head1 CONFORMING TO
RFC 2104
=head1 SEE ALSO
L<SHA1(3)>, L<evp(7)>
=head1 HISTORY
HMAC_CTX_init() was replaced with HMAC_CTX_reset() in OpenSSL 1.1.0.
HMAC_CTX_cleanup() existed in OpenSSL before version 1.1.0.
HMAC_CTX_new(), HMAC_CTX_free() and HMAC_CTX_get_md() are new in OpenSSL 1.1.0.
HMAC_Init_ex(), HMAC_Update() and HMAC_Final() did not return values in
OpenSSL before version 1.0.0.
=head1 COPYRIGHT
Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/OBJ_nid2obj.pod b/doc/man3/OBJ_nid2obj.pod
index cbf889f2c711..f84d5b1eb384 100644
--- a/doc/man3/OBJ_nid2obj.pod
+++ b/doc/man3/OBJ_nid2obj.pod
@@ -1,191 +1,191 @@
=pod
=head1 NAME
i2t_ASN1_OBJECT,
OBJ_length, OBJ_get0_data, OBJ_nid2obj, OBJ_nid2ln,
OBJ_nid2sn, OBJ_obj2nid, OBJ_txt2nid, OBJ_ln2nid, OBJ_sn2nid, OBJ_cmp,
OBJ_dup, OBJ_txt2obj, OBJ_obj2txt, OBJ_create, OBJ_cleanup
- ASN1 object utility functions
=head1 SYNOPSIS
#include <openssl/objects.h>
ASN1_OBJECT *OBJ_nid2obj(int n);
const char *OBJ_nid2ln(int n);
const char *OBJ_nid2sn(int n);
int OBJ_obj2nid(const ASN1_OBJECT *o);
int OBJ_ln2nid(const char *ln);
int OBJ_sn2nid(const char *sn);
int OBJ_txt2nid(const char *s);
ASN1_OBJECT *OBJ_txt2obj(const char *s, int no_name);
int OBJ_obj2txt(char *buf, int buf_len, const ASN1_OBJECT *a, int no_name);
int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a);
int OBJ_cmp(const ASN1_OBJECT *a, const ASN1_OBJECT *b);
ASN1_OBJECT *OBJ_dup(const ASN1_OBJECT *o);
int OBJ_create(const char *oid, const char *sn, const char *ln);
size_t OBJ_length(const ASN1_OBJECT *obj);
const unsigned char *OBJ_get0_data(const ASN1_OBJECT *obj);
Deprecated:
#if OPENSSL_API_COMPAT < 0x10100000L
void OBJ_cleanup(void)
#endif
=head1 DESCRIPTION
The ASN1 object utility functions process ASN1_OBJECT structures which are
a representation of the ASN1 OBJECT IDENTIFIER (OID) type.
For convenience, OIDs are usually represented in source code as numeric
identifiers, or B<NID>s. OpenSSL has an internal table of OIDs that
are generated when the library is built, and their corresponding NIDs
are available as defined constants. For the functions below, application
code should treat all returned values -- OIDs, NIDs, or names -- as
constants.
OBJ_nid2obj(), OBJ_nid2ln() and OBJ_nid2sn() convert the NID B<n> to
an ASN1_OBJECT structure, its long name and its short name respectively,
or B<NULL> if an error occurred.
OBJ_obj2nid(), OBJ_ln2nid(), OBJ_sn2nid() return the corresponding NID
for the object B<o>, the long name <ln> or the short name <sn> respectively
or NID_undef if an error occurred.
OBJ_txt2nid() returns NID corresponding to text string <s>. B<s> can be
a long name, a short name or the numerical representation of an object.
OBJ_txt2obj() converts the text string B<s> into an ASN1_OBJECT structure.
If B<no_name> is 0 then long names and short names will be interpreted
as well as numerical forms. If B<no_name> is 1 only the numerical form
is acceptable.
OBJ_obj2txt() converts the B<ASN1_OBJECT> B<a> into a textual representation.
The representation is written as a null terminated string to B<buf>
at most B<buf_len> bytes are written, truncating the result if necessary.
The total amount of space required is returned. If B<no_name> is 0 then
if the object has a long or short name then that will be used, otherwise
the numerical form will be used. If B<no_name> is 1 then the numerical
form will always be used.
i2t_ASN1_OBJECT() is the same as OBJ_obj2txt() with the B<no_name> set to zero.
OBJ_cmp() compares B<a> to B<b>. If the two are identical 0 is returned.
OBJ_dup() returns a copy of B<o>.
OBJ_create() adds a new object to the internal table. B<oid> is the
numerical form of the object, B<sn> the short name and B<ln> the
long name. A new NID is returned for the created object in case of
success and NID_undef in case of failure.
OBJ_length() returns the size of the content octets of B<obj>.
OBJ_get0_data() returns a pointer to the content octets of B<obj>.
The returned pointer is an internal pointer which B<must not> be freed.
OBJ_cleanup() releases any resources allocated by creating new objects.
=head1 NOTES
Objects in OpenSSL can have a short name, a long name and a numerical
identifier (NID) associated with them. A standard set of objects is
represented in an internal table. The appropriate values are defined
in the header file B<objects.h>.
For example the OID for commonName has the following definitions:
#define SN_commonName "CN"
#define LN_commonName "commonName"
#define NID_commonName 13
New objects can be added by calling OBJ_create().
Table objects have certain advantages over other objects: for example
their NIDs can be used in a C language switch statement. They are
also static constant structures which are shared: that is there
is only a single constant structure for each table object.
Objects which are not in the table have the NID value NID_undef.
Objects do not need to be in the internal tables to be processed,
the functions OBJ_txt2obj() and OBJ_obj2txt() can process the numerical
form of an OID.
Some objects are used to represent algorithms which do not have a
corresponding ASN.1 OBJECT IDENTIFIER encoding (for example no OID currently
exists for a particular algorithm). As a result they B<cannot> be encoded or
decoded as part of ASN.1 structures. Applications can determine if there
is a corresponding OBJECT IDENTIFIER by checking OBJ_length() is not zero.
These functions cannot return B<const> because an B<ASN1_OBJECT> can
represent both an internal, constant, OID and a dynamically-created one.
The latter cannot be constant because it needs to be freed after use.
+=head1 RETURN VALUES
+
+OBJ_nid2obj() returns an B<ASN1_OBJECT> structure or B<NULL> is an
+error occurred.
+
+OBJ_nid2ln() and OBJ_nid2sn() returns a valid string or B<NULL>
+on error.
+
+OBJ_obj2nid(), OBJ_ln2nid(), OBJ_sn2nid() and OBJ_txt2nid() return
+a NID or B<NID_undef> on error.
+
=head1 EXAMPLES
Create an object for B<commonName>:
ASN1_OBJECT *o = OBJ_nid2obj(NID_commonName);
Check if an object is B<commonName>
if (OBJ_obj2nid(obj) == NID_commonName)
/* Do something */
Create a new NID and initialize an object from it:
int new_nid = OBJ_create("1.2.3.4", "NewOID", "New Object Identifier");
ASN1_OBJECT *obj = OBJ_nid2obj(new_nid);
Create a new object directly:
obj = OBJ_txt2obj("1.2.3.4", 1);
=head1 BUGS
OBJ_obj2txt() is awkward and messy to use: it doesn't follow the
convention of other OpenSSL functions where the buffer can be set
to B<NULL> to determine the amount of data that should be written.
Instead B<buf> must point to a valid buffer and B<buf_len> should
be set to a positive value. A buffer length of 80 should be more
than enough to handle any OID encountered in practice.
-=head1 RETURN VALUES
-
-OBJ_nid2obj() returns an B<ASN1_OBJECT> structure or B<NULL> is an
-error occurred.
-
-OBJ_nid2ln() and OBJ_nid2sn() returns a valid string or B<NULL>
-on error.
-
-OBJ_obj2nid(), OBJ_ln2nid(), OBJ_sn2nid() and OBJ_txt2nid() return
-a NID or B<NID_undef> on error.
-
=head1 SEE ALSO
L<ERR_get_error(3)>
=head1 HISTORY
OBJ_cleanup() was deprecated in OpenSSL 1.1.0 by L<OPENSSL_init_crypto(3)>
and should not be used.
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/OCSP_cert_to_id.pod b/doc/man3/OCSP_cert_to_id.pod
index f1a4b1512b64..c8d39c191358 100644
--- a/doc/man3/OCSP_cert_to_id.pod
+++ b/doc/man3/OCSP_cert_to_id.pod
@@ -1,89 +1,89 @@
=pod
=head1 NAME
OCSP_cert_to_id, OCSP_cert_id_new, OCSP_CERTID_free, OCSP_id_issuer_cmp,
OCSP_id_cmp, OCSP_id_get0_info - OCSP certificate ID utility functions
=head1 SYNOPSIS
#include <openssl/ocsp.h>
OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst,
X509 *subject, X509 *issuer);
OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
X509_NAME *issuerName,
ASN1_BIT_STRING *issuerKey,
ASN1_INTEGER *serialNumber);
void OCSP_CERTID_free(OCSP_CERTID *id);
- int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
- int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+ int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
+ int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
ASN1_OCTET_STRING **pikeyHash,
ASN1_INTEGER **pserial, OCSP_CERTID *cid);
=head1 DESCRIPTION
OCSP_cert_to_id() creates and returns a new B<OCSP_CERTID> structure using
message digest B<dgst> for certificate B<subject> with issuer B<issuer>. If
B<dgst> is B<NULL> then SHA1 is used.
OCSP_cert_id_new() creates and returns a new B<OCSP_CERTID> using B<dgst> and
issuer name B<issuerName>, issuer key hash B<issuerKey> and serial number
B<serialNumber>.
OCSP_CERTID_free() frees up B<id>.
OCSP_id_cmp() compares B<OCSP_CERTID> B<a> and B<b>.
OCSP_id_issuer_cmp() compares only the issuer name of B<OCSP_CERTID> B<a> and B<b>.
OCSP_id_get0_info() returns the issuer name hash, hash OID, issuer key hash and
serial number contained in B<cid>. If any of the values are not required the
corresponding parameter can be set to B<NULL>.
=head1 RETURN VALUES
OCSP_cert_to_id() and OCSP_cert_id_new() return either a pointer to a valid
B<OCSP_CERTID> structure or B<NULL> if an error occurred.
OCSP_id_cmp() and OCSP_id_issuer_cmp() returns zero for a match and non-zero
otherwise.
OCSP_CERTID_free() does not return a value.
OCSP_id_get0_info() returns 1 for success and 0 for failure.
=head1 NOTES
OCSP clients will typically only use OCSP_cert_to_id() or OCSP_cert_id_new():
the other functions are used by responder applications.
The values returned by OCSP_id_get0_info() are internal pointers and B<MUST
NOT> be freed up by an application: they will be freed when the corresponding
B<OCSP_CERTID> structure is freed.
=head1 SEE ALSO
L<crypto(7)>,
L<OCSP_request_add1_nonce(3)>,
L<OCSP_REQUEST_new(3)>,
L<OCSP_resp_find_status(3)>,
L<OCSP_response_status(3)>,
L<OCSP_sendreq_new(3)>
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/PEM_read_bio_PrivateKey.pod b/doc/man3/PEM_read_bio_PrivateKey.pod
index 744a46f81ed9..7c381e85feff 100644
--- a/doc/man3/PEM_read_bio_PrivateKey.pod
+++ b/doc/man3/PEM_read_bio_PrivateKey.pod
@@ -1,483 +1,483 @@
=pod
=head1 NAME
pem_password_cb,
PEM_read_bio_PrivateKey, PEM_read_PrivateKey, PEM_write_bio_PrivateKey,
PEM_write_bio_PrivateKey_traditional, PEM_write_PrivateKey,
PEM_write_bio_PKCS8PrivateKey, PEM_write_PKCS8PrivateKey,
PEM_write_bio_PKCS8PrivateKey_nid, PEM_write_PKCS8PrivateKey_nid,
PEM_read_bio_PUBKEY, PEM_read_PUBKEY, PEM_write_bio_PUBKEY, PEM_write_PUBKEY,
PEM_read_bio_RSAPrivateKey, PEM_read_RSAPrivateKey,
PEM_write_bio_RSAPrivateKey, PEM_write_RSAPrivateKey,
PEM_read_bio_RSAPublicKey, PEM_read_RSAPublicKey, PEM_write_bio_RSAPublicKey,
PEM_write_RSAPublicKey, PEM_read_bio_RSA_PUBKEY, PEM_read_RSA_PUBKEY,
PEM_write_bio_RSA_PUBKEY, PEM_write_RSA_PUBKEY, PEM_read_bio_DSAPrivateKey,
PEM_read_DSAPrivateKey, PEM_write_bio_DSAPrivateKey, PEM_write_DSAPrivateKey,
PEM_read_bio_DSA_PUBKEY, PEM_read_DSA_PUBKEY, PEM_write_bio_DSA_PUBKEY,
PEM_write_DSA_PUBKEY, PEM_read_bio_DSAparams, PEM_read_DSAparams,
PEM_write_bio_DSAparams, PEM_write_DSAparams, PEM_read_bio_DHparams,
PEM_read_DHparams, PEM_write_bio_DHparams, PEM_write_DHparams,
PEM_read_bio_X509, PEM_read_X509, PEM_write_bio_X509, PEM_write_X509,
PEM_read_bio_X509_AUX, PEM_read_X509_AUX, PEM_write_bio_X509_AUX,
PEM_write_X509_AUX, PEM_read_bio_X509_REQ, PEM_read_X509_REQ,
PEM_write_bio_X509_REQ, PEM_write_X509_REQ, PEM_write_bio_X509_REQ_NEW,
PEM_write_X509_REQ_NEW, PEM_read_bio_X509_CRL, PEM_read_X509_CRL,
PEM_write_bio_X509_CRL, PEM_write_X509_CRL, PEM_read_bio_PKCS7, PEM_read_PKCS7,
PEM_write_bio_PKCS7, PEM_write_PKCS7 - PEM routines
=head1 SYNOPSIS
#include <openssl/pem.h>
typedef int pem_password_cb(char *buf, int size, int rwflag, void *u);
EVP_PKEY *PEM_read_bio_PrivateKey(BIO *bp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_bio_PrivateKey_traditional(BIO *bp, EVP_PKEY *x,
const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_bio_PKCS8PrivateKey(BIO *bp, EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_PKCS8PrivateKey(FILE *fp, EVP_PKEY *x, const EVP_CIPHER *enc,
char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_bio_PKCS8PrivateKey_nid(BIO *bp, EVP_PKEY *x, int nid,
char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_PKCS8PrivateKey_nid(FILE *fp, EVP_PKEY *x, int nid,
char *kstr, int klen,
pem_password_cb *cb, void *u);
EVP_PKEY *PEM_read_bio_PUBKEY(BIO *bp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
EVP_PKEY *PEM_read_PUBKEY(FILE *fp, EVP_PKEY **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_PUBKEY(BIO *bp, EVP_PKEY *x);
int PEM_write_PUBKEY(FILE *fp, EVP_PKEY *x);
RSA *PEM_read_bio_RSAPrivateKey(BIO *bp, RSA **x,
pem_password_cb *cb, void *u);
RSA *PEM_read_RSAPrivateKey(FILE *fp, RSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_RSAPrivateKey(BIO *bp, RSA *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_RSAPrivateKey(FILE *fp, RSA *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
RSA *PEM_read_bio_RSAPublicKey(BIO *bp, RSA **x,
pem_password_cb *cb, void *u);
RSA *PEM_read_RSAPublicKey(FILE *fp, RSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_RSAPublicKey(BIO *bp, RSA *x);
int PEM_write_RSAPublicKey(FILE *fp, RSA *x);
RSA *PEM_read_bio_RSA_PUBKEY(BIO *bp, RSA **x,
pem_password_cb *cb, void *u);
RSA *PEM_read_RSA_PUBKEY(FILE *fp, RSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_RSA_PUBKEY(BIO *bp, RSA *x);
int PEM_write_RSA_PUBKEY(FILE *fp, RSA *x);
DSA *PEM_read_bio_DSAPrivateKey(BIO *bp, DSA **x,
pem_password_cb *cb, void *u);
DSA *PEM_read_DSAPrivateKey(FILE *fp, DSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_DSAPrivateKey(BIO *bp, DSA *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
int PEM_write_DSAPrivateKey(FILE *fp, DSA *x, const EVP_CIPHER *enc,
unsigned char *kstr, int klen,
pem_password_cb *cb, void *u);
DSA *PEM_read_bio_DSA_PUBKEY(BIO *bp, DSA **x,
pem_password_cb *cb, void *u);
DSA *PEM_read_DSA_PUBKEY(FILE *fp, DSA **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_DSA_PUBKEY(BIO *bp, DSA *x);
int PEM_write_DSA_PUBKEY(FILE *fp, DSA *x);
DSA *PEM_read_bio_DSAparams(BIO *bp, DSA **x, pem_password_cb *cb, void *u);
DSA *PEM_read_DSAparams(FILE *fp, DSA **x, pem_password_cb *cb, void *u);
int PEM_write_bio_DSAparams(BIO *bp, DSA *x);
int PEM_write_DSAparams(FILE *fp, DSA *x);
DH *PEM_read_bio_DHparams(BIO *bp, DH **x, pem_password_cb *cb, void *u);
DH *PEM_read_DHparams(FILE *fp, DH **x, pem_password_cb *cb, void *u);
int PEM_write_bio_DHparams(BIO *bp, DH *x);
int PEM_write_DHparams(FILE *fp, DH *x);
X509 *PEM_read_bio_X509(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
X509 *PEM_read_X509(FILE *fp, X509 **x, pem_password_cb *cb, void *u);
int PEM_write_bio_X509(BIO *bp, X509 *x);
int PEM_write_X509(FILE *fp, X509 *x);
X509 *PEM_read_bio_X509_AUX(BIO *bp, X509 **x, pem_password_cb *cb, void *u);
X509 *PEM_read_X509_AUX(FILE *fp, X509 **x, pem_password_cb *cb, void *u);
int PEM_write_bio_X509_AUX(BIO *bp, X509 *x);
int PEM_write_X509_AUX(FILE *fp, X509 *x);
X509_REQ *PEM_read_bio_X509_REQ(BIO *bp, X509_REQ **x,
pem_password_cb *cb, void *u);
X509_REQ *PEM_read_X509_REQ(FILE *fp, X509_REQ **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_X509_REQ(BIO *bp, X509_REQ *x);
int PEM_write_X509_REQ(FILE *fp, X509_REQ *x);
int PEM_write_bio_X509_REQ_NEW(BIO *bp, X509_REQ *x);
int PEM_write_X509_REQ_NEW(FILE *fp, X509_REQ *x);
X509_CRL *PEM_read_bio_X509_CRL(BIO *bp, X509_CRL **x,
pem_password_cb *cb, void *u);
X509_CRL *PEM_read_X509_CRL(FILE *fp, X509_CRL **x,
pem_password_cb *cb, void *u);
int PEM_write_bio_X509_CRL(BIO *bp, X509_CRL *x);
int PEM_write_X509_CRL(FILE *fp, X509_CRL *x);
PKCS7 *PEM_read_bio_PKCS7(BIO *bp, PKCS7 **x, pem_password_cb *cb, void *u);
PKCS7 *PEM_read_PKCS7(FILE *fp, PKCS7 **x, pem_password_cb *cb, void *u);
int PEM_write_bio_PKCS7(BIO *bp, PKCS7 *x);
int PEM_write_PKCS7(FILE *fp, PKCS7 *x);
=head1 DESCRIPTION
The PEM functions read or write structures in PEM format. In
this sense PEM format is simply base64 encoded data surrounded
by header lines.
For more details about the meaning of arguments see the
B<PEM FUNCTION ARGUMENTS> section.
Each operation has four functions associated with it. For
brevity the term "B<TYPE> functions" will be used below to collectively
refer to the PEM_read_bio_TYPE(), PEM_read_TYPE(),
PEM_write_bio_TYPE(), and PEM_write_TYPE() functions.
The B<PrivateKey> functions read or write a private key in PEM format using an
EVP_PKEY structure. The write routines use PKCS#8 private key format and are
equivalent to PEM_write_bio_PKCS8PrivateKey().The read functions transparently
handle traditional and PKCS#8 format encrypted and unencrypted keys.
PEM_write_bio_PrivateKey_traditional() writes out a private key in the
"traditional" format with a simple private key marker and should only
be used for compatibility with legacy programs.
PEM_write_bio_PKCS8PrivateKey() and PEM_write_PKCS8PrivateKey() write a private
key in an EVP_PKEY structure in PKCS#8 EncryptedPrivateKeyInfo format using
PKCS#5 v2.0 password based encryption algorithms. The B<cipher> argument
specifies the encryption algorithm to use: unlike some other PEM routines the
encryption is applied at the PKCS#8 level and not in the PEM headers. If
B<cipher> is NULL then no encryption is used and a PKCS#8 PrivateKeyInfo
structure is used instead.
PEM_write_bio_PKCS8PrivateKey_nid() and PEM_write_PKCS8PrivateKey_nid()
also write out a private key as a PKCS#8 EncryptedPrivateKeyInfo however
it uses PKCS#5 v1.5 or PKCS#12 encryption algorithms instead. The algorithm
to use is specified in the B<nid> parameter and should be the NID of the
corresponding OBJECT IDENTIFIER (see NOTES section).
The B<PUBKEY> functions process a public key using an EVP_PKEY
structure. The public key is encoded as a SubjectPublicKeyInfo
structure.
The B<RSAPrivateKey> functions process an RSA private key using an
RSA structure. The write routines uses traditional format. The read
routines handles the same formats as the B<PrivateKey>
functions but an error occurs if the private key is not RSA.
The B<RSAPublicKey> functions process an RSA public key using an
RSA structure. The public key is encoded using a PKCS#1 RSAPublicKey
structure.
The B<RSA_PUBKEY> functions also process an RSA public key using
an RSA structure. However the public key is encoded using a
SubjectPublicKeyInfo structure and an error occurs if the public
key is not RSA.
The B<DSAPrivateKey> functions process a DSA private key using a
DSA structure. The write routines uses traditional format. The read
routines handles the same formats as the B<PrivateKey>
functions but an error occurs if the private key is not DSA.
The B<DSA_PUBKEY> functions process a DSA public key using
a DSA structure. The public key is encoded using a
SubjectPublicKeyInfo structure and an error occurs if the public
key is not DSA.
The B<DSAparams> functions process DSA parameters using a DSA
structure. The parameters are encoded using a Dss-Parms structure
as defined in RFC2459.
The B<DHparams> functions process DH parameters using a DH
structure. The parameters are encoded using a PKCS#3 DHparameter
structure.
The B<X509> functions process an X509 certificate using an X509
structure. They will also process a trusted X509 certificate but
any trust settings are discarded.
The B<X509_AUX> functions process a trusted X509 certificate using
an X509 structure.
The B<X509_REQ> and B<X509_REQ_NEW> functions process a PKCS#10
certificate request using an X509_REQ structure. The B<X509_REQ>
write functions use B<CERTIFICATE REQUEST> in the header whereas
the B<X509_REQ_NEW> functions use B<NEW CERTIFICATE REQUEST>
(as required by some CAs). The B<X509_REQ> read functions will
handle either form so there are no B<X509_REQ_NEW> read functions.
The B<X509_CRL> functions process an X509 CRL using an X509_CRL
structure.
The B<PKCS7> functions process a PKCS#7 ContentInfo using a PKCS7
structure.
=head1 PEM FUNCTION ARGUMENTS
The PEM functions have many common arguments.
The B<bp> BIO parameter (if present) specifies the BIO to read from
or write to.
The B<fp> FILE parameter (if present) specifies the FILE pointer to
read from or write to.
The PEM read functions all take an argument B<TYPE **x> and return
a B<TYPE *> pointer. Where B<TYPE> is whatever structure the function
uses. If B<x> is NULL then the parameter is ignored. If B<x> is not
NULL but B<*x> is NULL then the structure returned will be written
to B<*x>. If neither B<x> nor B<*x> is NULL then an attempt is made
to reuse the structure at B<*x> (but see BUGS and EXAMPLES sections).
Irrespective of the value of B<x> a pointer to the structure is always
returned (or NULL if an error occurred).
The PEM functions which write private keys take an B<enc> parameter
which specifies the encryption algorithm to use, encryption is done
at the PEM level. If this parameter is set to NULL then the private
key is written in unencrypted form.
The B<cb> argument is the callback to use when querying for the pass
phrase used for encrypted PEM structures (normally only private keys).
For the PEM write routines if the B<kstr> parameter is not NULL then
B<klen> bytes at B<kstr> are used as the passphrase and B<cb> is
ignored.
If the B<cb> parameters is set to NULL and the B<u> parameter is not
NULL then the B<u> parameter is interpreted as a null terminated string
to use as the passphrase. If both B<cb> and B<u> are NULL then the
default callback routine is used which will typically prompt for the
passphrase on the current terminal with echoing turned off.
The default passphrase callback is sometimes inappropriate (for example
in a GUI application) so an alternative can be supplied. The callback
routine has the following form:
int cb(char *buf, int size, int rwflag, void *u);
B<buf> is the buffer to write the passphrase to. B<size> is the maximum
length of the passphrase (i.e. the size of buf). B<rwflag> is a flag
which is set to 0 when reading and 1 when writing. A typical routine
will ask the user to verify the passphrase (for example by prompting
for it twice) if B<rwflag> is 1. The B<u> parameter has the same
value as the B<u> parameter passed to the PEM routine. It allows
arbitrary data to be passed to the callback by the application
(for example a window handle in a GUI application). The callback
B<must> return the number of characters in the passphrase or -1 if
an error occurred.
-=head1 EXAMPLES
-
-Although the PEM routines take several arguments in almost all applications
-most of them are set to 0 or NULL.
-
-Read a certificate in PEM format from a BIO:
-
- X509 *x;
-
- x = PEM_read_bio_X509(bp, NULL, 0, NULL);
- if (x == NULL)
- /* Error */
-
-Alternative method:
-
- X509 *x = NULL;
-
- if (!PEM_read_bio_X509(bp, &x, 0, NULL))
- /* Error */
-
-Write a certificate to a BIO:
-
- if (!PEM_write_bio_X509(bp, x))
- /* Error */
-
-Write a private key (using traditional format) to a BIO using
-triple DES encryption, the pass phrase is prompted for:
-
- if (!PEM_write_bio_PrivateKey(bp, key, EVP_des_ede3_cbc(), NULL, 0, 0, NULL))
- /* Error */
-
-Write a private key (using PKCS#8 format) to a BIO using triple
-DES encryption, using the pass phrase "hello":
-
- if (!PEM_write_bio_PKCS8PrivateKey(bp, key, EVP_des_ede3_cbc(),
- NULL, 0, 0, "hello"))
- /* Error */
-
-Read a private key from a BIO using a pass phrase callback:
-
- key = PEM_read_bio_PrivateKey(bp, NULL, pass_cb, "My Private Key");
- if (key == NULL)
- /* Error */
-
-Skeleton pass phrase callback:
-
- int pass_cb(char *buf, int size, int rwflag, void *u)
- {
-
- /* We'd probably do something else if 'rwflag' is 1 */
- printf("Enter pass phrase for \"%s\"\n", (char *)u);
-
- /* get pass phrase, length 'len' into 'tmp' */
- char *tmp = "hello";
- if (tmp == NULL) /* An error occurred */
- return -1;
-
- size_t len = strlen(tmp);
-
- if (len > size)
- len = size;
- memcpy(buf, tmp, len);
- return len;
- }
-
=head1 NOTES
The old B<PrivateKey> write routines are retained for compatibility.
New applications should write private keys using the
PEM_write_bio_PKCS8PrivateKey() or PEM_write_PKCS8PrivateKey() routines
because they are more secure (they use an iteration count of 2048 whereas
the traditional routines use a count of 1) unless compatibility with older
versions of OpenSSL is important.
The B<PrivateKey> read routines can be used in all applications because
they handle all formats transparently.
A frequent cause of problems is attempting to use the PEM routines like
this:
X509 *x;
PEM_read_bio_X509(bp, &x, 0, NULL);
this is a bug because an attempt will be made to reuse the data at B<x>
which is an uninitialised pointer.
These functions make no assumption regarding the pass phrase received from the
password callback.
It will simply be treated as a byte sequence.
=head1 PEM ENCRYPTION FORMAT
These old B<PrivateKey> routines use a non standard technique for encryption.
The private key (or other data) takes the following form:
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,3F17F5316E2BAC89
...base64 encoded data...
-----END RSA PRIVATE KEY-----
The line beginning with I<Proc-Type> contains the version and the
protection on the encapsulated data. The line beginning I<DEK-Info>
contains two comma separated values: the encryption algorithm name as
used by EVP_get_cipherbyname() and an initialization vector used by the
cipher encoded as a set of hexadecimal digits. After those two lines is
the base64-encoded encrypted data.
The encryption key is derived using EVP_BytesToKey(). The cipher's
initialization vector is passed to EVP_BytesToKey() as the B<salt>
parameter. Internally, B<PKCS5_SALT_LEN> bytes of the salt are used
(regardless of the size of the initialization vector). The user's
password is passed to EVP_BytesToKey() using the B<data> and B<datal>
parameters. Finally, the library uses an iteration count of 1 for
EVP_BytesToKey().
The B<key> derived by EVP_BytesToKey() along with the original initialization
vector is then used to decrypt the encrypted data. The B<iv> produced by
EVP_BytesToKey() is not utilized or needed, and NULL should be passed to
the function.
The pseudo code to derive the key would look similar to:
EVP_CIPHER* cipher = EVP_des_ede3_cbc();
EVP_MD* md = EVP_md5();
unsigned int nkey = EVP_CIPHER_key_length(cipher);
unsigned int niv = EVP_CIPHER_iv_length(cipher);
unsigned char key[nkey];
unsigned char iv[niv];
memcpy(iv, HexToBin("3F17F5316E2BAC89"), niv);
rc = EVP_BytesToKey(cipher, md, iv /*salt*/, pword, plen, 1, key, NULL /*iv*/);
if (rc != nkey)
/* Error */
/* On success, use key and iv to initialize the cipher */
=head1 BUGS
The PEM read routines in some versions of OpenSSL will not correctly reuse
an existing structure. Therefore the following:
PEM_read_bio_X509(bp, &x, 0, NULL);
where B<x> already contains a valid certificate, may not work, whereas:
X509_free(x);
x = PEM_read_bio_X509(bp, NULL, 0, NULL);
is guaranteed to work.
=head1 RETURN VALUES
The read routines return either a pointer to the structure read or NULL
if an error occurred.
The write routines return 1 for success or 0 for failure.
-=head1 HISTORY
+=head1 EXAMPLES
-The old Netscape certificate sequences were no longer documented
-in OpenSSL 1.1.0; applications should use the PKCS7 standard instead
-as they will be formally deprecated in a future releases.
+Although the PEM routines take several arguments in almost all applications
+most of them are set to 0 or NULL.
+
+Read a certificate in PEM format from a BIO:
+
+ X509 *x;
+
+ x = PEM_read_bio_X509(bp, NULL, 0, NULL);
+ if (x == NULL)
+ /* Error */
+
+Alternative method:
+
+ X509 *x = NULL;
+
+ if (!PEM_read_bio_X509(bp, &x, 0, NULL))
+ /* Error */
+
+Write a certificate to a BIO:
+
+ if (!PEM_write_bio_X509(bp, x))
+ /* Error */
+
+Write a private key (using traditional format) to a BIO using
+triple DES encryption, the pass phrase is prompted for:
+
+ if (!PEM_write_bio_PrivateKey(bp, key, EVP_des_ede3_cbc(), NULL, 0, 0, NULL))
+ /* Error */
+
+Write a private key (using PKCS#8 format) to a BIO using triple
+DES encryption, using the pass phrase "hello":
+
+ if (!PEM_write_bio_PKCS8PrivateKey(bp, key, EVP_des_ede3_cbc(),
+ NULL, 0, 0, "hello"))
+ /* Error */
+
+Read a private key from a BIO using a pass phrase callback:
+
+ key = PEM_read_bio_PrivateKey(bp, NULL, pass_cb, "My Private Key");
+ if (key == NULL)
+ /* Error */
+
+Skeleton pass phrase callback:
+
+ int pass_cb(char *buf, int size, int rwflag, void *u)
+ {
+
+ /* We'd probably do something else if 'rwflag' is 1 */
+ printf("Enter pass phrase for \"%s\"\n", (char *)u);
+
+ /* get pass phrase, length 'len' into 'tmp' */
+ char *tmp = "hello";
+ if (tmp == NULL) /* An error occurred */
+ return -1;
+
+ size_t len = strlen(tmp);
+
+ if (len > size)
+ len = size;
+ memcpy(buf, tmp, len);
+ return len;
+ }
=head1 SEE ALSO
L<EVP_EncryptInit(3)>, L<EVP_BytesToKey(3)>,
L<passphrase-encoding(7)>
+=head1 HISTORY
+
+The old Netscape certificate sequences were no longer documented
+in OpenSSL 1.1.0; applications should use the PKCS7 standard instead
+as they will be formally deprecated in a future releases.
+
=head1 COPYRIGHT
-Copyright 2001-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RAND_DRBG_generate.pod b/doc/man3/RAND_DRBG_generate.pod
index b39ee93f5142..bee2d6c176ef 100644
--- a/doc/man3/RAND_DRBG_generate.pod
+++ b/doc/man3/RAND_DRBG_generate.pod
@@ -1,88 +1,88 @@
=pod
=head1 NAME
RAND_DRBG_generate,
RAND_DRBG_bytes
- generate random bytes using the given drbg instance
=head1 SYNOPSIS
#include <openssl/rand_drbg.h>
int RAND_DRBG_generate(RAND_DRBG *drbg,
unsigned char *out, size_t outlen,
int prediction_resistance,
const unsigned char *adin, size_t adinlen);
int RAND_DRBG_bytes(RAND_DRBG *drbg,
unsigned char *out, size_t outlen);
=head1 DESCRIPTION
RAND_DRBG_generate() generates B<outlen> random bytes using the given
DRBG instance B<drbg> and stores them in the buffer at B<out>.
Before generating the output, the DRBG instance checks whether the maximum
number of generate requests (I<reseed interval>) or the maximum timespan
(I<reseed time interval>) since its last seeding have been reached.
If this is the case, the DRBG reseeds automatically.
Additionally, an immediate reseeding can be requested by setting the
B<prediction_resistance> flag to 1. See NOTES section for more details.
The caller can optionally provide additional data to be used for reseeding
by passing a pointer B<adin> to a buffer of length B<adinlen>.
This additional data is mixed into the internal state of the random
generator but does not contribute to the entropy count.
The additional data can be omitted by setting B<adin> to NULL and
B<adinlen> to 0;
RAND_DRBG_bytes() generates B<outlen> random bytes using the given
DRBG instance B<drbg> and stores them in the buffer at B<out>.
This function is a wrapper around the RAND_DRBG_generate() call,
which collects some additional data from low entropy sources
(e.g., a high resolution timer) and calls
RAND_DRBG_generate(drbg, out, outlen, 0, adin, adinlen).
=head1 RETURN VALUES
RAND_DRBG_generate() and RAND_DRBG_bytes() return 1 on success,
and 0 on failure.
=head1 NOTES
The I<reseed interval> and I<reseed time interval> of the B<drbg> are set to
reasonable default values, which in general do not have to be adjusted.
If necessary, they can be changed using L<RAND_DRBG_set_reseed_interval(3)>
and L<RAND_DRBG_set_reseed_time_interval(3)>, respectively.
A request for prediction resistance can only be satisfied by pulling fresh
entropy from one of the approved entropy sources listed in section 5.5.2 of
[NIST SP 800-90C].
Since the default DRBG implementation does not have access to such an approved
entropy source, a request for prediction resistance will always fail.
In other words, prediction resistance is currently not supported yet by the DRBG.
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
=head1 SEE ALSO
L<RAND_bytes(3)>,
L<RAND_DRBG_set_reseed_interval(3)>,
L<RAND_DRBG_set_reseed_time_interval(3)>,
L<RAND_DRBG(7)>
+=head1 HISTORY
+
+The RAND_DRBG functions were added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RAND_DRBG_get0_master.pod b/doc/man3/RAND_DRBG_get0_master.pod
index c958bf20ec0f..55d1eab7c21f 100644
--- a/doc/man3/RAND_DRBG_get0_master.pod
+++ b/doc/man3/RAND_DRBG_get0_master.pod
@@ -1,80 +1,79 @@
=pod
=head1 NAME
RAND_DRBG_get0_master,
RAND_DRBG_get0_public,
RAND_DRBG_get0_private
- get access to the global RAND_DRBG instances
=head1 SYNOPSIS
#include <openssl/rand_drbg.h>
RAND_DRBG *RAND_DRBG_get0_master(void);
RAND_DRBG *RAND_DRBG_get0_public(void);
RAND_DRBG *RAND_DRBG_get0_private(void);
=head1 DESCRIPTION
The default RAND API implementation (RAND_OpenSSL()) utilizes three
shared DRBG instances which are accessed via the RAND API:
The <public> and <private> DRBG are thread-local instances, which are used
by RAND_bytes() and RAND_priv_bytes(), respectively.
The <master> DRBG is a global instance, which is not intended to be used
directly, but is used internally to reseed the other two instances.
These functions here provide access to the shared DRBG instances.
=head1 RETURN VALUES
RAND_DRBG_get0_master() returns a pointer to the <master> DRBG instance.
RAND_DRBG_get0_public() returns a pointer to the <public> DRBG instance.
RAND_DRBG_get0_private() returns a pointer to the <private> DRBG instance.
=head1 NOTES
It is not thread-safe to access the <master> DRBG instance.
The <public> and <private> DRBG instance can be accessed safely, because
they are thread-local. Note however, that changes to these two instances
apply only to the current thread.
For that reason it is recommended not to change the settings of these
three instances directly.
Instead, an application should change the default settings for new DRBG instances
at initialization time, before creating additional threads.
During initialization, it is possible to change the reseed interval
and reseed time interval.
It is also possible to exchange the reseeding callbacks entirely.
-
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
=head1 SEE ALSO
L<RAND_DRBG_set_callbacks(3)>,
L<RAND_DRBG_set_reseed_defaults(3)>,
L<RAND_DRBG_set_reseed_interval(3)>,
L<RAND_DRBG_set_reseed_time_interval(3)>,
L<RAND_DRBG_set_callbacks(3)>,
L<RAND_DRBG_generate(3)>,
L<RAND_DRBG(7)>
+=head1 HISTORY
+
+The RAND_DRBG functions were added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RAND_DRBG_new.pod b/doc/man3/RAND_DRBG_new.pod
index dcd7a944190f..5da91be9dfab 100644
--- a/doc/man3/RAND_DRBG_new.pod
+++ b/doc/man3/RAND_DRBG_new.pod
@@ -1,127 +1,127 @@
=pod
=head1 NAME
RAND_DRBG_new,
RAND_DRBG_secure_new,
RAND_DRBG_set,
RAND_DRBG_set_defaults,
RAND_DRBG_instantiate,
RAND_DRBG_uninstantiate,
RAND_DRBG_free
- initialize and cleanup a RAND_DRBG instance
=head1 SYNOPSIS
#include <openssl/rand_drbg.h>
RAND_DRBG *RAND_DRBG_new(int type,
unsigned int flags,
RAND_DRBG *parent);
RAND_DRBG *RAND_DRBG_secure_new(int type,
unsigned int flags,
RAND_DRBG *parent);
int RAND_DRBG_set(RAND_DRBG *drbg,
int type, unsigned int flags);
int RAND_DRBG_set_defaults(int type, unsigned int flags);
int RAND_DRBG_instantiate(RAND_DRBG *drbg,
const unsigned char *pers, size_t perslen);
int RAND_DRBG_uninstantiate(RAND_DRBG *drbg);
void RAND_DRBG_free(RAND_DRBG *drbg);
=head1 DESCRIPTION
RAND_DRBG_new() and RAND_DRBG_secure_new()
create a new DRBG instance of the given B<type>, allocated from the heap resp.
the secure heap
(using OPENSSL_zalloc() resp. OPENSSL_secure_zalloc()).
RAND_DRBG_set() initializes the B<drbg> with the given B<type> and B<flags>.
RAND_DRBG_set_defaults() sets the default B<type> and B<flags> for new DRBG
instances.
Currently, all DRBG types are based on AES-CTR, so B<type> can be one of the
following values: NID_aes_128_ctr, NID_aes_192_ctr, NID_aes_256_ctr.
Before the DRBG can be used to generate random bits, it is necessary to set
its type and to instantiate it.
The optional B<flags> argument specifies a set of bit flags which can be
joined using the | operator. Currently, the only flag is
RAND_DRBG_FLAG_CTR_NO_DF, which disables the use of a the derivation function
ctr_df. For an explanation, see [NIST SP 800-90A Rev. 1].
If a B<parent> instance is specified then this will be used instead of
the default entropy source for reseeding the B<drbg>. It is said that the
B<drbg> is I<chained> to its B<parent>.
For more information, see the NOTES section.
RAND_DRBG_instantiate()
seeds the B<drbg> instance using random input from trusted entropy sources.
Optionally, a personalization string B<pers> of length B<perslen> can be
specified.
To omit the personalization string, set B<pers>=NULL and B<perslen>=0;
RAND_DRBG_uninstantiate()
clears the internal state of the B<drbg> and puts it back in the
uninstantiated state.
=head1 RETURN VALUES
RAND_DRBG_new() and RAND_DRBG_secure_new() return a pointer to a DRBG
instance allocated on the heap, resp. secure heap.
RAND_DRBG_set(),
RAND_DRBG_instantiate(), and
RAND_DRBG_uninstantiate()
return 1 on success, and 0 on failure.
RAND_DRBG_free() does not return a value.
=head1 NOTES
The DRBG design supports I<chaining>, which means that a DRBG instance can
use another B<parent> DRBG instance instead of the default entropy source
to obtain fresh random input for reseeding, provided that B<parent> DRBG
instance was properly instantiated, either from a trusted entropy source,
or from yet another parent DRBG instance.
For a detailed description of the reseeding process, see L<RAND_DRBG(7)>.
The default DRBG type and flags are applied only during creation of a DRBG
instance.
To ensure that they are applied to the global and thread-local DRBG instances
(<master>, resp. <public> and <private>), it is necessary to call
RAND_DRBG_set_defaults() before creating any thread and before calling any
cryptographic routines that obtain random data directly or indirectly.
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
=head1 SEE ALSO
L<OPENSSL_zalloc(3)>,
L<OPENSSL_secure_zalloc(3)>,
L<RAND_DRBG_generate(3)>,
L<RAND_DRBG(7)>
+=head1 HISTORY
+
+The RAND_DRBG functions were added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RAND_DRBG_reseed.pod b/doc/man3/RAND_DRBG_reseed.pod
index da3a40be4424..3610c1301e09 100644
--- a/doc/man3/RAND_DRBG_reseed.pod
+++ b/doc/man3/RAND_DRBG_reseed.pod
@@ -1,111 +1,116 @@
=pod
=head1 NAME
RAND_DRBG_reseed,
RAND_DRBG_set_reseed_interval,
RAND_DRBG_set_reseed_time_interval,
RAND_DRBG_set_reseed_defaults
- reseed a RAND_DRBG instance
=head1 SYNOPSIS
#include <openssl/rand_drbg.h>
int RAND_DRBG_reseed(RAND_DRBG *drbg,
- const unsigned char *adin, size_t adinlen);
+ const unsigned char *adin, size_t adinlen,
+ int prediction_resistance);
int RAND_DRBG_set_reseed_interval(RAND_DRBG *drbg,
unsigned int interval);
int RAND_DRBG_set_reseed_time_interval(RAND_DRBG *drbg,
time_t interval);
int RAND_DRBG_set_reseed_defaults(
unsigned int master_reseed_interval,
unsigned int slave_reseed_interval,
time_t master_reseed_time_interval,
time_t slave_reseed_time_interval
);
=head1 DESCRIPTION
RAND_DRBG_reseed()
reseeds the given B<drbg>, obtaining entropy input from its entropy source
and mixing in the specified additional data provided in the buffer B<adin>
of length B<adinlen>.
The additional data can be omitted by setting B<adin> to NULL and B<adinlen>
to 0.
+An immediate reseeding from a live entropy source can be requested by setting
+the B<prediction_resistance> flag to 1.
+This feature is not implemented yet, so reseeding with prediction resistance
+requested will always fail.
RAND_DRBG_set_reseed_interval()
sets the reseed interval of the B<drbg>, which is the maximum allowed number
of generate requests between consecutive reseedings.
If B<interval> > 0, then the B<drbg> will reseed automatically whenever the
number of generate requests since its last seeding exceeds the given reseed
interval.
If B<interval> == 0, then this feature is disabled.
RAND_DRBG_set_reseed_time_interval()
sets the reseed time interval of the B<drbg>, which is the maximum allowed
number of seconds between consecutive reseedings.
If B<interval> > 0, then the B<drbg> will reseed automatically whenever the
elapsed time since its last reseeding exceeds the given reseed time interval.
If B<interval> == 0, then this feature is disabled.
RAND_DRBG_set_reseed_defaults() sets the default values for the reseed interval
(B<master_reseed_interval> and B<slave_reseed_interval>)
and the reseed time interval
(B<master_reseed_time_interval> and B<slave_reseed_tme_interval>)
of DRBG instances.
The default values are set independently for master DRBG instances (which don't
have a parent) and slave DRBG instances (which are chained to a parent DRBG).
=head1 RETURN VALUES
RAND_DRBG_reseed(),
RAND_DRBG_set_reseed_interval(), and
RAND_DRBG_set_reseed_time_interval(),
return 1 on success, 0 on failure.
=head1 NOTES
The default OpenSSL random generator is already set up for automatic reseeding,
so in general it is not necessary to reseed it explicitly, or to modify
its reseeding thresholds.
Normally, the entropy input for seeding a DRBG is either obtained from a
trusted os entropy source or from a parent DRBG instance, which was seeded
(directly or indirectly) from a trusted os entropy source.
In exceptional cases it is possible to replace the reseeding mechanism entirely
by providing application defined callbacks using RAND_DRBG_set_callbacks().
The reseeding default values are applied only during creation of a DRBG instance.
To ensure that they are applied to the global and thread-local DRBG instances
(<master>, resp. <public> and <private>), it is necessary to call
RAND_DRBG_set_reseed_defaults() before creating any thread and before calling any
cryptographic routines that obtain random data directly or indirectly.
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
=head1 SEE ALSO
L<RAND_DRBG_generate(3)>,
L<RAND_DRBG_bytes(3)>,
L<RAND_DRBG_set_callbacks(3)>.
L<RAND_DRBG(7)>
+=head1 HISTORY
+
+The RAND_DRBG functions were added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RAND_DRBG_set_callbacks.pod b/doc/man3/RAND_DRBG_set_callbacks.pod
index a927d6a7dacc..3da051e696aa 100644
--- a/doc/man3/RAND_DRBG_set_callbacks.pod
+++ b/doc/man3/RAND_DRBG_set_callbacks.pod
@@ -1,147 +1,146 @@
=pod
=head1 NAME
RAND_DRBG_set_callbacks,
RAND_DRBG_get_entropy_fn,
RAND_DRBG_cleanup_entropy_fn,
RAND_DRBG_get_nonce_fn,
RAND_DRBG_cleanup_nonce_fn
- set callbacks for reseeding
=head1 SYNOPSIS
#include <openssl/rand_drbg.h>
int RAND_DRBG_set_callbacks(RAND_DRBG *drbg,
RAND_DRBG_get_entropy_fn get_entropy,
RAND_DRBG_cleanup_entropy_fn cleanup_entropy,
RAND_DRBG_get_nonce_fn get_nonce,
RAND_DRBG_cleanup_nonce_fn cleanup_nonce);
=head2 Callback Functions
typedef size_t (*RAND_DRBG_get_entropy_fn)(
RAND_DRBG *drbg,
unsigned char **pout,
int entropy,
size_t min_len, size_t max_len,
int prediction_resistance);
typedef void (*RAND_DRBG_cleanup_entropy_fn)(
RAND_DRBG *drbg,
unsigned char *out, size_t outlen);
typedef size_t (*RAND_DRBG_get_nonce_fn)(
RAND_DRBG *drbg,
unsigned char **pout,
int entropy,
size_t min_len, size_t max_len);
typedef void (*RAND_DRBG_cleanup_nonce_fn)(
RAND_DRBG *drbg,
unsigned char *out, size_t outlen);
=head1 DESCRIPTION
RAND_DRBG_set_callbacks() sets the callbacks for obtaining fresh entropy and
the nonce when reseeding the given B<drbg>.
The callback functions are implemented and provided by the caller.
Their parameter lists need to match the function prototypes above.
Setting the callbacks is allowed only if the DRBG has not been initialized yet.
Otherwise, the operation will fail.
To change the settings for one of the three shared DRBGs it is necessary to call
RAND_DRBG_uninstantiate() first.
The B<get_entropy>() callback is called by the B<drbg> when it requests fresh
random input.
It is expected that the callback allocates and fills a random buffer of size
B<min_len> <= size <= B<max_len> (in bytes) which contains at least B<entropy>
bits of randomness.
The B<prediction_resistance> flag indicates whether the reseeding was
triggered by a prediction resistance request.
The buffer's address is to be returned in *B<pout> and the number of collected
randomness bytes as return value.
If the callback fails to acquire at least B<entropy> bits of randomness,
it must indicate an error by returning a buffer length of 0.
If B<prediction_resistance> was requested and the random source of the DRBG
does not satisfy the conditions requested by [NIST SP 800-90C], then
it must also indicate an error by returning a buffer length of 0.
See NOTES section for more details.
The B<cleanup_entropy>() callback is called from the B<drbg> to to clear and
free the buffer allocated previously by get_entropy().
The values B<out> and B<outlen> are the random buffer's address and length,
as returned by the get_entropy() callback.
The B<get_nonce>() and B<cleanup_nonce>() callbacks are used to obtain a nonce
and free it again. A nonce is only required for instantiation (not for reseeding)
and only in the case where the DRBG uses a derivation function.
The callbacks are analogous to get_entropy() and cleanup_entropy(),
except for the missing prediction_resistance flag.
If the derivation function is disabled, then no nonce is used for instantiation,
and the B<get_nonce>() and B<cleanup_nonce>() callbacks can be omitted by
setting them to NULL.
=head1 RETURN VALUES
RAND_DRBG_set_callbacks() return 1 on success, and 0 on failure
=head1 NOTES
It is important that B<cleanup_entropy>() and B<cleanup_nonce>() clear the buffer
contents safely before freeing it, in order not to leave sensitive information
about the DRBG's state in memory.
A request for prediction resistance can only be satisfied by pulling fresh
entropy from one of the approved entropy sources listed in section 5.5.2 of
[NIST SP 800-90C].
Since the default implementation of the get_entropy callback does not have access
to such an approved entropy source, a request for prediction resistance will
always fail.
In other words, prediction resistance is currently not supported yet by the DRBG.
The derivation function is disabled during initialization by calling the
RAND_DRBG_set() function with the RAND_DRBG_FLAG_CTR_NO_DF flag.
For more information on the derivation function and when it can be omitted,
see [NIST SP 800-90A Rev. 1]. Roughly speeking it can be omitted if the random
source has "full entropy", i.e., contains 8 bits of entropy per byte.
Even if a nonce is required, the B<get_nonce>() and B<cleanup_nonce>()
callbacks can be omitted by setting them to NULL.
In this case the DRBG will automatically request an extra amount of entropy
(using the B<get_entropy>() and B<cleanup_entropy>() callbacks) which it will
utilize for the nonce, following the recommendations of [NIST SP 800-90A Rev. 1],
section 8.6.7.
-
-=head1 HISTORY
-
-The RAND_DRBG functions were added in OpenSSL 1.1.1.
-
=head1 SEE ALSO
L<RAND_DRBG_new(3)>,
L<RAND_DRBG_reseed(3)>,
L<RAND_DRBG(7)>
+=head1 HISTORY
+
+The RAND_DRBG functions were added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2017-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RAND_add.pod b/doc/man3/RAND_add.pod
index b6753fd2ed0b..4ba6ff977dd1 100644
--- a/doc/man3/RAND_add.pod
+++ b/doc/man3/RAND_add.pod
@@ -1,104 +1,104 @@
=pod
=head1 NAME
RAND_add, RAND_poll, RAND_seed, RAND_status, RAND_event, RAND_screen,
RAND_keep_random_devices_open
- add randomness to the PRNG or get its status
=head1 SYNOPSIS
#include <openssl/rand.h>
int RAND_status(void);
int RAND_poll();
void RAND_add(const void *buf, int num, double randomness);
void RAND_seed(const void *buf, int num);
void RAND_keep_random_devices_open(int keep);
Deprecated:
#if OPENSSL_API_COMPAT < 0x10100000L
int RAND_event(UINT iMsg, WPARAM wParam, LPARAM lParam);
void RAND_screen(void);
#endif
=head1 DESCRIPTION
These functions can be used to seed the random generator and to check its
seeded state.
In general, manual (re-)seeding of the default OpenSSL random generator
(L<RAND_OpenSSL(3)>) is not necessary (but allowed), since it does (re-)seed
itself automatically using trusted system entropy sources.
This holds unless the default RAND_METHOD has been replaced or OpenSSL was
built with automatic reseeding disabled, see L<RAND(7)> for more details.
RAND_status() indicates whether or not the random generator has been sufficiently
seeded. If not, functions such as L<RAND_bytes(3)> will fail.
RAND_poll() uses the system's capabilities to seed the random generator using
random input obtained from polling various trusted entropy sources.
The default choice of the entropy source can be modified at build time,
see L<RAND(7)> for more details.
RAND_add() mixes the B<num> bytes at B<buf> into the internal state
of the random generator.
This function will not normally be needed, as mentioned above.
The B<randomness> argument is an estimate of how much randomness is
contained in
B<buf>, in bytes, and should be a number between zero and B<num>.
Details about sources of randomness and how to estimate their randomness
can be found in the literature; for example [NIST SP 800-90B].
The content of B<buf> cannot be recovered from subsequent random generator output.
Applications that intend to save and restore random state in an external file
should consider using L<RAND_load_file(3)> instead.
RAND_seed() is equivalent to RAND_add() with B<randomness> set to B<num>.
RAND_keep_random_devices_open() is used to control file descriptor
usage by the random seed sources. Some seed sources maintain open file
descriptors by default, which allows such sources to operate in a
chroot(2) jail without the associated device nodes being available. When
the B<keep> argument is zero, this call disables the retention of file
descriptors. Conversely, a non-zero argument enables the retention of
file descriptors. This function is usually called during initialization
and it takes effect immediately.
RAND_event() and RAND_screen() are equivalent to RAND_poll() and exist
for compatibility reasons only. See HISTORY section below.
=head1 RETURN VALUES
RAND_status() returns 1 if the random generator has been seeded
with enough data, 0 otherwise.
RAND_poll() returns 1 if it generated seed data, 0 otherwise.
RAND_event() returns RAND_status().
The other functions do not return values.
-=head1 HISTORY
-
-RAND_event() and RAND_screen() were deprecated in OpenSSL 1.1.0 and should
-not be used.
-
=head1 SEE ALSO
L<RAND_bytes(3)>,
L<RAND_egd(3)>,
L<RAND_load_file(3)>,
L<RAND(7)>
+=head1 HISTORY
+
+RAND_event() and RAND_screen() were deprecated in OpenSSL 1.1.0 and should
+not be used.
+
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RAND_bytes.pod b/doc/man3/RAND_bytes.pod
index f257e050065f..e2265d170a61 100644
--- a/doc/man3/RAND_bytes.pod
+++ b/doc/man3/RAND_bytes.pod
@@ -1,78 +1,78 @@
=pod
=head1 NAME
RAND_bytes, RAND_priv_bytes, RAND_pseudo_bytes - generate random data
=head1 SYNOPSIS
#include <openssl/rand.h>
int RAND_bytes(unsigned char *buf, int num);
int RAND_priv_bytes(unsigned char *buf, int num);
Deprecated:
#if OPENSSL_API_COMPAT < 0x10100000L
int RAND_pseudo_bytes(unsigned char *buf, int num);
#endif
=head1 DESCRIPTION
RAND_bytes() puts B<num> cryptographically strong pseudo-random bytes
into B<buf>.
RAND_priv_bytes() has the same semantics as RAND_bytes(). It is intended to
be used for generating values that should remain private. If using the
default RAND_METHOD, this function uses a separate "private" PRNG
instance so that a compromise of the "public" PRNG instance will not
affect the secrecy of these private values, as described in L<RAND(7)>
and L<RAND_DRBG(7)>.
=head1 NOTES
Always check the error return value of RAND_bytes() and
RAND_priv_bytes() and do not take randomness for granted: an error occurs
if the CSPRNG has not been seeded with enough randomness to ensure an
unpredictable byte sequence.
=head1 RETURN VALUES
RAND_bytes() and RAND_priv_bytes()
return 1 on success, -1 if not supported by the current
RAND method, or 0 on other failure. The error code can be
obtained by L<ERR_get_error(3)>.
+=head1 SEE ALSO
+
+L<RAND_add(3)>,
+L<RAND_bytes(3)>,
+L<RAND_priv_bytes(3)>,
+L<ERR_get_error(3)>,
+L<RAND(7)>,
+L<RAND_DRBG(7)>
+
=head1 HISTORY
=over 2
=item *
RAND_pseudo_bytes() was deprecated in OpenSSL 1.1.0; use RAND_bytes() instead.
=item *
The RAND_priv_bytes() function was added in OpenSSL 1.1.1.
=back
-=head1 SEE ALSO
-
-L<RAND_add(3)>,
-L<RAND_bytes(3)>,
-L<RAND_priv_bytes(3)>,
-L<ERR_get_error(3)>,
-L<RAND(7)>,
-L<RAND_DRBG(7)>
-
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RAND_cleanup.pod b/doc/man3/RAND_cleanup.pod
index 3859ce343aa8..e5187532222d 100644
--- a/doc/man3/RAND_cleanup.pod
+++ b/doc/man3/RAND_cleanup.pod
@@ -1,44 +1,44 @@
=pod
=head1 NAME
RAND_cleanup - erase the PRNG state
=head1 SYNOPSIS
#include <openssl/rand.h>
#if OPENSSL_API_COMPAT < 0x10100000L
void RAND_cleanup(void)
#endif
=head1 DESCRIPTION
Prior to OpenSSL 1.1.0, RAND_cleanup() released all resources used by
the PRNG. As of version 1.1.0, it does nothing and should not be called,
since no explicit initialisation or de-initialisation is necessary. See
L<OPENSSL_init_crypto(3)>.
=head1 RETURN VALUES
RAND_cleanup() returns no value.
+=head1 SEE ALSO
+
+L<RAND(7)>
+
=head1 HISTORY
RAND_cleanup() was deprecated in OpenSSL 1.1.0; do not use it.
See L<OPENSSL_init_crypto(3)>
-=head1 SEE ALSO
-
-L<RAND(7)>
-
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RSA_padding_add_PKCS1_type_1.pod b/doc/man3/RSA_padding_add_PKCS1_type_1.pod
index 9ea2634c0346..20926003d876 100644
--- a/doc/man3/RSA_padding_add_PKCS1_type_1.pod
+++ b/doc/man3/RSA_padding_add_PKCS1_type_1.pod
@@ -1,135 +1,157 @@
=pod
=head1 NAME
RSA_padding_add_PKCS1_type_1, RSA_padding_check_PKCS1_type_1,
RSA_padding_add_PKCS1_type_2, RSA_padding_check_PKCS1_type_2,
RSA_padding_add_PKCS1_OAEP, RSA_padding_check_PKCS1_OAEP,
+RSA_padding_add_PKCS1_OAEP_mgf1, RSA_padding_check_PKCS1_OAEP_mgf1,
RSA_padding_add_SSLv23, RSA_padding_check_SSLv23,
RSA_padding_add_none, RSA_padding_check_none - asymmetric encryption
padding
=head1 SYNOPSIS
#include <openssl/rsa.h>
int RSA_padding_add_PKCS1_type_1(unsigned char *to, int tlen,
- unsigned char *f, int fl);
+ const unsigned char *f, int fl);
int RSA_padding_check_PKCS1_type_1(unsigned char *to, int tlen,
- unsigned char *f, int fl, int rsa_len);
+ const unsigned char *f, int fl, int rsa_len);
int RSA_padding_add_PKCS1_type_2(unsigned char *to, int tlen,
- unsigned char *f, int fl);
+ const unsigned char *f, int fl);
int RSA_padding_check_PKCS1_type_2(unsigned char *to, int tlen,
- unsigned char *f, int fl, int rsa_len);
+ const unsigned char *f, int fl, int rsa_len);
int RSA_padding_add_PKCS1_OAEP(unsigned char *to, int tlen,
- unsigned char *f, int fl, unsigned char *p, int pl);
+ const unsigned char *f, int fl,
+ const unsigned char *p, int pl);
int RSA_padding_check_PKCS1_OAEP(unsigned char *to, int tlen,
- unsigned char *f, int fl, int rsa_len,
- unsigned char *p, int pl);
+ const unsigned char *f, int fl, int rsa_len,
+ const unsigned char *p, int pl);
+
+ int RSA_padding_add_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
+ const unsigned char *f, int fl,
+ const unsigned char *p, int pl,
+ const EVP_MD *md, const EVP_MD *mgf1md);
+
+ int RSA_padding_check_PKCS1_OAEP_mgf1(unsigned char *to, int tlen,
+ const unsigned char *f, int fl, int rsa_len,
+ const unsigned char *p, int pl,
+ const EVP_MD *md, const EVP_MD *mgf1md);
int RSA_padding_add_SSLv23(unsigned char *to, int tlen,
- unsigned char *f, int fl);
+ const unsigned char *f, int fl);
int RSA_padding_check_SSLv23(unsigned char *to, int tlen,
- unsigned char *f, int fl, int rsa_len);
+ const unsigned char *f, int fl, int rsa_len);
int RSA_padding_add_none(unsigned char *to, int tlen,
- unsigned char *f, int fl);
+ const unsigned char *f, int fl);
int RSA_padding_check_none(unsigned char *to, int tlen,
- unsigned char *f, int fl, int rsa_len);
+ const unsigned char *f, int fl, int rsa_len);
=head1 DESCRIPTION
The RSA_padding_xxx_xxx() functions are called from the RSA encrypt,
decrypt, sign and verify functions. Normally they should not be called
from application programs.
However, they can also be called directly to implement padding for other
asymmetric ciphers. RSA_padding_add_PKCS1_OAEP() and
RSA_padding_check_PKCS1_OAEP() may be used in an application combined
with B<RSA_NO_PADDING> in order to implement OAEP with an encoding
parameter.
RSA_padding_add_xxx() encodes B<fl> bytes from B<f> so as to fit into
B<tlen> bytes and stores the result at B<to>. An error occurs if B<fl>
does not meet the size requirements of the encoding method.
The following encoding methods are implemented:
=over 4
=item PKCS1_type_1
PKCS #1 v2.0 EMSA-PKCS1-v1_5 (PKCS #1 v1.5 block type 1); used for signatures
=item PKCS1_type_2
PKCS #1 v2.0 EME-PKCS1-v1_5 (PKCS #1 v1.5 block type 2)
=item PKCS1_OAEP
PKCS #1 v2.0 EME-OAEP
=item SSLv23
PKCS #1 EME-PKCS1-v1_5 with SSL-specific modification
=item none
simply copy the data
=back
The random number generator must be seeded prior to calling
RSA_padding_add_xxx().
RSA_padding_check_xxx() verifies that the B<fl> bytes at B<f> contain
a valid encoding for a B<rsa_len> byte RSA key in the respective
encoding method and stores the recovered data of at most B<tlen> bytes
(for B<RSA_NO_PADDING>: of size B<tlen>)
at B<to>.
For RSA_padding_xxx_OAEP(), B<p> points to the encoding parameter
of length B<pl>. B<p> may be B<NULL> if B<pl> is 0.
+For RSA_padding_xxx_OAEP_mgf1(), B<md> points to the md hash,
+if B<md> is B<NULL> that means md=sha1, and B<mgf1md> points to
+the mgf1 hash, if B<mgf1md> is B<NULL> that means mgf1md=md.
+
=head1 RETURN VALUES
The RSA_padding_add_xxx() functions return 1 on success, 0 on error.
The RSA_padding_check_xxx() functions return the length of the
recovered data, -1 on error. Error codes can be obtained by calling
L<ERR_get_error(3)>.
=head1 WARNING
-The RSA_padding_check_PKCS1_type_2() padding check leaks timing
+The result of RSA_padding_check_PKCS1_type_2() is a very sensitive
information which can potentially be used to mount a Bleichenbacher
padding oracle attack. This is an inherent weakness in the PKCS #1
-v1.5 padding design. Prefer PKCS1_OAEP padding. Otherwise it can
-be recommended to pass zero-padded B<f>, so that B<fl> equals to
-B<rsa_len>, and if fixed by protocol, B<tlen> being set to the
-expected length. In such case leakage would be minimal, it would
-take attacker's ability to observe memory access pattern with byte
-granilarity as it occurs, post-factum timing analysis won't do.
+v1.5 padding design. Prefer PKCS1_OAEP padding. If that is not
+possible, the result of RSA_padding_check_PKCS1_type_2() should be
+checked in constant time if it matches the expected length of the
+plaintext and additionally some application specific consistency
+checks on the plaintext need to be performed in constant time.
+If the plaintext is rejected it must be kept secret which of the
+checks caused the application to reject the message.
+Do not remove the zero-padding from the decrypted raw RSA data
+which was computed by RSA_private_decrypt() with B<RSA_NO_PADDING>,
+as this would create a small timing side channel which could be
+used to mount a Bleichenbacher attack against any padding mode
+including PKCS1_OAEP.
=head1 SEE ALSO
L<RSA_public_encrypt(3)>,
L<RSA_private_decrypt(3)>,
L<RSA_sign(3)>, L<RSA_verify(3)>
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/RSA_public_encrypt.pod b/doc/man3/RSA_public_encrypt.pod
index 91c176e24c52..d91c6884b1d5 100644
--- a/doc/man3/RSA_public_encrypt.pod
+++ b/doc/man3/RSA_public_encrypt.pod
@@ -1,95 +1,109 @@
=pod
=head1 NAME
RSA_public_encrypt, RSA_private_decrypt - RSA public key cryptography
=head1 SYNOPSIS
#include <openssl/rsa.h>
- int RSA_public_encrypt(int flen, unsigned char *from,
+ int RSA_public_encrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
- int RSA_private_decrypt(int flen, unsigned char *from,
+ int RSA_private_decrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding);
=head1 DESCRIPTION
RSA_public_encrypt() encrypts the B<flen> bytes at B<from> (usually a
session key) using the public key B<rsa> and stores the ciphertext in
B<to>. B<to> must point to RSA_size(B<rsa>) bytes of memory.
B<padding> denotes one of the following modes:
=over 4
=item RSA_PKCS1_PADDING
PKCS #1 v1.5 padding. This currently is the most widely used mode.
+However, it is highly recommended to use RSA_PKCS1_OAEP_PADDING in
+new applications. SEE WARNING BELOW.
=item RSA_PKCS1_OAEP_PADDING
EME-OAEP as defined in PKCS #1 v2.0 with SHA-1, MGF1 and an empty
encoding parameter. This mode is recommended for all new applications.
=item RSA_SSLV23_PADDING
PKCS #1 v1.5 padding with an SSL-specific modification that denotes
that the server is SSL3 capable.
=item RSA_NO_PADDING
Raw RSA encryption. This mode should I<only> be used to implement
cryptographically sound padding modes in the application code.
Encrypting user data directly with RSA is insecure.
=back
-B<flen> must be less than RSA_size(B<rsa>) - 11 for the PKCS #1 v1.5
-based padding modes, less than RSA_size(B<rsa>) - 41 for
+B<flen> must not be more than RSA_size(B<rsa>) - 11 for the PKCS #1 v1.5
+based padding modes, not more than RSA_size(B<rsa>) - 42 for
RSA_PKCS1_OAEP_PADDING and exactly RSA_size(B<rsa>) for RSA_NO_PADDING.
-The random number generator must be seeded prior to calling
-RSA_public_encrypt().
+When a padding mode other than RSA_NO_PADDING is in use, then
+RSA_public_encrypt() will include some random bytes into the ciphertext
+and therefore the ciphertext will be different each time, even if the
+plaintext and the public key are exactly identical.
+The returned ciphertext in B<to> will always be zero padded to exactly
+RSA_size(B<rsa>) bytes.
+B<to> and B<from> may overlap.
RSA_private_decrypt() decrypts the B<flen> bytes at B<from> using the
-private key B<rsa> and stores the plaintext in B<to>. B<to> must point
-to a memory section large enough to hold the decrypted data (which is
-smaller than RSA_size(B<rsa>)). B<padding> is the padding mode that
-was used to encrypt the data.
+private key B<rsa> and stores the plaintext in B<to>. B<flen> should
+be equal to RSA_size(B<rsa>) but may be smaller, when leading zero
+bytes are in the ciphertext. Those are not important and may be removed,
+but RSA_public_encrypt() does not do that. B<to> must point
+to a memory section large enough to hold the maximal possible decrypted
+data (which is equal to RSA_size(B<rsa>) for RSA_NO_PADDING,
+RSA_size(B<rsa>) - 11 for the PKCS #1 v1.5 based padding modes and
+RSA_size(B<rsa>) - 42 for RSA_PKCS1_OAEP_PADDING).
+B<padding> is the padding mode that was used to encrypt the data.
+B<to> and B<from> may overlap.
=head1 RETURN VALUES
RSA_public_encrypt() returns the size of the encrypted data (i.e.,
RSA_size(B<rsa>)). RSA_private_decrypt() returns the size of the
-recovered plaintext.
+recovered plaintext. A return value of 0 is not an error and
+means only that the plaintext was empty.
On error, -1 is returned; the error codes can be
obtained by L<ERR_get_error(3)>.
=head1 WARNING
Decryption failures in the RSA_PKCS1_PADDING mode leak information
which can potentially be used to mount a Bleichenbacher padding oracle
attack. This is an inherent weakness in the PKCS #1 v1.5 padding
design. Prefer RSA_PKCS1_OAEP_PADDING.
=head1 CONFORMING TO
SSL, PKCS #1 v2.0
=head1 SEE ALSO
L<ERR_get_error(3)>, L<RAND_bytes(3)>,
L<RSA_size(3)>
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CIPHER_get_name.pod b/doc/man3/SSL_CIPHER_get_name.pod
index 4c12c5ed20d0..26edae3d80be 100644
--- a/doc/man3/SSL_CIPHER_get_name.pod
+++ b/doc/man3/SSL_CIPHER_get_name.pod
@@ -1,210 +1,213 @@
=pod
=head1 NAME
SSL_CIPHER_get_name,
SSL_CIPHER_standard_name,
OPENSSL_cipher_name,
SSL_CIPHER_get_bits,
SSL_CIPHER_get_version,
SSL_CIPHER_description,
SSL_CIPHER_get_cipher_nid,
SSL_CIPHER_get_digest_nid,
SSL_CIPHER_get_handshake_digest,
SSL_CIPHER_get_kx_nid,
SSL_CIPHER_get_auth_nid,
SSL_CIPHER_is_aead,
SSL_CIPHER_find,
SSL_CIPHER_get_id,
SSL_CIPHER_get_protocol_id
- get SSL_CIPHER properties
=head1 SYNOPSIS
#include <openssl/ssl.h>
const char *SSL_CIPHER_get_name(const SSL_CIPHER *cipher);
const char *SSL_CIPHER_standard_name(const SSL_CIPHER *cipher);
const char *OPENSSL_cipher_name(const char *stdname);
int SSL_CIPHER_get_bits(const SSL_CIPHER *cipher, int *alg_bits);
char *SSL_CIPHER_get_version(const SSL_CIPHER *cipher);
char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int size);
int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c);
int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c);
const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c);
int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c);
int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c);
int SSL_CIPHER_is_aead(const SSL_CIPHER *c);
const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
uint32_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
=head1 DESCRIPTION
SSL_CIPHER_get_name() returns a pointer to the name of B<cipher>. If the
B<cipher> is NULL, it returns "(NONE)".
SSL_CIPHER_standard_name() returns a pointer to the standard RFC name of
B<cipher>. If the B<cipher> is NULL, it returns "(NONE)". If the B<cipher>
has no standard name, it returns B<NULL>. If B<cipher> was defined in both
SSLv3 and TLS, it returns the TLS name.
OPENSSL_cipher_name() returns a pointer to the OpenSSL name of B<stdname>.
If the B<stdname> is NULL, or B<stdname> has no corresponding OpenSSL name,
it returns "(NONE)". Where both exist, B<stdname> should be the TLS name rather
than the SSLv3 name.
SSL_CIPHER_get_bits() returns the number of secret bits used for B<cipher>.
If B<cipher> is NULL, 0 is returned.
SSL_CIPHER_get_version() returns string which indicates the SSL/TLS protocol
version that first defined the cipher. It returns "(NONE)" if B<cipher> is NULL.
SSL_CIPHER_get_cipher_nid() returns the cipher NID corresponding to B<c>.
If there is no cipher (e.g. for cipher suites with no encryption) then
B<NID_undef> is returned.
SSL_CIPHER_get_digest_nid() returns the digest NID corresponding to the MAC
used by B<c> during record encryption/decryption. If there is no digest (e.g.
for AEAD cipher suites) then B<NID_undef> is returned.
SSL_CIPHER_get_handshake_digest() returns an EVP_MD for the digest used during
the SSL/TLS handshake when using the SSL_CIPHER B<c>. Note that this may be
different to the digest used to calculate the MAC for encrypted records.
SSL_CIPHER_get_kx_nid() returns the key exchange NID corresponding to the method
used by B<c>. If there is no key exchange, then B<NID_undef> is returned.
If any appropriate key exchange algorithm can be used (as in the case of TLS 1.3
cipher suites) B<NID_kx_any> is returned. Examples (not comprehensive):
NID_kx_rsa
NID_kx_ecdhe
NID_kx_dhe
NID_kx_psk
SSL_CIPHER_get_auth_nid() returns the authentication NID corresponding to the method
used by B<c>. If there is no authentication, then B<NID_undef> is returned.
If any appropriate authentication algorithm can be used (as in the case of
TLS 1.3 cipher suites) B<NID_auth_any> is returned. Examples (not comprehensive):
NID_auth_rsa
NID_auth_ecdsa
NID_auth_psk
SSL_CIPHER_is_aead() returns 1 if the cipher B<c> is AEAD (e.g. GCM or
ChaCha20/Poly1305), and 0 if it is not AEAD.
SSL_CIPHER_find() returns a B<SSL_CIPHER> structure which has the cipher ID stored
in B<ptr>. The B<ptr> parameter is a two element array of B<char>, which stores the
two-byte TLS cipher ID (as allocated by IANA) in network byte order. This parameter
is usually retrieved from a TLS packet by using functions like
L<SSL_client_hello_get0_ciphers(3)>. SSL_CIPHER_find() returns NULL if an
error occurs or the indicated cipher is not found.
SSL_CIPHER_get_id() returns the OpenSSL-specific ID of the given cipher B<c>. That ID is
not the same as the IANA-specific ID.
SSL_CIPHER_get_protocol_id() returns the two-byte ID used in the TLS protocol of the given
cipher B<c>.
SSL_CIPHER_description() returns a textual description of the cipher used
into the buffer B<buf> of length B<len> provided. If B<buf> is provided, it
must be at least 128 bytes, otherwise a buffer will be allocated using
OPENSSL_malloc(). If the provided buffer is too small, or the allocation fails,
B<NULL> is returned.
The string returned by SSL_CIPHER_description() consists of several fields
separated by whitespace:
=over 4
=item <ciphername>
Textual representation of the cipher name.
=item <protocol version>
-Protocol version, such as B<TLSv1.2>, when the cipher was first defined.
+The minimum protocol version that the ciphersuite supports, such as B<TLSv1.2>.
+Note that this is not always the same as the protocol version in which the
+ciphersuite was first defined because some ciphersuites are backwards compatible
+with earlier protocol versions.
=item Kx=<key exchange>
Key exchange method such as B<RSA>, B<ECDHE>, etc.
=item Au=<authentication>
Authentication method such as B<RSA>, B<None>, etc.. None is the
representation of anonymous ciphers.
=item Enc=<symmetric encryption method>
Encryption method, with number of secret bits, such as B<AESGCM(128)>.
=item Mac=<message authentication code>
Message digest, such as B<SHA256>.
=back
Some examples for the output of SSL_CIPHER_description():
ECDHE-RSA-AES256-GCM-SHA256 TLSv1.2 Kx=ECDH Au=RSA Enc=AESGCM(256) Mac=AEAD
RSA-PSK-AES256-CBC-SHA384 TLSv1.0 Kx=RSAPSK Au=RSA Enc=AES(256) Mac=SHA384
=head1 RETURN VALUES
SSL_CIPHER_get_name(), SSL_CIPHER_standard_name(), OPENSSL_cipher_name(),
SSL_CIPHER_get_version() and SSL_CIPHER_description() return the corresponding
value in a null-terminated string for a specific cipher or "(NONE)"
if the cipher is not found.
SSL_CIPHER_get_bits() returns a positive integer representing the number of
secret bits or 0 if an error occurred.
SSL_CIPHER_get_cipher_nid(), SSL_CIPHER_get_digest_nid(),
SSL_CIPHER_get_kx_nid() and SSL_CIPHER_get_auth_nid() return the NID value or
B<NID_undef> if an error occurred.
SSL_CIPHER_get_handshake_digest() returns a valid B<EVP_MD> structure or NULL
if an error occurred.
SSL_CIPHER_is_aead() returns 1 if the cipher is AEAD or 0 otherwise.
SSL_CIPHER_find() returns a valid B<SSL_CIPHER> structure or NULL if an error
occurred.
SSL_CIPHER_get_id() returns a 4-byte integer representing the OpenSSL-specific ID.
SSL_CIPHER_get_protocol_id() returns a 2-byte integer representing the TLS
protocol-specific ID.
+=head1 SEE ALSO
+
+L<ssl(7)>, L<SSL_get_current_cipher(3)>,
+L<SSL_get_ciphers(3)>, L<ciphers(1)>
+
=head1 HISTORY
The SSL_CIPHER_get_version() function was updated to always return the
correct protocol string in OpenSSL 1.1.0.
The SSL_CIPHER_description() function was changed to return B<NULL> on error,
rather than a fixed string, in OpenSSL 1.1.0.
The SSL_CIPHER_get_handshake_digest() function was added in OpenSSL 1.1.1.
The SSL_CIPHER_standard_name() function was globally available in OpenSSL 1.1.1.
Before OpenSSL 1.1.1, tracing (B<enable-ssl-trace> argument to Configure) was
required to enable this function.
The OPENSSL_cipher_name() function was added in OpenSSL 1.1.1.
-=head1 SEE ALSO
-
-L<ssl(7)>, L<SSL_get_current_cipher(3)>,
-L<SSL_get_ciphers(3)>, L<ciphers(1)>
-
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CONF_cmd.pod b/doc/man3/SSL_CONF_cmd.pod
index a74e7284f9de..7f2449e379b9 100644
--- a/doc/man3/SSL_CONF_cmd.pod
+++ b/doc/man3/SSL_CONF_cmd.pod
@@ -1,693 +1,693 @@
=pod
=head1 NAME
SSL_CONF_cmd_value_type,
SSL_CONF_cmd - send configuration command
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);
=head1 DESCRIPTION
The function SSL_CONF_cmd() performs configuration operation B<cmd> with
optional parameter B<value> on B<ctx>. Its purpose is to simplify application
configuration of B<SSL_CTX> or B<SSL> structures by providing a common
framework for command line options or configuration files.
SSL_CONF_cmd_value_type() returns the type of value that B<cmd> refers to.
=head1 SUPPORTED COMMAND LINE COMMANDS
Currently supported B<cmd> names for command lines (i.e. when the
flag B<SSL_CONF_CMDLINE> is set) are listed below. Note: all B<cmd> names
are case sensitive. Unless otherwise stated commands can be used by
both clients and servers and the B<value> parameter is not used. The default
prefix for command line commands is B<-> and that is reflected below.
=over 4
=item B<-sigalgs>
This sets the supported signature algorithms for TLSv1.2 and TLSv1.3.
For clients this
value is used directly for the supported signature algorithms extension. For
servers it is used to determine which signature algorithms to support.
The B<value> argument should be a colon separated list of signature algorithms
in order of decreasing preference of the form B<algorithm+hash> or
B<signature_scheme>. B<algorithm>
is one of B<RSA>, B<DSA> or B<ECDSA> and B<hash> is a supported algorithm
OID short name such as B<SHA1>, B<SHA224>, B<SHA256>, B<SHA384> of B<SHA512>.
Note: algorithm and hash names are case sensitive.
B<signature_scheme> is one of the signature schemes defined in TLSv1.3,
specified using the IETF name, e.g., B<ecdsa_secp256r1_sha256>, B<ed25519>,
or B<rsa_pss_pss_sha256>.
If this option is not set then all signature algorithms supported by the
OpenSSL library are permissible.
Note: algorithms which specify a PKCS#1 v1.5 signature scheme (either by
using B<RSA> as the B<algorithm> or by using one of the B<rsa_pkcs1_*>
identifiers) are ignored in TLSv1.3 and will not be negotiated.
=item B<-client_sigalgs>
This sets the supported signature algorithms associated with client
authentication for TLSv1.2 and TLSv1.3.
For servers the value is used in the
B<signature_algorithms> field of a B<CertificateRequest> message.
For clients it is
used to determine which signature algorithm to use with the client certificate.
If a server does not request a certificate this option has no effect.
The syntax of B<value> is identical to B<-sigalgs>. If not set then
the value set for B<-sigalgs> will be used instead.
=item B<-groups>
This sets the supported groups. For clients, the groups are
sent using the supported groups extension. For servers, it is used
to determine which group to use. This setting affects groups used for
signatures (in TLSv1.2 and earlier) and key exchange. The first group listed
will also be used for the B<key_share> sent by a client in a TLSv1.3
B<ClientHello>.
The B<value> argument is a colon separated list of groups. The group can be
either the B<NIST> name (e.g. B<P-256>), some other commonly used name where
applicable (e.g. B<X25519>) or an OpenSSL OID name (e.g B<prime256v1>). Group
names are case sensitive. The list should be in order of preference with the
most preferred group first.
=item B<-curves>
This is a synonym for the "-groups" command.
=item B<-named_curve>
This sets the temporary curve used for ephemeral ECDH modes. Only used by
servers
The B<value> argument is a curve name or the special value B<auto> which
picks an appropriate curve based on client and server preferences. The curve
can be either the B<NIST> name (e.g. B<P-256>) or an OpenSSL OID name
(e.g B<prime256v1>). Curve names are case sensitive.
=item B<-cipher>
Sets the TLSv1.2 and below ciphersuite list to B<value>. This list will be
combined with any configured TLSv1.3 ciphersuites. Note: syntax checking
of B<value> is currently not performed unless a B<SSL> or B<SSL_CTX> structure is
associated with B<cctx>.
=item B<-ciphersuites>
Sets the available ciphersuites for TLSv1.3 to value. This is a simple colon
(":") separated list of TLSv1.3 ciphersuite names in order of preference. This
list will be combined any configured TLSv1.2 and below ciphersuites.
See L<ciphers(1)> for more information.
=item B<-cert>
Attempts to use the file B<value> as the certificate for the appropriate
context. It currently uses SSL_CTX_use_certificate_chain_file() if an B<SSL_CTX>
structure is set or SSL_use_certificate_file() with filetype PEM if an B<SSL>
structure is set. This option is only supported if certificate operations
are permitted.
=item B<-key>
Attempts to use the file B<value> as the private key for the appropriate
context. This option is only supported if certificate operations
are permitted. Note: if no B<-key> option is set then a private key is
not loaded unless the flag B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set.
=item B<-dhparam>
Attempts to use the file B<value> as the set of temporary DH parameters for
the appropriate context. This option is only supported if certificate
operations are permitted.
=item B<-record_padding>
Attempts to pad TLSv1.3 records so that they are a multiple of B<value> in
length on send. A B<value> of 0 or 1 turns off padding. Otherwise, the
B<value> must be >1 or <=16384.
=item B<-no_renegotiation>
Disables all attempts at renegotiation in TLSv1.2 and earlier, same as setting
B<SSL_OP_NO_RENEGOTIATION>.
=item B<-min_protocol>, B<-max_protocol>
Sets the minimum and maximum supported protocol.
Currently supported protocol values are B<SSLv3>, B<TLSv1>,
B<TLSv1.1>, B<TLSv1.2>, B<TLSv1.3> for TLS and B<DTLSv1>, B<DTLSv1.2> for DTLS,
and B<None> for no limit.
If either bound is not specified then only the other bound applies,
if specified.
To restrict the supported protocol versions use these commands rather
than the deprecated alternative commands below.
=item B<-no_ssl3>, B<-no_tls1>, B<-no_tls1_1>, B<-no_tls1_2>, B<-no_tls1_3>
Disables protocol support for SSLv3, TLSv1.0, TLSv1.1, TLSv1.2 or TLSv1.3 by
setting the corresponding options B<SSL_OP_NO_SSLv3>, B<SSL_OP_NO_TLSv1>,
B<SSL_OP_NO_TLSv1_1>, B<SSL_OP_NO_TLSv1_2> and B<SSL_OP_NO_TLSv1_3>
respectively. These options are deprecated, instead use B<-min_protocol> and
B<-max_protocol>.
=item B<-bugs>
Various bug workarounds are set, same as setting B<SSL_OP_ALL>.
=item B<-comp>
Enables support for SSL/TLS compression, same as clearing
B<SSL_OP_NO_COMPRESSION>.
This command was introduced in OpenSSL 1.1.0.
As of OpenSSL 1.1.0, compression is off by default.
=item B<-no_comp>
Disables support for SSL/TLS compression, same as setting
B<SSL_OP_NO_COMPRESSION>.
As of OpenSSL 1.1.0, compression is off by default.
=item B<-no_ticket>
Disables support for session tickets, same as setting B<SSL_OP_NO_TICKET>.
=item B<-serverpref>
Use server and not client preference order when determining which cipher suite,
signature algorithm or elliptic curve to use for an incoming connection.
Equivalent to B<SSL_OP_CIPHER_SERVER_PREFERENCE>. Only used by servers.
=item B<-prioritize_chacha>
Prioritize ChaCha ciphers when the client has a ChaCha20 cipher at the top of
its preference list. This usually indicates a client without AES hardware
acceleration (e.g. mobile) is in use. Equivalent to B<SSL_OP_PRIORITIZE_CHACHA>.
Only used by servers. Requires B<-serverpref>.
=item B<-no_resumption_on_reneg>
set SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION flag. Only used by servers.
=item B<-legacyrenegotiation>
permits the use of unsafe legacy renegotiation. Equivalent to setting
B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION>.
=item B<-legacy_server_connect>, B<-no_legacy_server_connect>
permits or prohibits the use of unsafe legacy renegotiation for OpenSSL
clients only. Equivalent to setting or clearing B<SSL_OP_LEGACY_SERVER_CONNECT>.
Set by default.
=item B<-allow_no_dhe_kex>
In TLSv1.3 allow a non-(ec)dhe based key exchange mode on resumption. This means
that there will be no forward secrecy for the resumed session.
=item B<-strict>
enables strict mode protocol handling. Equivalent to setting
B<SSL_CERT_FLAG_TLS_STRICT>.
=item B<-anti_replay>, B<-no_anti_replay>
Switches replay protection, on or off respectively. With replay protection on,
OpenSSL will automatically detect if a session ticket has been used more than
once, TLSv1.3 has been negotiated, and early data is enabled on the server. A
full handshake is forced if a session ticket is used a second or subsequent
time. Anti-Replay is on by default unless overridden by a configuration file and
is only used by servers. Anti-replay measures are required for compliance with
the TLSv1.3 specification. Some applications may be able to mitigate the replay
risks in other ways and in such cases the built-in OpenSSL functionality is not
required. Switching off anti-replay is equivalent to B<SSL_OP_NO_ANTI_REPLAY>.
=back
=head1 SUPPORTED CONFIGURATION FILE COMMANDS
Currently supported B<cmd> names for configuration files (i.e. when the
flag B<SSL_CONF_FLAG_FILE> is set) are listed below. All configuration file
B<cmd> names are case insensitive so B<signaturealgorithms> is recognised
as well as B<SignatureAlgorithms>. Unless otherwise stated the B<value> names
are also case insensitive.
Note: the command prefix (if set) alters the recognised B<cmd> values.
=over 4
=item B<CipherString>
Sets the ciphersuite list for TLSv1.2 and below to B<value>. This list will be
combined with any configured TLSv1.3 ciphersuites. Note: syntax
checking of B<value> is currently not performed unless an B<SSL> or B<SSL_CTX>
structure is associated with B<cctx>.
=item B<Ciphersuites>
Sets the available ciphersuites for TLSv1.3 to B<value>. This is a simple colon
(":") separated list of TLSv1.3 ciphersuite names in order of preference. This
list will be combined any configured TLSv1.2 and below ciphersuites.
See L<ciphers(1)> for more information.
=item B<Certificate>
Attempts to use the file B<value> as the certificate for the appropriate
context. It currently uses SSL_CTX_use_certificate_chain_file() if an B<SSL_CTX>
structure is set or SSL_use_certificate_file() with filetype PEM if an B<SSL>
structure is set. This option is only supported if certificate operations
are permitted.
=item B<PrivateKey>
Attempts to use the file B<value> as the private key for the appropriate
context. This option is only supported if certificate operations
are permitted. Note: if no B<PrivateKey> option is set then a private key is
not loaded unless the B<SSL_CONF_FLAG_REQUIRE_PRIVATE> is set.
=item B<ChainCAFile>, B<ChainCAPath>, B<VerifyCAFile>, B<VerifyCAPath>
These options indicate a file or directory used for building certificate
chains or verifying certificate chains. These options are only supported
if certificate operations are permitted.
=item B<RequestCAFile>
This option indicates a file containing a set of certificates in PEM form.
The subject names of the certificates are sent to the peer in the
B<certificate_authorities> extension for TLS 1.3 (in ClientHello or
CertificateRequest) or in a certificate request for previous versions or
TLS.
=item B<ServerInfoFile>
Attempts to use the file B<value> in the "serverinfo" extension using the
function SSL_CTX_use_serverinfo_file.
=item B<DHParameters>
Attempts to use the file B<value> as the set of temporary DH parameters for
the appropriate context. This option is only supported if certificate
operations are permitted.
=item B<RecordPadding>
Attempts to pad TLSv1.3 records so that they are a multiple of B<value> in
length on send. A B<value> of 0 or 1 turns off padding. Otherwise, the
B<value> must be >1 or <=16384.
=item B<SignatureAlgorithms>
This sets the supported signature algorithms for TLSv1.2 and TLSv1.3.
For clients this
value is used directly for the supported signature algorithms extension. For
servers it is used to determine which signature algorithms to support.
The B<value> argument should be a colon separated list of signature algorithms
in order of decreasing preference of the form B<algorithm+hash> or
B<signature_scheme>. B<algorithm>
is one of B<RSA>, B<DSA> or B<ECDSA> and B<hash> is a supported algorithm
OID short name such as B<SHA1>, B<SHA224>, B<SHA256>, B<SHA384> of B<SHA512>.
Note: algorithm and hash names are case sensitive.
B<signature_scheme> is one of the signature schemes defined in TLSv1.3,
specified using the IETF name, e.g., B<ecdsa_secp256r1_sha256>, B<ed25519>,
or B<rsa_pss_pss_sha256>.
If this option is not set then all signature algorithms supported by the
OpenSSL library are permissible.
Note: algorithms which specify a PKCS#1 v1.5 signature scheme (either by
using B<RSA> as the B<algorithm> or by using one of the B<rsa_pkcs1_*>
identifiers) are ignored in TLSv1.3 and will not be negotiated.
=item B<ClientSignatureAlgorithms>
This sets the supported signature algorithms associated with client
authentication for TLSv1.2 and TLSv1.3.
For servers the value is used in the
B<signature_algorithms> field of a B<CertificateRequest> message.
For clients it is
used to determine which signature algorithm to use with the client certificate.
If a server does not request a certificate this option has no effect.
The syntax of B<value> is identical to B<SignatureAlgorithms>. If not set then
the value set for B<SignatureAlgorithms> will be used instead.
=item B<Groups>
This sets the supported groups. For clients, the groups are
sent using the supported groups extension. For servers, it is used
to determine which group to use. This setting affects groups used for
signatures (in TLSv1.2 and earlier) and key exchange. The first group listed
will also be used for the B<key_share> sent by a client in a TLSv1.3
B<ClientHello>.
The B<value> argument is a colon separated list of groups. The group can be
either the B<NIST> name (e.g. B<P-256>), some other commonly used name where
applicable (e.g. B<X25519>) or an OpenSSL OID name (e.g B<prime256v1>). Group
names are case sensitive. The list should be in order of preference with the
most preferred group first.
=item B<Curves>
This is a synonym for the "Groups" command.
=item B<MinProtocol>
This sets the minimum supported SSL, TLS or DTLS version.
Currently supported protocol values are B<SSLv3>, B<TLSv1>, B<TLSv1.1>,
B<TLSv1.2>, B<TLSv1.3>, B<DTLSv1> and B<DTLSv1.2>.
The value B<None> will disable the limit.
=item B<MaxProtocol>
This sets the maximum supported SSL, TLS or DTLS version.
Currently supported protocol values are B<SSLv3>, B<TLSv1>, B<TLSv1.1>,
B<TLSv1.2>, B<TLSv1.3>, B<DTLSv1> and B<DTLSv1.2>.
The value B<None> will disable the limit.
=item B<Protocol>
This can be used to enable or disable certain versions of the SSL,
TLS or DTLS protocol.
The B<value> argument is a comma separated list of supported protocols
to enable or disable.
If a protocol is preceded by B<-> that version is disabled.
All protocol versions are enabled by default.
You need to disable at least one protocol version for this setting have any
effect.
Only enabling some protocol versions does not disable the other protocol
versions.
Currently supported protocol values are B<SSLv3>, B<TLSv1>, B<TLSv1.1>,
B<TLSv1.2>, B<TLSv1.3>, B<DTLSv1> and B<DTLSv1.2>.
The special value B<ALL> refers to all supported versions.
This can't enable protocols that are disabled using B<MinProtocol>
or B<MaxProtocol>, but can disable protocols that are still allowed
by them.
The B<Protocol> command is fragile and deprecated; do not use it.
Use B<MinProtocol> and B<MaxProtocol> instead.
If you do use B<Protocol>, make sure that the resulting range of enabled
protocols has no "holes", e.g. if TLS 1.0 and TLS 1.2 are both enabled, make
sure to also leave TLS 1.1 enabled.
=item B<Options>
The B<value> argument is a comma separated list of various flags to set.
If a flag string is preceded B<-> it is disabled.
See the L<SSL_CTX_set_options(3)> function for more details of
individual options.
Each option is listed below. Where an operation is enabled by default
the B<-flag> syntax is needed to disable it.
B<SessionTicket>: session ticket support, enabled by default. Inverse of
B<SSL_OP_NO_TICKET>: that is B<-SessionTicket> is the same as setting
B<SSL_OP_NO_TICKET>.
B<Compression>: SSL/TLS compression support, enabled by default. Inverse
of B<SSL_OP_NO_COMPRESSION>.
B<EmptyFragments>: use empty fragments as a countermeasure against a
SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. It
is set by default. Inverse of B<SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS>.
B<Bugs>: enable various bug workarounds. Same as B<SSL_OP_ALL>.
B<DHSingle>: enable single use DH keys, set by default. Inverse of
B<SSL_OP_DH_SINGLE>. Only used by servers.
B<ECDHSingle>: enable single use ECDH keys, set by default. Inverse of
B<SSL_OP_ECDH_SINGLE>. Only used by servers.
B<ServerPreference>: use server and not client preference order when
determining which cipher suite, signature algorithm or elliptic curve
to use for an incoming connection. Equivalent to
B<SSL_OP_CIPHER_SERVER_PREFERENCE>. Only used by servers.
B<PrioritizeChaCha>: prioritizes ChaCha ciphers when the client has a
ChaCha20 cipher at the top of its preference list. This usually indicates
a mobile client is in use. Equivalent to B<SSL_OP_PRIORITIZE_CHACHA>.
Only used by servers.
B<NoResumptionOnRenegotiation>: set
B<SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION> flag. Only used by servers.
B<NoRenegotiation>: disables all attempts at renegotiation in TLSv1.2 and
earlier, same as setting B<SSL_OP_NO_RENEGOTIATION>.
B<UnsafeLegacyRenegotiation>: permits the use of unsafe legacy renegotiation.
Equivalent to B<SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION>.
B<UnsafeLegacyServerConnect>: permits the use of unsafe legacy renegotiation
for OpenSSL clients only. Equivalent to B<SSL_OP_LEGACY_SERVER_CONNECT>.
Set by default.
B<EncryptThenMac>: use encrypt-then-mac extension, enabled by
default. Inverse of B<SSL_OP_NO_ENCRYPT_THEN_MAC>: that is,
B<-EncryptThenMac> is the same as setting B<SSL_OP_NO_ENCRYPT_THEN_MAC>.
B<AllowNoDHEKEX>: In TLSv1.3 allow a non-(ec)dhe based key exchange mode on
resumption. This means that there will be no forward secrecy for the resumed
session. Equivalent to B<SSL_OP_ALLOW_NO_DHE_KEX>.
B<MiddleboxCompat>: If set then dummy Change Cipher Spec (CCS) messages are sent
in TLSv1.3. This has the effect of making TLSv1.3 look more like TLSv1.2 so that
middleboxes that do not understand TLSv1.3 will not drop the connection. This
option is set by default. A future version of OpenSSL may not set this by
default. Equivalent to B<SSL_OP_ENABLE_MIDDLEBOX_COMPAT>.
B<AntiReplay>: If set then OpenSSL will automatically detect if a session ticket
has been used more than once, TLSv1.3 has been negotiated, and early data is
enabled on the server. A full handshake is forced if a session ticket is used a
second or subsequent time. This option is set by default and is only used by
servers. Anti-replay measures are required to comply with the TLSv1.3
specification. Some applications may be able to mitigate the replay risks in
other ways and in such cases the built-in OpenSSL functionality is not required.
Disabling anti-replay is equivalent to setting B<SSL_OP_NO_ANTI_REPLAY>.
=item B<VerifyMode>
The B<value> argument is a comma separated list of flags to set.
B<Peer> enables peer verification: for clients only.
B<Request> requests but does not require a certificate from the client.
Servers only.
B<Require> requests and requires a certificate from the client: an error
occurs if the client does not present a certificate. Servers only.
B<Once> requests a certificate from a client only on the initial connection:
not when renegotiating. Servers only.
B<RequestPostHandshake> configures the connection to support requests but does
not require a certificate from the client post-handshake. A certificate will
not be requested during the initial handshake. The server application must
provide a mechanism to request a certificate post-handshake. Servers only.
TLSv1.3 only.
B<RequiresPostHandshake> configures the connection to support requests and
requires a certificate from the client post-handshake: an error occurs if the
client does not present a certificate. A certificate will not be requested
during the initial handshake. The server application must provide a mechanism
to request a certificate post-handshake. Servers only. TLSv1.3 only.
=item B<ClientCAFile>, B<ClientCAPath>
A file or directory of certificates in PEM format whose names are used as the
set of acceptable names for client CAs. Servers only. This option is only
supported if certificate operations are permitted.
=back
=head1 SUPPORTED COMMAND TYPES
The function SSL_CONF_cmd_value_type() currently returns one of the following
types:
=over 4
=item B<SSL_CONF_TYPE_UNKNOWN>
The B<cmd> string is unrecognised, this return value can be use to flag
syntax errors.
=item B<SSL_CONF_TYPE_STRING>
The value is a string without any specific structure.
=item B<SSL_CONF_TYPE_FILE>
The value is a file name.
=item B<SSL_CONF_TYPE_DIR>
The value is a directory name.
=item B<SSL_CONF_TYPE_NONE>
The value string is not used e.g. a command line option which doesn't take an
argument.
=back
=head1 NOTES
The order of operations is significant. This can be used to set either defaults
or values which cannot be overridden. For example if an application calls:
SSL_CONF_cmd(ctx, "Protocol", "-SSLv3");
SSL_CONF_cmd(ctx, userparam, uservalue);
it will disable SSLv3 support by default but the user can override it. If
however the call sequence is:
SSL_CONF_cmd(ctx, userparam, uservalue);
SSL_CONF_cmd(ctx, "Protocol", "-SSLv3");
SSLv3 is B<always> disabled and attempt to override this by the user are
ignored.
By checking the return code of SSL_CONF_cmd() it is possible to query if a
given B<cmd> is recognised, this is useful if SSL_CONF_cmd() values are
mixed with additional application specific operations.
For example an application might call SSL_CONF_cmd() and if it returns
-2 (unrecognised command) continue with processing of application specific
commands.
Applications can also use SSL_CONF_cmd() to process command lines though the
utility function SSL_CONF_cmd_argv() is normally used instead. One way
to do this is to set the prefix to an appropriate value using
SSL_CONF_CTX_set1_prefix(), pass the current argument to B<cmd> and the
following argument to B<value> (which may be NULL).
In this case if the return value is positive then it is used to skip that
number of arguments as they have been processed by SSL_CONF_cmd(). If -2 is
returned then B<cmd> is not recognised and application specific arguments
can be checked instead. If -3 is returned a required argument is missing
and an error is indicated. If 0 is returned some other error occurred and
this can be reported back to the user.
The function SSL_CONF_cmd_value_type() can be used by applications to
check for the existence of a command or to perform additional syntax
checking or translation of the command value. For example if the return
value is B<SSL_CONF_TYPE_FILE> an application could translate a relative
pathname to an absolute pathname.
+=head1 RETURN VALUES
+
+SSL_CONF_cmd() returns 1 if the value of B<cmd> is recognised and B<value> is
+B<NOT> used and 2 if both B<cmd> and B<value> are used. In other words it
+returns the number of arguments processed. This is useful when processing
+command lines.
+
+A return value of -2 means B<cmd> is not recognised.
+
+A return value of -3 means B<cmd> is recognised and the command requires a
+value but B<value> is NULL.
+
+A return code of 0 indicates that both B<cmd> and B<value> are valid but an
+error occurred attempting to perform the operation: for example due to an
+error in the syntax of B<value> in this case the error queue may provide
+additional information.
+
=head1 EXAMPLES
Set supported signature algorithms:
SSL_CONF_cmd(ctx, "SignatureAlgorithms", "ECDSA+SHA256:RSA+SHA256:DSA+SHA256");
There are various ways to select the supported protocols.
This set the minimum protocol version to TLSv1, and so disables SSLv3.
This is the recommended way to disable protocols.
SSL_CONF_cmd(ctx, "MinProtocol", "TLSv1");
The following also disables SSLv3:
SSL_CONF_cmd(ctx, "Protocol", "-SSLv3");
The following will first enable all protocols, and then disable
SSLv3.
If no protocol versions were disabled before this has the same effect as
"-SSLv3", but if some versions were disables this will re-enable them before
disabling SSLv3.
SSL_CONF_cmd(ctx, "Protocol", "ALL,-SSLv3");
Only enable TLSv1.2:
SSL_CONF_cmd(ctx, "MinProtocol", "TLSv1.2");
SSL_CONF_cmd(ctx, "MaxProtocol", "TLSv1.2");
This also only enables TLSv1.2:
SSL_CONF_cmd(ctx, "Protocol", "-ALL,TLSv1.2");
Disable TLS session tickets:
SSL_CONF_cmd(ctx, "Options", "-SessionTicket");
Enable compression:
SSL_CONF_cmd(ctx, "Options", "Compression");
Set supported curves to P-256, P-384:
SSL_CONF_cmd(ctx, "Curves", "P-256:P-384");
-=head1 RETURN VALUES
-
-SSL_CONF_cmd() returns 1 if the value of B<cmd> is recognised and B<value> is
-B<NOT> used and 2 if both B<cmd> and B<value> are used. In other words it
-returns the number of arguments processed. This is useful when processing
-command lines.
-
-A return value of -2 means B<cmd> is not recognised.
-
-A return value of -3 means B<cmd> is recognised and the command requires a
-value but B<value> is NULL.
-
-A return code of 0 indicates that both B<cmd> and B<value> are valid but an
-error occurred attempting to perform the operation: for example due to an
-error in the syntax of B<value> in this case the error queue may provide
-additional information.
-
=head1 SEE ALSO
L<SSL_CONF_CTX_new(3)>,
L<SSL_CONF_CTX_set_flags(3)>,
L<SSL_CONF_CTX_set1_prefix(3)>,
L<SSL_CONF_CTX_set_ssl_ctx(3)>,
L<SSL_CONF_cmd_argv(3)>,
L<SSL_CTX_set_options(3)>
=head1 HISTORY
The SSL_CONF_cmd() function was added in OpenSSL 1.0.2.
The B<SSL_OP_NO_SSL2> option doesn't have effect since 1.1.0, but the macro
is retained for backwards compatibility.
The B<SSL_CONF_TYPE_NONE> was added in OpenSSL 1.1.0. In earlier versions of
OpenSSL passing a command which didn't take an argument would return
B<SSL_CONF_TYPE_UNKNOWN>.
B<MinProtocol> and B<MaxProtocol> where added in OpenSSL 1.1.0.
B<AllowNoDHEKEX> and B<PrioritizeChaCha> were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
Copyright 2012-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_load_verify_locations.pod b/doc/man3/SSL_CTX_load_verify_locations.pod
index a96aafed5f76..b16271bfaa19 100644
--- a/doc/man3/SSL_CTX_load_verify_locations.pod
+++ b/doc/man3/SSL_CTX_load_verify_locations.pod
@@ -1,161 +1,161 @@
=pod
=head1 NAME
SSL_CTX_load_verify_locations, SSL_CTX_set_default_verify_paths,
SSL_CTX_set_default_verify_dir, SSL_CTX_set_default_verify_file - set
default locations for trusted CA certificates
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath);
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
=head1 DESCRIPTION
SSL_CTX_load_verify_locations() specifies the locations for B<ctx>, at
which CA certificates for verification purposes are located. The certificates
available via B<CAfile> and B<CApath> are trusted.
SSL_CTX_set_default_verify_paths() specifies that the default locations from
which CA certificates are loaded should be used. There is one default directory
and one default file. The default CA certificates directory is called "certs" in
the default OpenSSL directory. Alternatively the SSL_CERT_DIR environment
variable can be defined to override this location. The default CA certificates
file is called "cert.pem" in the default OpenSSL directory. Alternatively the
SSL_CERT_FILE environment variable can be defined to override this location.
SSL_CTX_set_default_verify_dir() is similar to
SSL_CTX_set_default_verify_paths() except that just the default directory is
used.
SSL_CTX_set_default_verify_file() is similar to
SSL_CTX_set_default_verify_paths() except that just the default file is
used.
=head1 NOTES
If B<CAfile> is not NULL, it points to a file of CA certificates in PEM
format. The file can contain several CA certificates identified by
-----BEGIN CERTIFICATE-----
... (CA certificate in base64 encoding) ...
-----END CERTIFICATE-----
sequences. Before, between, and after the certificates text is allowed
which can be used e.g. for descriptions of the certificates.
The B<CAfile> is processed on execution of the SSL_CTX_load_verify_locations()
function.
If B<CApath> is not NULL, it points to a directory containing CA certificates
in PEM format. The files each contain one CA certificate. The files are
looked up by the CA subject name hash value, which must hence be available.
If more than one CA certificate with the same name hash value exist, the
extension must be different (e.g. 9d66eef0.0, 9d66eef0.1 etc). The search
is performed in the ordering of the extension number, regardless of other
properties of the certificates.
Use the B<c_rehash> utility to create the necessary links.
The certificates in B<CApath> are only looked up when required, e.g. when
building the certificate chain or when actually performing the verification
of a peer certificate.
When looking up CA certificates, the OpenSSL library will first search the
certificates in B<CAfile>, then those in B<CApath>. Certificate matching
is done based on the subject name, the key identifier (if present), and the
serial number as taken from the certificate to be verified. If these data
do not match, the next certificate will be tried. If a first certificate
matching the parameters is found, the verification process will be performed;
no other certificates for the same parameters will be searched in case of
failure.
In server mode, when requesting a client certificate, the server must send
the list of CAs of which it will accept client certificates. This list
is not influenced by the contents of B<CAfile> or B<CApath> and must
explicitly be set using the
L<SSL_CTX_set_client_CA_list(3)>
family of functions.
When building its own certificate chain, an OpenSSL client/server will
try to fill in missing certificates from B<CAfile>/B<CApath>, if the
certificate chain was not explicitly specified (see
L<SSL_CTX_add_extra_chain_cert(3)>,
L<SSL_CTX_use_certificate(3)>.
=head1 WARNINGS
If several CA certificates matching the name, key identifier, and serial
number condition are available, only the first one will be examined. This
may lead to unexpected results if the same CA certificate is available
with different expiration dates. If a "certificate expired" verification
error occurs, no other certificate will be searched. Make sure to not
have expired certificates mixed with valid ones.
-=head1 EXAMPLES
-
-Generate a CA certificate file with descriptive text from the CA certificates
-ca1.pem ca2.pem ca3.pem:
-
- #!/bin/sh
- rm CAfile.pem
- for i in ca1.pem ca2.pem ca3.pem ; do
- openssl x509 -in $i -text >> CAfile.pem
- done
-
-Prepare the directory /some/where/certs containing several CA certificates
-for use as B<CApath>:
-
- cd /some/where/certs
- c_rehash .
-
=head1 RETURN VALUES
For SSL_CTX_load_verify_locations the following return values can occur:
=over 4
=item Z<>0
The operation failed because B<CAfile> and B<CApath> are NULL or the
processing at one of the locations specified failed. Check the error
stack to find out the reason.
=item Z<>1
The operation succeeded.
=back
SSL_CTX_set_default_verify_paths(), SSL_CTX_set_default_verify_dir() and
SSL_CTX_set_default_verify_file() all return 1 on success or 0 on failure. A
missing default location is still treated as a success.
+=head1 EXAMPLES
+
+Generate a CA certificate file with descriptive text from the CA certificates
+ca1.pem ca2.pem ca3.pem:
+
+ #!/bin/sh
+ rm CAfile.pem
+ for i in ca1.pem ca2.pem ca3.pem ; do
+ openssl x509 -in $i -text >> CAfile.pem
+ done
+
+Prepare the directory /some/where/certs containing several CA certificates
+for use as B<CApath>:
+
+ cd /some/where/certs
+ c_rehash .
+
=head1 SEE ALSO
L<ssl(7)>,
L<SSL_CTX_set_client_CA_list(3)>,
L<SSL_get_client_CA_list(3)>,
L<SSL_CTX_use_certificate(3)>,
L<SSL_CTX_add_extra_chain_cert(3)>,
L<SSL_CTX_set_cert_store(3)>,
L<SSL_CTX_set_client_CA_list(3)>
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_new.pod b/doc/man3/SSL_CTX_new.pod
index d07834151eb7..df25a6f657fd 100644
--- a/doc/man3/SSL_CTX_new.pod
+++ b/doc/man3/SSL_CTX_new.pod
@@ -1,219 +1,219 @@
=pod
=head1 NAME
TLSv1_2_method, TLSv1_2_server_method, TLSv1_2_client_method,
SSL_CTX_new, SSL_CTX_up_ref, SSLv3_method, SSLv3_server_method,
SSLv3_client_method, TLSv1_method, TLSv1_server_method, TLSv1_client_method,
TLSv1_1_method, TLSv1_1_server_method, TLSv1_1_client_method, TLS_method,
TLS_server_method, TLS_client_method, SSLv23_method, SSLv23_server_method,
SSLv23_client_method, DTLS_method, DTLS_server_method, DTLS_client_method,
DTLSv1_method, DTLSv1_server_method, DTLSv1_client_method,
DTLSv1_2_method, DTLSv1_2_server_method, DTLSv1_2_client_method
- create a new SSL_CTX object as framework for TLS/SSL or DTLS enabled
functions
=head1 SYNOPSIS
#include <openssl/ssl.h>
SSL_CTX *SSL_CTX_new(const SSL_METHOD *method);
int SSL_CTX_up_ref(SSL_CTX *ctx);
const SSL_METHOD *TLS_method(void);
const SSL_METHOD *TLS_server_method(void);
const SSL_METHOD *TLS_client_method(void);
const SSL_METHOD *SSLv23_method(void);
const SSL_METHOD *SSLv23_server_method(void);
const SSL_METHOD *SSLv23_client_method(void);
#ifndef OPENSSL_NO_SSL3_METHOD
const SSL_METHOD *SSLv3_method(void);
const SSL_METHOD *SSLv3_server_method(void);
const SSL_METHOD *SSLv3_client_method(void);
#endif
#ifndef OPENSSL_NO_TLS1_METHOD
const SSL_METHOD *TLSv1_method(void);
const SSL_METHOD *TLSv1_server_method(void);
const SSL_METHOD *TLSv1_client_method(void);
#endif
#ifndef OPENSSL_NO_TLS1_1_METHOD
const SSL_METHOD *TLSv1_1_method(void);
const SSL_METHOD *TLSv1_1_server_method(void);
const SSL_METHOD *TLSv1_1_client_method(void);
#endif
#ifndef OPENSSL_NO_TLS1_2_METHOD
const SSL_METHOD *TLSv1_2_method(void);
const SSL_METHOD *TLSv1_2_server_method(void);
const SSL_METHOD *TLSv1_2_client_method(void);
#endif
const SSL_METHOD *DTLS_method(void);
const SSL_METHOD *DTLS_server_method(void);
const SSL_METHOD *DTLS_client_method(void);
#ifndef OPENSSL_NO_DTLS1_METHOD
const SSL_METHOD *DTLSv1_method(void);
const SSL_METHOD *DTLSv1_server_method(void);
const SSL_METHOD *DTLSv1_client_method(void);
#endif
#ifndef OPENSSL_NO_DTLS1_2_METHOD
const SSL_METHOD *DTLSv1_2_method(void);
const SSL_METHOD *DTLSv1_2_server_method(void);
const SSL_METHOD *DTLSv1_2_client_method(void);
#endif
=head1 DESCRIPTION
SSL_CTX_new() creates a new B<SSL_CTX> object as framework to
establish TLS/SSL or DTLS enabled connections. An B<SSL_CTX> object is
reference counted. Creating an B<SSL_CTX> object for the first time increments
the reference count. Freeing it (using SSL_CTX_free) decrements it. When the
reference count drops to zero, any memory or resources allocated to the
B<SSL_CTX> object are freed. SSL_CTX_up_ref() increments the reference count for
an existing B<SSL_CTX> structure.
=head1 NOTES
The SSL_CTX object uses B<method> as connection method.
The methods exist in a generic type (for client and server use), a server only
type, and a client only type.
B<method> can be of the following types:
=over 4
=item TLS_method(), TLS_server_method(), TLS_client_method()
These are the general-purpose I<version-flexible> SSL/TLS methods.
The actual protocol version used will be negotiated to the highest version
mutually supported by the client and the server.
The supported protocols are SSLv3, TLSv1, TLSv1.1, TLSv1.2 and TLSv1.3.
Applications should use these methods, and avoid the version-specific
methods described below.
=item SSLv23_method(), SSLv23_server_method(), SSLv23_client_method()
Use of these functions is deprecated. They have been replaced with the above
TLS_method(), TLS_server_method() and TLS_client_method() respectively. New
code should use those functions instead.
=item TLSv1_2_method(), TLSv1_2_server_method(), TLSv1_2_client_method()
A TLS/SSL connection established with these methods will only understand the
TLSv1.2 protocol.
=item TLSv1_1_method(), TLSv1_1_server_method(), TLSv1_1_client_method()
A TLS/SSL connection established with these methods will only understand the
TLSv1.1 protocol.
=item TLSv1_method(), TLSv1_server_method(), TLSv1_client_method()
A TLS/SSL connection established with these methods will only understand the
TLSv1 protocol.
=item SSLv3_method(), SSLv3_server_method(), SSLv3_client_method()
A TLS/SSL connection established with these methods will only understand the
SSLv3 protocol.
The SSLv3 protocol is deprecated and should not be used.
=item DTLS_method(), DTLS_server_method(), DTLS_client_method()
These are the version-flexible DTLS methods.
Currently supported protocols are DTLS 1.0 and DTLS 1.2.
=item DTLSv1_2_method(), DTLSv1_2_server_method(), DTLSv1_2_client_method()
These are the version-specific methods for DTLSv1.2.
=item DTLSv1_method(), DTLSv1_server_method(), DTLSv1_client_method()
These are the version-specific methods for DTLSv1.
=back
SSL_CTX_new() initializes the list of ciphers, the session cache setting, the
callbacks, the keys and certificates and the options to their default values.
TLS_method(), TLS_server_method(), TLS_client_method(), DTLS_method(),
DTLS_server_method() and DTLS_client_method() are the I<version-flexible>
methods.
All other methods only support one specific protocol version.
Use the I<version-flexible> methods instead of the version specific methods.
If you want to limit the supported protocols for the version flexible
methods you can use L<SSL_CTX_set_min_proto_version(3)>,
L<SSL_set_min_proto_version(3)>, L<SSL_CTX_set_max_proto_version(3)> and
L<SSL_set_max_proto_version(3)> functions.
Using these functions it is possible to choose e.g. TLS_server_method()
and be able to negotiate with all possible clients, but to only
allow newer protocols like TLS 1.0, TLS 1.1, TLS 1.2 or TLS 1.3.
The list of protocols available can also be limited using the
B<SSL_OP_NO_SSLv3>, B<SSL_OP_NO_TLSv1>, B<SSL_OP_NO_TLSv1_1>,
B<SSL_OP_NO_TLSv1_3>, B<SSL_OP_NO_TLSv1_2> and B<SSL_OP_NO_TLSv1_3>
options of the
L<SSL_CTX_set_options(3)> or L<SSL_set_options(3)> functions, but this approach
is not recommended. Clients should avoid creating "holes" in the set of
protocols they support. When disabling a protocol, make sure that you also
disable either all previous or all subsequent protocol versions.
In clients, when a protocol version is disabled without disabling I<all>
previous protocol versions, the effect is to also disable all subsequent
protocol versions.
The SSLv3 protocol is deprecated and should generally not be used.
Applications should typically use L<SSL_CTX_set_min_proto_version(3)> to set
the minimum protocol to at least B<TLS1_VERSION>.
=head1 RETURN VALUES
The following return values can occur:
=over 4
=item NULL
The creation of a new SSL_CTX object failed. Check the error stack to find out
the reason.
=item Pointer to an SSL_CTX object
The return value points to an allocated SSL_CTX object.
SSL_CTX_up_ref() returns 1 for success and 0 for failure.
=back
+=head1 SEE ALSO
+
+L<SSL_CTX_set_options(3)>, L<SSL_CTX_free(3)>, L<SSL_accept(3)>,
+L<SSL_CTX_set_min_proto_version(3)>, L<ssl(7)>, L<SSL_set_connect_state(3)>
+
=head1 HISTORY
Support for SSLv2 and the corresponding SSLv2_method(),
SSLv2_server_method() and SSLv2_client_method() functions where
removed in OpenSSL 1.1.0.
SSLv23_method(), SSLv23_server_method() and SSLv23_client_method()
were deprecated and the preferred TLS_method(), TLS_server_method()
-and TLS_client_method() functions were introduced in OpenSSL 1.1.0.
+and TLS_client_method() functions were added in OpenSSL 1.1.0.
All version-specific methods were deprecated in OpenSSL 1.1.0.
-=head1 SEE ALSO
-
-L<SSL_CTX_set_options(3)>, L<SSL_CTX_free(3)>, L<SSL_accept(3)>,
-L<SSL_CTX_set_min_proto_version(3)>, L<ssl(7)>, L<SSL_set_connect_state(3)>
-
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set1_sigalgs.pod b/doc/man3/SSL_CTX_set1_sigalgs.pod
index 93d5320d965a..1c462a95b6ae 100644
--- a/doc/man3/SSL_CTX_set1_sigalgs.pod
+++ b/doc/man3/SSL_CTX_set1_sigalgs.pod
@@ -1,118 +1,118 @@
=pod
=head1 NAME
SSL_CTX_set1_sigalgs, SSL_set1_sigalgs, SSL_CTX_set1_sigalgs_list,
SSL_set1_sigalgs_list, SSL_CTX_set1_client_sigalgs,
SSL_set1_client_sigalgs, SSL_CTX_set1_client_sigalgs_list,
SSL_set1_client_sigalgs_list - set supported signature algorithms
=head1 SYNOPSIS
#include <openssl/ssl.h>
long SSL_CTX_set1_sigalgs(SSL_CTX *ctx, const int *slist, long slistlen);
long SSL_set1_sigalgs(SSL *ssl, const int *slist, long slistlen);
long SSL_CTX_set1_sigalgs_list(SSL_CTX *ctx, const char *str);
long SSL_set1_sigalgs_list(SSL *ssl, const char *str);
long SSL_CTX_set1_client_sigalgs(SSL_CTX *ctx, const int *slist, long slistlen);
long SSL_set1_client_sigalgs(SSL *ssl, const int *slist, long slistlen);
long SSL_CTX_set1_client_sigalgs_list(SSL_CTX *ctx, const char *str);
long SSL_set1_client_sigalgs_list(SSL *ssl, const char *str);
=head1 DESCRIPTION
SSL_CTX_set1_sigalgs() and SSL_set1_sigalgs() set the supported signature
algorithms for B<ctx> or B<ssl>. The array B<slist> of length B<slistlen>
must consist of pairs of NIDs corresponding to digest and public key
algorithms.
SSL_CTX_set1_sigalgs_list() and SSL_set1_sigalgs_list() set the supported
signature algorithms for B<ctx> or B<ssl>. The B<str> parameter
must be a null terminated string consisting of a colon separated list of
elements, where each element is either a combination of a public key
algorithm and a digest separated by B<+>, or a TLS 1.3-style named
SignatureScheme such as rsa_pss_pss_sha256.
SSL_CTX_set1_client_sigalgs(), SSL_set1_client_sigalgs(),
SSL_CTX_set1_client_sigalgs_list() and SSL_set1_client_sigalgs_list() set
signature algorithms related to client authentication, otherwise they are
identical to SSL_CTX_set1_sigalgs(), SSL_set1_sigalgs(),
SSL_CTX_set1_sigalgs_list() and SSL_set1_sigalgs_list().
All these functions are implemented as macros. The signature algorithm
parameter (integer array or string) is not freed: the application should
free it, if necessary.
=head1 NOTES
If an application wishes to allow the setting of signature algorithms
as one of many user configurable options it should consider using the more
flexible SSL_CONF API instead.
The signature algorithms set by a client are used directly in the supported
signature algorithm in the client hello message.
The supported signature algorithms set by a server are not sent to the
client but are used to determine the set of shared signature algorithms
and (if server preferences are set with SSL_OP_CIPHER_SERVER_PREFERENCE)
their order.
The client authentication signature algorithms set by a server are sent
in a certificate request message if client authentication is enabled,
otherwise they are unused.
Similarly client authentication signature algorithms set by a client are
used to determined the set of client authentication shared signature
algorithms.
Signature algorithms will neither be advertised nor used if the security level
prohibits them (for example SHA1 if the security level is 4 or more).
Currently the NID_md5, NID_sha1, NID_sha224, NID_sha256, NID_sha384 and
NID_sha512 digest NIDs are supported and the public key algorithm NIDs
EVP_PKEY_RSA, EVP_PKEY_RSA_PSS, EVP_PKEY_DSA and EVP_PKEY_EC.
The short or long name values for digests can be used in a string (for
example "MD5", "SHA1", "SHA224", "SHA256", "SHA384", "SHA512") and
the public key algorithm strings "RSA", "RSA-PSS", "DSA" or "ECDSA".
The TLS 1.3 signature scheme names (such as "rsa_pss_pss_sha256") can also
be used with the B<_list> forms of the API.
The use of MD5 as a digest is strongly discouraged due to security weaknesses.
+=head1 RETURN VALUES
+
+All these functions return 1 for success and 0 for failure.
+
=head1 EXAMPLES
Set supported signature algorithms to SHA256 with ECDSA and SHA256 with RSA
using an array:
const int slist[] = {NID_sha256, EVP_PKEY_EC, NID_sha256, EVP_PKEY_RSA};
SSL_CTX_set1_sigalgs(ctx, slist, 4);
Set supported signature algorithms to SHA256 with ECDSA and SHA256 with RSA
using a string:
SSL_CTX_set1_sigalgs_list(ctx, "ECDSA+SHA256:RSA+SHA256");
-=head1 RETURN VALUES
-
-All these functions return 1 for success and 0 for failure.
-
=head1 SEE ALSO
L<ssl(7)>, L<SSL_get_shared_sigalgs(3)>,
L<SSL_CONF_CTX_new(3)>
=head1 COPYRIGHT
-Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_client_hello_cb.pod b/doc/man3/SSL_CTX_set_client_hello_cb.pod
index 6824b5b8d1a4..2ec298960a03 100644
--- a/doc/man3/SSL_CTX_set_client_hello_cb.pod
+++ b/doc/man3/SSL_CTX_set_client_hello_cb.pod
@@ -1,130 +1,132 @@
=pod
=head1 NAME
SSL_CTX_set_client_hello_cb, SSL_client_hello_cb_fn, SSL_client_hello_isv2, SSL_client_hello_get0_legacy_version, SSL_client_hello_get0_random, SSL_client_hello_get0_session_id, SSL_client_hello_get0_ciphers, SSL_client_hello_get0_compression_methods, SSL_client_hello_get1_extensions_present, SSL_client_hello_get0_ext - callback functions for early server-side ClientHello processing
=head1 SYNOPSIS
typedef int (*SSL_client_hello_cb_fn)(SSL *s, int *al, void *arg);
void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn *f,
void *arg);
int SSL_client_hello_isv2(SSL *s);
unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_compression_methods(SSL *s,
const unsigned char **out);
int SSL_client_hello_get1_extensions_present(SSL *s, int **out,
size_t *outlen);
int SSL_client_hello_get0_ext(SSL *s, int type, const unsigned char **out,
size_t *outlen);
=head1 DESCRIPTION
SSL_CTX_set_client_hello_cb() sets the callback function, which is automatically
called during the early stages of ClientHello processing on the server.
The argument supplied when setting the callback is passed back to the
callback at runtime. A callback that returns failure (0) will cause the
connection to terminate, and callbacks returning failure should indicate
what alert value is to be sent in the B<al> parameter. A callback may
also return a negative value to suspend the handshake, and the handshake
function will return immediately. L<SSL_get_error(3)> will return
SSL_ERROR_WANT_CLIENT_HELLO_CB to indicate that the handshake was suspended.
It is the job of the ClientHello callback to store information about the state
of the last call if needed to continue. On the next call into the handshake
function, the ClientHello callback will be called again, and, if it returns
success, normal handshake processing will continue from that point.
SSL_client_hello_isv2() indicates whether the ClientHello was carried in a
SSLv2 record and is in the SSLv2 format. The SSLv2 format has substantial
differences from the normal SSLv3 format, including using three bytes per
cipher suite, and not allowing extensions. Additionally, the SSLv2 format
'challenge' field is exposed via SSL_client_hello_get0_random(), padded to
SSL3_RANDOM_SIZE bytes with zeros if needed. For SSLv2 format ClientHellos,
SSL_client_hello_get0_compression_methods() returns a dummy list that only includes
the null compression method, since the SSLv2 format does not include a
mechanism by which to negotiate compression.
SSL_client_hello_get0_random(), SSL_client_hello_get0_session_id(),
SSL_client_hello_get0_ciphers(), and
SSL_client_hello_get0_compression_methods() provide access to the corresponding
ClientHello fields, returning the field length and optionally setting an out
pointer to the octets of that field.
Similarly, SSL_client_hello_get0_ext() provides access to individual extensions
from the ClientHello on a per-extension basis. For the provided wire
protocol extension type value, the extension value and length are returned
in the output parameters (if present).
SSL_client_hello_get1_extensions_present() can be used prior to
SSL_client_hello_get0_ext(), to determine which extensions are present in the
ClientHello before querying for them. The B<out> and B<outlen> parameters are
both required, and on success the caller must release the storage allocated for
B<*out> using OPENSSL_free(). The contents of B<*out> is an array of integers
holding the numerical value of the TLS extension types in the order they appear
in the ClientHello. B<*outlen> contains the number of elements in the array.
+In situations when the ClientHello has no extensions, the function will return
+success with B<*out> set to NULL and B<*outlen> set to 0.
=head1 NOTES
The ClientHello callback provides a vast window of possibilities for application
code to affect the TLS handshake. A primary use of the callback is to
allow the server to examine the server name indication extension provided
by the client in order to select an appropriate certificate to present,
and make other configuration adjustments relevant to that server name
and its configuration. Such configuration changes can include swapping out
the associated SSL_CTX pointer, modifying the server's list of permitted TLS
versions, changing the server's cipher list in response to the client's
cipher list, etc.
It is also recommended that applications utilize a ClientHello callback and
not use a servername callback, in order to avoid unexpected behavior that
occurs due to the relative order of processing between things like session
resumption and the historical servername callback.
The SSL_client_hello_* family of functions may only be called from code executing
within a ClientHello callback.
=head1 RETURN VALUES
The application's supplied ClientHello callback returns
SSL_CLIENT_HELLO_SUCCESS on success, SSL_CLIENT_HELLO_ERROR on failure, and
SSL_CLIENT_HELLO_RETRY to suspend processing.
SSL_client_hello_isv2() returns 1 for SSLv2-format ClientHellos and 0 otherwise.
SSL_client_hello_get0_random(), SSL_client_hello_get0_session_id(),
SSL_client_hello_get0_ciphers(), and
SSL_client_hello_get0_compression_methods() return the length of the
corresponding ClientHello fields. If zero is returned, the output pointer
should not be assumed to be valid.
SSL_client_hello_get0_ext() returns 1 if the extension of type 'type' is present, and
0 otherwise.
SSL_client_hello_get1_extensions_present() returns 1 on success and 0 on failure.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_CTX_set_tlsext_servername_callback(3)>,
L<SSL_bytes_to_cipher_list>
=head1 HISTORY
The SSL ClientHello callback, SSL_client_hello_isv2(),
SSL_client_hello_get0_random(), SSL_client_hello_get0_session_id(),
SSL_client_hello_get0_ciphers(), SSL_client_hello_get0_compression_methods(),
SSL_client_hello_get0_ext(), and SSL_client_hello_get1_extensions_present()
were added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2017-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_default_passwd_cb.pod b/doc/man3/SSL_CTX_set_default_passwd_cb.pod
index 999a70c8c366..991ce7a5a922 100644
--- a/doc/man3/SSL_CTX_set_default_passwd_cb.pod
+++ b/doc/man3/SSL_CTX_set_default_passwd_cb.pod
@@ -1,113 +1,113 @@
=pod
=head1 NAME
SSL_CTX_set_default_passwd_cb, SSL_CTX_set_default_passwd_cb_userdata,
SSL_CTX_get_default_passwd_cb, SSL_CTX_get_default_passwd_cb_userdata,
SSL_set_default_passwd_cb, SSL_set_default_passwd_cb_userdata,
SSL_get_default_passwd_cb, SSL_get_default_passwd_cb_userdata - set or
get passwd callback for encrypted PEM file handling
=head1 SYNOPSIS
#include <openssl/ssl.h>
void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx);
void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx);
void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb);
void SSL_set_default_passwd_cb_userdata(SSL *s, void *u);
pem_password_cb *SSL_get_default_passwd_cb(SSL *s);
void *SSL_get_default_passwd_cb_userdata(SSL *s);
=head1 DESCRIPTION
SSL_CTX_set_default_passwd_cb() sets the default password callback called
when loading/storing a PEM certificate with encryption.
SSL_CTX_set_default_passwd_cb_userdata() sets a pointer to userdata, B<u>,
which will be provided to the password callback on invocation.
SSL_CTX_get_default_passwd_cb() returns a function pointer to the password
callback currently set in B<ctx>. If no callback was explicitly set, the
NULL pointer is returned.
SSL_CTX_get_default_passwd_cb_userdata() returns a pointer to the userdata
currently set in B<ctx>. If no userdata was explicitly set, the NULL pointer
is returned.
SSL_set_default_passwd_cb(), SSL_set_default_passwd_cb_userdata(),
SSL_get_default_passwd_cb() and SSL_get_default_passwd_cb_userdata() perform
the same function as their SSL_CTX counterparts, but using an SSL object.
The password callback, which must be provided by the application, hands back the
password to be used during decryption.
On invocation a pointer to userdata
is provided. The function must store the password into the provided buffer
B<buf> which is of size B<size>. The actual length of the password must
be returned to the calling function. B<rwflag> indicates whether the
callback is used for reading/decryption (rwflag=0) or writing/encryption
(rwflag=1).
For more details, see L<pem_password_cb(3)>.
=head1 NOTES
When loading or storing private keys, a password might be supplied to
protect the private key. The way this password can be supplied may depend
on the application. If only one private key is handled, it can be practical
to have the callback handle the password dialog interactively. If several
keys have to be handled, it can be practical to ask for the password once,
then keep it in memory and use it several times. In the last case, the
password could be stored into the userdata storage and the
callback only returns the password already stored.
When asking for the password interactively, the callback can use
B<rwflag> to check, whether an item shall be encrypted (rwflag=1).
In this case the password dialog may ask for the same password twice
for comparison in order to catch typos, that would make decryption
impossible.
Other items in PEM formatting (certificates) can also be encrypted, it is
however not usual, as certificate information is considered public.
=head1 RETURN VALUES
These functions do not provide diagnostic information.
=head1 EXAMPLES
The following example returns the password provided as userdata to the
calling function. The password is considered to be a '\0' terminated
string. If the password does not fit into the buffer, the password is
truncated.
int my_cb(char *buf, int size, int rwflag, void *u)
{
strncpy(buf, (char *)u, size);
buf[size - 1] = '\0';
return strlen(buf);
}
+=head1 SEE ALSO
+
+L<ssl(7)>,
+L<SSL_CTX_use_certificate(3)>
+
=head1 HISTORY
SSL_CTX_get_default_passwd_cb(), SSL_CTX_get_default_passwd_cb_userdata(),
SSL_set_default_passwd_cb() and SSL_set_default_passwd_cb_userdata() were
added in OpenSSL 1.1.0.
-=head1 SEE ALSO
-
-L<ssl(7)>,
-L<SSL_CTX_use_certificate(3)>
-
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_generate_session_id.pod b/doc/man3/SSL_CTX_set_generate_session_id.pod
index 2bee351a4dbc..dab563750806 100644
--- a/doc/man3/SSL_CTX_set_generate_session_id.pod
+++ b/doc/man3/SSL_CTX_set_generate_session_id.pod
@@ -1,138 +1,138 @@
=pod
=head1 NAME
SSL_CTX_set_generate_session_id, SSL_set_generate_session_id,
SSL_has_matching_session_id, GEN_SESSION_CB
- manipulate generation of SSL session IDs (server only)
=head1 SYNOPSIS
#include <openssl/ssl.h>
typedef int (*GEN_SESSION_CB)(const SSL *ssl, unsigned char *id,
unsigned int *id_len);
int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb);
int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB, cb);
int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
unsigned int id_len);
=head1 DESCRIPTION
SSL_CTX_set_generate_session_id() sets the callback function for generating
new session ids for SSL/TLS sessions for B<ctx> to be B<cb>.
SSL_set_generate_session_id() sets the callback function for generating
new session ids for SSL/TLS sessions for B<ssl> to be B<cb>.
SSL_has_matching_session_id() checks, whether a session with id B<id>
(of length B<id_len>) is already contained in the internal session cache
of the parent context of B<ssl>.
=head1 NOTES
When a new session is established between client and server, the server
generates a session id. The session id is an arbitrary sequence of bytes.
The length of the session id is between 1 and 32 bytes. The session id is not
security critical but must be unique for the server. Additionally, the session id is
transmitted in the clear when reusing the session so it must not contain
sensitive information.
Without a callback being set, an OpenSSL server will generate a unique
session id from pseudo random numbers of the maximum possible length.
Using the callback function, the session id can be changed to contain
additional information like e.g. a host id in order to improve load balancing
or external caching techniques.
The callback function receives a pointer to the memory location to put
B<id> into and a pointer to the maximum allowed length B<id_len>. The
buffer at location B<id> is only guaranteed to have the size B<id_len>.
The callback is only allowed to generate a shorter id and reduce B<id_len>;
the callback B<must never> increase B<id_len> or write to the location
B<id> exceeding the given limit.
The location B<id> is filled with 0x00 before the callback is called, so the
callback may only fill part of the possible length and leave B<id_len>
untouched while maintaining reproducibility.
Since the sessions must be distinguished, session ids must be unique.
Without the callback a random number is used, so that the probability
of generating the same session id is extremely small (2^256 for SSLv3/TLSv1).
In order to assure the uniqueness of the generated session id, the callback must call
SSL_has_matching_session_id() and generate another id if a conflict occurs.
If an id conflict is not resolved, the handshake will fail.
If the application codes e.g. a unique host id, a unique process number, and
a unique sequence number into the session id, uniqueness could easily be
achieved without randomness added (it should however be taken care that
no confidential information is leaked this way). If the application can not
guarantee uniqueness, it is recommended to use the maximum B<id_len> and
fill in the bytes not used to code special information with random data
to avoid collisions.
SSL_has_matching_session_id() will only query the internal session cache,
not the external one. Since the session id is generated before the
handshake is completed, it is not immediately added to the cache. If
another thread is using the same internal session cache, a race condition
can occur in that another thread generates the same session id.
Collisions can also occur when using an external session cache, since
the external cache is not tested with SSL_has_matching_session_id()
and the same race condition applies.
The callback must return 0 if it cannot generate a session id for whatever
reason and return 1 on success.
+=head1 RETURN VALUES
+
+SSL_CTX_set_generate_session_id() and SSL_set_generate_session_id()
+always return 1.
+
+SSL_has_matching_session_id() returns 1 if another session with the
+same id is already in the cache.
+
=head1 EXAMPLES
The callback function listed will generate a session id with the
server id given, and will fill the rest with pseudo random bytes:
const char session_id_prefix = "www-18";
#define MAX_SESSION_ID_ATTEMPTS 10
static int generate_session_id(const SSL *ssl, unsigned char *id,
unsigned int *id_len)
{
unsigned int count = 0;
do {
RAND_pseudo_bytes(id, *id_len);
/*
* Prefix the session_id with the required prefix. NB: If our
* prefix is too long, clip it - but there will be worse effects
* anyway, eg. the server could only possibly create 1 session
* ID (ie. the prefix!) so all future session negotiations will
* fail due to conflicts.
*/
memcpy(id, session_id_prefix, strlen(session_id_prefix) < *id_len ?
strlen(session_id_prefix) : *id_len);
} while (SSL_has_matching_session_id(ssl, id, *id_len)
&& ++count < MAX_SESSION_ID_ATTEMPTS);
if (count >= MAX_SESSION_ID_ATTEMPTS)
return 0;
return 1;
}
-=head1 RETURN VALUES
-
-SSL_CTX_set_generate_session_id() and SSL_set_generate_session_id()
-always return 1.
-
-SSL_has_matching_session_id() returns 1 if another session with the
-same id is already in the cache.
-
=head1 SEE ALSO
L<ssl(7)>, L<SSL_get_version(3)>
=head1 COPYRIGHT
-Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_min_proto_version.pod b/doc/man3/SSL_CTX_set_min_proto_version.pod
index 45866588601a..7dfbfecf079d 100644
--- a/doc/man3/SSL_CTX_set_min_proto_version.pod
+++ b/doc/man3/SSL_CTX_set_min_proto_version.pod
@@ -1,73 +1,73 @@
=pod
=head1 NAME
SSL_CTX_set_min_proto_version, SSL_CTX_set_max_proto_version,
SSL_CTX_get_min_proto_version, SSL_CTX_get_max_proto_version,
SSL_set_min_proto_version, SSL_set_max_proto_version,
SSL_get_min_proto_version, SSL_get_max_proto_version - Get and set minimum
and maximum supported protocol version
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_CTX_set_min_proto_version(SSL_CTX *ctx, int version);
int SSL_CTX_set_max_proto_version(SSL_CTX *ctx, int version);
int SSL_CTX_get_min_proto_version(SSL_CTX *ctx);
int SSL_CTX_get_max_proto_version(SSL_CTX *ctx);
int SSL_set_min_proto_version(SSL *ssl, int version);
int SSL_set_max_proto_version(SSL *ssl, int version);
int SSL_get_min_proto_version(SSL *ssl);
int SSL_get_max_proto_version(SSL *ssl);
=head1 DESCRIPTION
The functions get or set the minimum and maximum supported protocol versions
for the B<ctx> or B<ssl>.
This works in combination with the options set via
L<SSL_CTX_set_options(3)> that also make it possible to disable
specific protocol versions.
Use these functions instead of disabling specific protocol versions.
Setting the minimum or maximum version to 0, will enable protocol
versions down to the lowest version, or up to the highest version
supported by the library, respectively.
Getters return 0 in case B<ctx> or B<ssl> have been configured to
automatically use the lowest or highest version supported by the library.
Currently supported versions are B<SSL3_VERSION>, B<TLS1_VERSION>,
B<TLS1_1_VERSION>, B<TLS1_2_VERSION>, B<TLS1_3_VERSION> for TLS and
B<DTLS1_VERSION>, B<DTLS1_2_VERSION> for DTLS.
=head1 RETURN VALUES
These setter functions return 1 on success and 0 on failure. The getter
functions return the configured version or 0 for auto-configuration of
lowest or highest protocol, respectively.
=head1 NOTES
All these functions are implemented using macros.
+=head1 SEE ALSO
+
+L<SSL_CTX_set_options(3)>, L<SSL_CONF_cmd(3)>
+
=head1 HISTORY
The setter functions were added in OpenSSL 1.1.0. The getter functions
were added in OpenSSL 1.1.1.
-=head1 SEE ALSO
-
-L<SSL_CTX_set_options(3)>, L<SSL_CONF_cmd(3)>
-
=head1 COPYRIGHT
-Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_read_ahead.pod b/doc/man3/SSL_CTX_set_read_ahead.pod
index 137e251b9585..ff037d938dcd 100644
--- a/doc/man3/SSL_CTX_set_read_ahead.pod
+++ b/doc/man3/SSL_CTX_set_read_ahead.pod
@@ -1,74 +1,74 @@
=pod
=head1 NAME
SSL_CTX_set_read_ahead, SSL_CTX_get_read_ahead,
SSL_set_read_ahead, SSL_get_read_ahead,
SSL_CTX_get_default_read_ahead
- manage whether to read as many input bytes as possible
=head1 SYNOPSIS
#include <openssl/ssl.h>
void SSL_set_read_ahead(SSL *s, int yes);
int SSL_get_read_ahead(const SSL *s);
SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes);
long SSL_CTX_get_read_ahead(SSL_CTX *ctx);
long SSL_CTX_get_default_read_ahead(SSL_CTX *ctx);
=head1 DESCRIPTION
SSL_CTX_set_read_ahead() and SSL_set_read_ahead() set whether we should read as
many input bytes as possible (for non-blocking reads) or not. For example if
B<x> bytes are currently required by OpenSSL, but B<y> bytes are available from
the underlying BIO (where B<y> > B<x>), then OpenSSL will read all B<y> bytes
into its buffer (providing that the buffer is large enough) if reading ahead is
on, or B<x> bytes otherwise.
Setting the parameter B<yes> to 0 turns reading ahead is off, other values turn
it on.
SSL_CTX_set_default_read_ahead() is identical to SSL_CTX_set_read_ahead().
SSL_CTX_get_read_ahead() and SSL_get_read_ahead() indicate whether reading
ahead has been set or not.
SSL_CTX_get_default_read_ahead() is identical to SSL_CTX_get_read_ahead().
=head1 NOTES
These functions have no impact when used with DTLS. The return values for
SSL_CTX_get_read_head() and SSL_get_read_ahead() are undefined for DTLS. Setting
B<read_ahead> can impact the behaviour of the SSL_pending() function
(see L<SSL_pending(3)>).
Since SSL_read() can return B<SSL_ERROR_WANT_READ> for non-application data
records, and SSL_has_pending() can't tell the difference between processed and
unprocessed data, it's recommended that if read ahead is turned on that
B<SSL_MODE_AUTO_RETRY> is not turned off using SSL_CTX_clear_mode().
That will prevent getting B<SSL_ERROR_WANT_READ> when there is still a complete
-record availale that hasn't been processed.
+record available that hasn't been processed.
If the application wants to continue to use the underlying transport (e.g. TCP
connection) after the SSL connection is finished using SSL_shutdown() reading
ahead should be turned off.
Otherwise the SSL structure might read data that it shouldn't.
=head1 RETURN VALUES
SSL_get_read_ahead() and SSL_CTX_get_read_ahead() return 0 if reading ahead is off,
and non zero otherwise.
=head1 SEE ALSO
L<ssl(7)>, L<SSL_pending(3)>
=head1 COPYRIGHT
-Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_split_send_fragment.pod b/doc/man3/SSL_CTX_set_split_send_fragment.pod
index 877b4aecd949..d63ca4157e09 100644
--- a/doc/man3/SSL_CTX_set_split_send_fragment.pod
+++ b/doc/man3/SSL_CTX_set_split_send_fragment.pod
@@ -1,188 +1,188 @@
=pod
=head1 NAME
SSL_CTX_set_max_send_fragment, SSL_set_max_send_fragment,
SSL_CTX_set_split_send_fragment, SSL_set_split_send_fragment,
SSL_CTX_set_max_pipelines, SSL_set_max_pipelines,
SSL_CTX_set_default_read_buffer_len, SSL_set_default_read_buffer_len,
SSL_CTX_set_tlsext_max_fragment_length,
SSL_set_tlsext_max_fragment_length,
SSL_SESSION_get_max_fragment_length - Control fragment size settings and pipelining operations
=head1 SYNOPSIS
#include <openssl/ssl.h>
long SSL_CTX_set_max_send_fragment(SSL_CTX *ctx, long);
long SSL_set_max_send_fragment(SSL *ssl, long m);
long SSL_CTX_set_max_pipelines(SSL_CTX *ctx, long m);
long SSL_set_max_pipelines(SSL_CTX *ssl, long m);
long SSL_CTX_set_split_send_fragment(SSL_CTX *ctx, long m);
long SSL_set_split_send_fragment(SSL *ssl, long m);
void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
void SSL_set_default_read_buffer_len(SSL *s, size_t len);
int SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, uint8_t mode);
int SSL_set_tlsext_max_fragment_length(SSL *ssl, uint8_t mode);
uint8_t SSL_SESSION_get_max_fragment_length(SSL_SESSION *session);
=head1 DESCRIPTION
Some engines are able to process multiple simultaneous crypto operations. This
capability could be utilised to parallelise the processing of a single
connection. For example a single write can be split into multiple records and
each one encrypted independently and in parallel. Note: this will only work in
TLS1.1+. There is no support in SSLv3, TLSv1.0 or DTLS (any version). This
capability is known as "pipelining" within OpenSSL.
In order to benefit from the pipelining capability. You need to have an engine
that provides ciphers that support this. The OpenSSL "dasync" engine provides
AES128-SHA based ciphers that have this capability. However these are for
development and test purposes only.
SSL_CTX_set_max_send_fragment() and SSL_set_max_send_fragment() set the
B<max_send_fragment> parameter for SSL_CTX and SSL objects respectively. This
value restricts the amount of plaintext bytes that will be sent in any one
SSL/TLS record. By default its value is SSL3_RT_MAX_PLAIN_LENGTH (16384). These
functions will only accept a value in the range 512 - SSL3_RT_MAX_PLAIN_LENGTH.
SSL_CTX_set_max_pipelines() and SSL_set_max_pipelines() set the maximum number
of pipelines that will be used at any one time. This value applies to both
"read" pipelining and "write" pipelining. By default only one pipeline will be
used (i.e. normal non-parallel operation). The number of pipelines set must be
in the range 1 - SSL_MAX_PIPELINES (32). Setting this to a value > 1 will also
automatically turn on "read_ahead" (see L<SSL_CTX_set_read_ahead(3)>). This is
explained further below. OpenSSL will only every use more than one pipeline if
a cipher suite is negotiated that uses a pipeline capable cipher provided by an
engine.
Pipelining operates slightly differently for reading encrypted data compared to
writing encrypted data. SSL_CTX_set_split_send_fragment() and
SSL_set_split_send_fragment() define how data is split up into pipelines when
writing encrypted data. The number of pipelines used will be determined by the
amount of data provided to the SSL_write_ex() or SSL_write() call divided by
B<split_send_fragment>.
For example if B<split_send_fragment> is set to 2000 and B<max_pipelines> is 4
then:
SSL_write/SSL_write_ex called with 0-2000 bytes == 1 pipeline used
SSL_write/SSL_write_ex called with 2001-4000 bytes == 2 pipelines used
SSL_write/SSL_write_ex called with 4001-6000 bytes == 3 pipelines used
SSL_write/SSL_write_ex called with 6001+ bytes == 4 pipelines used
B<split_send_fragment> must always be less than or equal to
B<max_send_fragment>. By default it is set to be equal to B<max_send_fragment>.
This will mean that the same number of records will always be created as would
have been created in the non-parallel case, although the data will be
apportioned differently. In the parallel case data will be spread equally
between the pipelines.
Read pipelining is controlled in a slightly different way than with write
pipelining. While reading we are constrained by the number of records that the
peer (and the network) can provide to us in one go. The more records we can get
in one go the more opportunity we have to parallelise the processing. As noted
above when setting B<max_pipelines> to a value greater than one, B<read_ahead>
is automatically set. The B<read_ahead> parameter causes OpenSSL to attempt to
read as much data into the read buffer as the network can provide and will fit
into the buffer. Without this set data is read into the read buffer one record
at a time. The more data that can be read, the more opportunity there is for
parallelising the processing at the cost of increased memory overhead per
connection. Setting B<read_ahead> can impact the behaviour of the SSL_pending()
function (see L<SSL_pending(3)>).
The SSL_CTX_set_default_read_buffer_len() and SSL_set_default_read_buffer_len()
functions control the size of the read buffer that will be used. The B<len>
parameter sets the size of the buffer. The value will only be used if it is
greater than the default that would have been used anyway. The normal default
value depends on a number of factors but it will be at least
SSL3_RT_MAX_PLAIN_LENGTH + SSL3_RT_MAX_ENCRYPTED_OVERHEAD (16704) bytes.
SSL_CTX_set_tlsext_max_fragment_length() sets the default maximum fragment
length negotiation mode via value B<mode> to B<ctx>.
This setting affects only SSL instances created after this function is called.
It affects the client-side as only its side may initiate this extension use.
SSL_set_tlsext_max_fragment_length() sets the maximum fragment length
negotiation mode via value B<mode> to B<ssl>.
This setting will be used during a handshake when extensions are exchanged
between client and server.
So it only affects SSL sessions created after this function is called.
It affects the client-side as only its side may initiate this extension use.
SSL_SESSION_get_max_fragment_length() gets the maximum fragment length
negotiated in B<session>.
=head1 RETURN VALUES
All non-void functions return 1 on success and 0 on failure.
=head1 NOTES
The Maximum Fragment Length extension support is optional on the server side.
If the server does not support this extension then
SSL_SESSION_get_max_fragment_length() will return:
TLSEXT_max_fragment_length_DISABLED.
The following modes are available:
=over 4
=item TLSEXT_max_fragment_length_DISABLED
Disables Maximum Fragment Length Negotiation (default).
=item TLSEXT_max_fragment_length_512
Sets Maximum Fragment Length to 512 bytes.
=item TLSEXT_max_fragment_length_1024
Sets Maximum Fragment Length to 1024.
=item TLSEXT_max_fragment_length_2048
Sets Maximum Fragment Length to 2048.
=item TLSEXT_max_fragment_length_4096
Sets Maximum Fragment Length to 4096.
=back
With the exception of SSL_CTX_set_default_read_buffer_len()
SSL_set_default_read_buffer_len(), SSL_CTX_set_tlsext_max_fragment_length(),
SSL_set_tlsext_max_fragment_length() and SSL_SESSION_get_max_fragment_length()
all these functions are implemented using macros.
+=head1 SEE ALSO
+
+L<SSL_CTX_set_read_ahead(3)>, L<SSL_pending(3)>
+
=head1 HISTORY
The SSL_CTX_set_max_pipelines(), SSL_set_max_pipelines(),
SSL_CTX_set_split_send_fragment(), SSL_set_split_send_fragment(),
SSL_CTX_set_default_read_buffer_len() and SSL_set_default_read_buffer_len()
functions were added in OpenSSL 1.1.0.
The SSL_CTX_set_tlsext_max_fragment_length(), SSL_set_tlsext_max_fragment_length()
and SSL_SESSION_get_max_fragment_length() functions were added in OpenSSL 1.1.1.
-=head1 SEE ALSO
-
-L<SSL_CTX_set_read_ahead(3)>, L<SSL_pending(3)>
-
=head1 COPYRIGHT
-Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod b/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
index 7a4bb3427027..43bddc51e8cf 100644
--- a/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
+++ b/doc/man3/SSL_CTX_set_tlsext_ticket_key_cb.pod
@@ -1,200 +1,200 @@
=pod
=head1 NAME
SSL_CTX_set_tlsext_ticket_key_cb - set a callback for session ticket processing
=head1 SYNOPSIS
#include <openssl/tls1.h>
long SSL_CTX_set_tlsext_ticket_key_cb(SSL_CTX sslctx,
int (*cb)(SSL *s, unsigned char key_name[16],
unsigned char iv[EVP_MAX_IV_LENGTH],
EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc));
=head1 DESCRIPTION
SSL_CTX_set_tlsext_ticket_key_cb() sets a callback function I<cb> for handling
session tickets for the ssl context I<sslctx>. Session tickets, defined in
RFC5077 provide an enhanced session resumption capability where the server
implementation is not required to maintain per session state. It only applies
to TLS and there is no SSLv3 implementation.
The callback function I<cb> will be called for every client instigated TLS
session when session ticket extension is presented in the TLS hello
message. It is the responsibility of this function to create or retrieve the
cryptographic parameters and to maintain their state.
The OpenSSL library uses your callback function to help implement a common TLS
ticket construction state according to RFC5077 Section 4 such that per session
state is unnecessary and a small set of cryptographic variables needs to be
maintained by the callback function implementation.
In order to reuse a session, a TLS client must send the a session ticket
extension to the server. The client can only send exactly one session ticket.
The server, through the callback function, either agrees to reuse the session
ticket information or it starts a full TLS handshake to create a new session
ticket.
Before the callback function is started I<ctx> and I<hctx> have been
initialised with L<EVP_CIPHER_CTX_reset(3)> and L<HMAC_CTX_reset(3)> respectively.
For new sessions tickets, when the client doesn't present a session ticket, or
an attempted retrieval of the ticket failed, or a renew option was indicated,
the callback function will be called with I<enc> equal to 1. The OpenSSL
library expects that the function will set an arbitrary I<name>, initialize
I<iv>, and set the cipher context I<ctx> and the hash context I<hctx>.
The I<name> is 16 characters long and is used as a key identifier.
The I<iv> length is the length of the IV of the corresponding cipher. The
maximum IV length is B<EVP_MAX_IV_LENGTH> bytes defined in B<evp.h>.
The initialization vector I<iv> should be a random value. The cipher context
I<ctx> should use the initialisation vector I<iv>. The cipher context can be
set using L<EVP_EncryptInit_ex(3)>. The hmac context can be set using
L<HMAC_Init_ex(3)>.
When the client presents a session ticket, the callback function with be called
with I<enc> set to 0 indicating that the I<cb> function should retrieve a set
of parameters. In this case I<name> and I<iv> have already been parsed out of
the session ticket. The OpenSSL library expects that the I<name> will be used
to retrieve a cryptographic parameters and that the cryptographic context
I<ctx> will be set with the retrieved parameters and the initialization vector
I<iv>. using a function like L<EVP_DecryptInit_ex(3)>. The I<hctx> needs to be
set using L<HMAC_Init_ex(3)>.
If the I<name> is still valid but a renewal of the ticket is required the
callback function should return 2. The library will call the callback again
with an argument of enc equal to 1 to set the new ticket.
The return value of the I<cb> function is used by OpenSSL to determine what
further processing will occur. The following return values have meaning:
=over 4
=item Z<>2
This indicates that the I<ctx> and I<hctx> have been set and the session can
continue on those parameters. Additionally it indicates that the session
ticket is in a renewal period and should be replaced. The OpenSSL library will
call I<cb> again with an enc argument of 1 to set the new ticket (see RFC5077
3.3 paragraph 2).
=item Z<>1
This indicates that the I<ctx> and I<hctx> have been set and the session can
continue on those parameters.
=item Z<>0
This indicates that it was not possible to set/retrieve a session ticket and
the SSL/TLS session will continue by negotiating a set of cryptographic
parameters or using the alternate SSL/TLS resumption mechanism, session ids.
If called with enc equal to 0 the library will call the I<cb> again to get
a new set of parameters.
=item less than 0
This indicates an error.
=back
=head1 NOTES
Session resumption shortcuts the TLS so that the client certificate
negotiation don't occur. It makes up for this by storing client certificate
an all other negotiated state information encrypted within the ticket. In a
resumed session the applications will have all this state information available
exactly as if a full negotiation had occurred.
If an attacker can obtain the key used to encrypt a session ticket, they can
obtain the master secret for any ticket using that key and decrypt any traffic
using that session: even if the cipher suite supports forward secrecy. As
a result applications may wish to use multiple keys and avoid using long term
keys stored in files.
Applications can use longer keys to maintain a consistent level of security.
For example if a cipher suite uses 256 bit ciphers but only a 128 bit ticket key
the overall security is only 128 bits because breaking the ticket key will
enable an attacker to obtain the session keys.
+=head1 RETURN VALUES
+
+returns 0 to indicate the callback function was set.
+
=head1 EXAMPLES
Reference Implementation:
SSL_CTX_set_tlsext_ticket_key_cb(SSL, ssl_tlsext_ticket_key_cb);
...
static int ssl_tlsext_ticket_key_cb(SSL *s, unsigned char key_name[16],
unsigned char *iv, EVP_CIPHER_CTX *ctx,
HMAC_CTX *hctx, int enc)
{
if (enc) { /* create new session */
if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) <= 0)
return -1; /* insufficient random */
key = currentkey(); /* something that you need to implement */
if (key == NULL) {
/* current key doesn't exist or isn't valid */
key = createkey(); /*
* Something that you need to implement.
* createkey needs to initialise a name,
* an aes_key, a hmac_key and optionally
* an expire time.
*/
if (key == NULL) /* key couldn't be created */
return 0;
}
memcpy(key_name, key->name, 16);
EVP_EncryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv);
HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL);
return 1;
} else { /* retrieve session */
key = findkey(name);
if (key == NULL || key->expire < now())
return 0;
HMAC_Init_ex(&hctx, key->hmac_key, 16, EVP_sha256(), NULL);
EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL, key->aes_key, iv);
if (key->expire < now() - RENEW_TIME) {
/*
* return 2 - This session will get a new ticket even though the
* current one is still valid.
*/
return 2;
}
return 1;
}
}
-=head1 RETURN VALUES
-
-returns 0 to indicate the callback function was set.
-
=head1 SEE ALSO
L<ssl(7)>, L<SSL_set_session(3)>,
L<SSL_session_reused(3)>,
L<SSL_CTX_add_session(3)>,
L<SSL_CTX_sess_number(3)>,
L<SSL_CTX_sess_set_get_cb(3)>,
L<SSL_CTX_set_session_id_context(3)>,
=head1 COPYRIGHT
-Copyright 2014-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2014-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_CTX_set_tmp_dh_callback.pod b/doc/man3/SSL_CTX_set_tmp_dh_callback.pod
index a2ac1c0adbbc..fba649f8f572 100644
--- a/doc/man3/SSL_CTX_set_tmp_dh_callback.pod
+++ b/doc/man3/SSL_CTX_set_tmp_dh_callback.pod
@@ -1,135 +1,135 @@
=pod
=head1 NAME
SSL_CTX_set_tmp_dh_callback, SSL_CTX_set_tmp_dh, SSL_set_tmp_dh_callback, SSL_set_tmp_dh - handle DH keys for ephemeral key exchange
=head1 SYNOPSIS
#include <openssl/ssl.h>
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
DH *(*tmp_dh_callback)(SSL *ssl, int is_export,
int keylength));
long SSL_CTX_set_tmp_dh(SSL_CTX *ctx, DH *dh);
void SSL_set_tmp_dh_callback(SSL *ctx,
DH *(*tmp_dh_callback)(SSL *ssl, int is_export,
int keylength));
long SSL_set_tmp_dh(SSL *ssl, DH *dh)
=head1 DESCRIPTION
SSL_CTX_set_tmp_dh_callback() sets the callback function for B<ctx> to be
used when a DH parameters are required to B<tmp_dh_callback>.
The callback is inherited by all B<ssl> objects created from B<ctx>.
SSL_CTX_set_tmp_dh() sets DH parameters to be used to be B<dh>.
The key is inherited by all B<ssl> objects created from B<ctx>.
SSL_set_tmp_dh_callback() sets the callback only for B<ssl>.
SSL_set_tmp_dh() sets the parameters only for B<ssl>.
These functions apply to SSL/TLS servers only.
=head1 NOTES
When using a cipher with RSA authentication, an ephemeral DH key exchange
can take place. Ciphers with DSA keys always use ephemeral DH keys as well.
In these cases, the session data are negotiated using the
ephemeral/temporary DH key and the key supplied and certified
by the certificate chain is only used for signing.
Anonymous ciphers (without a permanent server key) also use ephemeral DH keys.
Using ephemeral DH key exchange yields forward secrecy, as the connection
can only be decrypted, when the DH key is known. By generating a temporary
DH key inside the server application that is lost when the application
is left, it becomes impossible for an attacker to decrypt past sessions,
even if he gets hold of the normal (certified) key, as this key was
only used for signing.
In order to perform a DH key exchange the server must use a DH group
(DH parameters) and generate a DH key. The server will always generate
a new DH key during the negotiation.
As generating DH parameters is extremely time consuming, an application
should not generate the parameters on the fly but supply the parameters.
DH parameters can be reused, as the actual key is newly generated during
the negotiation. The risk in reusing DH parameters is that an attacker
may specialize on a very often used DH group. Applications should therefore
generate their own DH parameters during the installation process using the
openssl L<dhparam(1)> application. This application
guarantees that "strong" primes are used.
Files dh2048.pem, and dh4096.pem in the 'apps' directory of the current
version of the OpenSSL distribution contain the 'SKIP' DH parameters,
which use safe primes and were generated verifiably pseudo-randomly.
These files can be converted into C code using the B<-C> option of the
L<dhparam(1)> application. Generation of custom DH
parameters during installation should still be preferred to stop an
attacker from specializing on a commonly used group. File dh1024.pem
contains old parameters that must not be used by applications.
An application may either directly specify the DH parameters or
can supply the DH parameters via a callback function.
Previous versions of the callback used B<is_export> and B<keylength>
parameters to control parameter generation for export and non-export
cipher suites. Modern servers that do not support export cipher suites
are advised to either use SSL_CTX_set_tmp_dh() or alternatively, use
the callback but ignore B<keylength> and B<is_export> and simply
supply at least 2048-bit parameters in the callback.
+=head1 RETURN VALUES
+
+SSL_CTX_set_tmp_dh_callback() and SSL_set_tmp_dh_callback() do not return
+diagnostic output.
+
+SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() do return 1 on success and 0
+on failure. Check the error queue to find out the reason of failure.
+
=head1 EXAMPLES
Setup DH parameters with a key length of 2048 bits. (Error handling
partly left out.)
Command-line parameter generation:
$ openssl dhparam -out dh_param_2048.pem 2048
Code for setting up parameters during server initialization:
SSL_CTX ctx = SSL_CTX_new();
DH *dh_2048 = NULL;
FILE *paramfile = fopen("dh_param_2048.pem", "r");
if (paramfile) {
dh_2048 = PEM_read_DHparams(paramfile, NULL, NULL, NULL);
fclose(paramfile);
} else {
/* Error. */
}
if (dh_2048 == NULL)
/* Error. */
if (SSL_CTX_set_tmp_dh(ctx, dh_2048) != 1)
/* Error. */
...
-=head1 RETURN VALUES
-
-SSL_CTX_set_tmp_dh_callback() and SSL_set_tmp_dh_callback() do not return
-diagnostic output.
-
-SSL_CTX_set_tmp_dh() and SSL_set_tmp_dh() do return 1 on success and 0
-on failure. Check the error queue to find out the reason of failure.
-
=head1 SEE ALSO
L<ssl(7)>, L<SSL_CTX_set_cipher_list(3)>,
L<SSL_CTX_set_options(3)>,
L<ciphers(1)>, L<dhparam(1)>
=head1 COPYRIGHT
-Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_get_error.pod b/doc/man3/SSL_get_error.pod
index 5a7a4b7058ef..32668a036ddb 100644
--- a/doc/man3/SSL_get_error.pod
+++ b/doc/man3/SSL_get_error.pod
@@ -1,176 +1,176 @@
=pod
=head1 NAME
SSL_get_error - obtain result code for TLS/SSL I/O operation
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_get_error(const SSL *ssl, int ret);
=head1 DESCRIPTION
SSL_get_error() returns a result code (suitable for the C "switch"
statement) for a preceding call to SSL_connect(), SSL_accept(), SSL_do_handshake(),
SSL_read_ex(), SSL_read(), SSL_peek_ex(), SSL_peek(), SSL_write_ex() or
SSL_write() on B<ssl>. The value returned by that TLS/SSL I/O function must be
passed to SSL_get_error() in parameter B<ret>.
In addition to B<ssl> and B<ret>, SSL_get_error() inspects the
current thread's OpenSSL error queue. Thus, SSL_get_error() must be
used in the same thread that performed the TLS/SSL I/O operation, and no
other OpenSSL function calls should appear in between. The current
thread's error queue must be empty before the TLS/SSL I/O operation is
attempted, or SSL_get_error() will not work reliably.
=head1 RETURN VALUES
The following return values can currently occur:
=over 4
=item SSL_ERROR_NONE
The TLS/SSL I/O operation completed. This result code is returned
if and only if B<ret E<gt> 0>.
=item SSL_ERROR_ZERO_RETURN
The TLS/SSL peer has closed the connection for writing by sending the
close_notify alert.
No more data can be read.
Note that B<SSL_ERROR_ZERO_RETURN> does not necessarily
indicate that the underlying transport has been closed.
=item SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE
The operation did not complete and can be retried later.
B<SSL_ERROR_WANT_READ> is returned when the last operation was a read
operation from a non-blocking B<BIO>.
It means that not enough data was available at this time to complete the
operation.
If at a later time the underlying B<BIO> has data available for reading the same
function can be called again.
SSL_read() and SSL_read_ex() can also set B<SSL_ERROR_WANT_READ> when there is
still unprocessed data available at either the B<SSL> or the B<BIO> layer, even
for a blocking B<BIO>.
See L<SSL_read(3)> for more information.
B<SSL_ERROR_WANT_WRITE> is returned when the last operation was a write
to a non-blocking B<BIO> and it was unable to sent all data to the B<BIO>.
When the B<BIO> is writeable again, the same function can be called again.
Note that the retry may again lead to an B<SSL_ERROR_WANT_READ> or
B<SSL_ERROR_WANT_WRITE> condition.
There is no fixed upper limit for the number of iterations that
may be necessary until progress becomes visible at application
protocol level.
It is safe to call SSL_read() or SSL_read_ex() when more data is available
even when the call that set this error was an SSL_write() or SSL_write_ex().
However if the call was an SSL_write() or SSL_write_ex(), it should be called
again to continue sending the application data.
For socket B<BIO>s (e.g. when SSL_set_fd() was used), select() or
poll() on the underlying socket can be used to find out when the
TLS/SSL I/O function should be retried.
Caveat: Any TLS/SSL I/O function can lead to either of
B<SSL_ERROR_WANT_READ> and B<SSL_ERROR_WANT_WRITE>.
In particular,
SSL_read_ex(), SSL_read(), SSL_peek_ex(), or SSL_peek() may want to write data
and SSL_write() or SSL_write_ex() may want to read data.
This is mainly because
TLS/SSL handshakes may occur at any time during the protocol (initiated by
either the client or the server); SSL_read_ex(), SSL_read(), SSL_peek_ex(),
SSL_peek(), SSL_write_ex(), and SSL_write() will handle any pending handshakes.
=item SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT
The operation did not complete; the same TLS/SSL I/O function should be
called again later. The underlying BIO was not connected yet to the peer
and the call would block in connect()/accept(). The SSL function should be
called again when the connection is established. These messages can only
appear with a BIO_s_connect() or BIO_s_accept() BIO, respectively.
In order to find out, when the connection has been successfully established,
on many platforms select() or poll() for writing on the socket file descriptor
can be used.
=item SSL_ERROR_WANT_X509_LOOKUP
The operation did not complete because an application callback set by
SSL_CTX_set_client_cert_cb() has asked to be called again.
The TLS/SSL I/O function should be called again later.
Details depend on the application.
=item SSL_ERROR_WANT_ASYNC
The operation did not complete because an asynchronous engine is still
processing data. This will only occur if the mode has been set to SSL_MODE_ASYNC
using L<SSL_CTX_set_mode(3)> or L<SSL_set_mode(3)> and an asynchronous capable
engine is being used. An application can determine whether the engine has
completed its processing using select() or poll() on the asynchronous wait file
descriptor. This file descriptor is available by calling
L<SSL_get_all_async_fds(3)> or L<SSL_get_changed_async_fds(3)>. The TLS/SSL I/O
function should be called again later. The function B<must> be called from the
same thread that the original call was made from.
=item SSL_ERROR_WANT_ASYNC_JOB
The asynchronous job could not be started because there were no async jobs
available in the pool (see ASYNC_init_thread(3)). This will only occur if the
mode has been set to SSL_MODE_ASYNC using L<SSL_CTX_set_mode(3)> or
L<SSL_set_mode(3)> and a maximum limit has been set on the async job pool
through a call to L<ASYNC_init_thread(3)>. The application should retry the
operation after a currently executing asynchronous operation for the current
thread has completed.
=item SSL_ERROR_WANT_CLIENT_HELLO_CB
The operation did not complete because an application callback set by
SSL_CTX_set_client_hello_cb() has asked to be called again.
The TLS/SSL I/O function should be called again later.
Details depend on the application.
=item SSL_ERROR_SYSCALL
Some non-recoverable, fatal I/O error occurred. The OpenSSL error queue may
contain more information on the error. For socket I/O on Unix systems, consult
B<errno> for details. If this error occurs then no further I/O operations should
be performed on the connection and SSL_shutdown() must not be called.
This value can also be returned for other errors, check the error queue for
details.
=item SSL_ERROR_SSL
A non-recoverable, fatal error in the SSL library occurred, usually a protocol
error. The OpenSSL error queue contains more information on the error. If this
error occurs then no further I/O operations should be performed on the
connection and SSL_shutdown() must not be called.
=back
=head1 SEE ALSO
L<ssl(7)>
=head1 HISTORY
The SSL_ERROR_WANT_ASYNC error code was added in OpenSSL 1.1.0.
The SSL_ERROR_WANT_CLIENT_HELLO_CB error code was added in OpenSSL 1.1.1.
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_load_client_CA_file.pod b/doc/man3/SSL_load_client_CA_file.pod
index 412b1a098ca4..a6cfb308d30c 100644
--- a/doc/man3/SSL_load_client_CA_file.pod
+++ b/doc/man3/SSL_load_client_CA_file.pod
@@ -1,71 +1,71 @@
=pod
=head1 NAME
SSL_load_client_CA_file - load certificate names from file
=head1 SYNOPSIS
#include <openssl/ssl.h>
STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
=head1 DESCRIPTION
SSL_load_client_CA_file() reads certificates from B<file> and returns
a STACK_OF(X509_NAME) with the subject names found.
=head1 NOTES
SSL_load_client_CA_file() reads a file of PEM formatted certificates and
extracts the X509_NAMES of the certificates found. While the name suggests
the specific usage as support function for
L<SSL_CTX_set_client_CA_list(3)>,
it is not limited to CA certificates.
-=head1 EXAMPLES
-
-Load names of CAs from file and use it as a client CA list:
-
- SSL_CTX *ctx;
- STACK_OF(X509_NAME) *cert_names;
-
- ...
- cert_names = SSL_load_client_CA_file("/path/to/CAfile.pem");
- if (cert_names != NULL)
- SSL_CTX_set_client_CA_list(ctx, cert_names);
- else
- /* error */
- ...
-
=head1 RETURN VALUES
The following return values can occur:
=over 4
=item NULL
The operation failed, check out the error stack for the reason.
=item Pointer to STACK_OF(X509_NAME)
Pointer to the subject names of the successfully read certificates.
=back
+=head1 EXAMPLES
+
+Load names of CAs from file and use it as a client CA list:
+
+ SSL_CTX *ctx;
+ STACK_OF(X509_NAME) *cert_names;
+
+ ...
+ cert_names = SSL_load_client_CA_file("/path/to/CAfile.pem");
+ if (cert_names != NULL)
+ SSL_CTX_set_client_CA_list(ctx, cert_names);
+ else
+ /* error */
+ ...
+
=head1 SEE ALSO
L<ssl(7)>,
L<SSL_CTX_set_client_CA_list(3)>
=head1 COPYRIGHT
-Copyright 2000-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_read.pod b/doc/man3/SSL_read.pod
index 1410a0228c30..4da7ad1ae1f4 100644
--- a/doc/man3/SSL_read.pod
+++ b/doc/man3/SSL_read.pod
@@ -1,152 +1,152 @@
=pod
=head1 NAME
SSL_read_ex, SSL_read, SSL_peek_ex, SSL_peek
- read bytes from a TLS/SSL connection
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
int SSL_read(SSL *ssl, void *buf, int num);
int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
int SSL_peek(SSL *ssl, void *buf, int num);
=head1 DESCRIPTION
SSL_read_ex() and SSL_read() try to read B<num> bytes from the specified B<ssl>
into the buffer B<buf>. On success SSL_read_ex() will store the number of bytes
actually read in B<*readbytes>.
SSL_peek_ex() and SSL_peek() are identical to SSL_read_ex() and SSL_read()
respectively except no bytes are actually removed from the underlying BIO during
the read, so that a subsequent call to SSL_read_ex() or SSL_read() will yield
at least the same bytes.
=head1 NOTES
In the paragraphs below a "read function" is defined as one of SSL_read_ex(),
SSL_read(), SSL_peek_ex() or SSL_peek().
If necessary, a read function will negotiate a TLS/SSL session, if not already
explicitly performed by L<SSL_connect(3)> or L<SSL_accept(3)>. If the
peer requests a re-negotiation, it will be performed transparently during
the read function operation. The behaviour of the read functions depends on the
underlying BIO.
For the transparent negotiation to succeed, the B<ssl> must have been
initialized to client or server mode. This is being done by calling
L<SSL_set_connect_state(3)> or SSL_set_accept_state() before the first
invocation of a read function.
The read functions work based on the SSL/TLS records. The data are received in
records (with a maximum record size of 16kB). Only when a record has been
completely received, can it be processed (decryption and check of integrity).
Therefore data that was not retrieved at the last read call can still be
buffered inside the SSL layer and will be retrieved on the next read
call. If B<num> is higher than the number of bytes buffered then the read
functions will return with the bytes buffered. If no more bytes are in the
buffer, the read functions will trigger the processing of the next record.
Only when the record has been received and processed completely will the read
functions return reporting success. At most the contents of one record will
be returned. As the size of an SSL/TLS record may exceed the maximum packet size
of the underlying transport (e.g. TCP), it may be necessary to read several
packets from the transport layer before the record is complete and the read call
can succeed.
If B<SSL_MODE_AUTO_RETRY> has been switched off and a non-application data
record has been processed, the read function can return and set the error to
B<SSL_ERROR_WANT_READ>.
In this case there might still be unprocessed data available in the B<BIO>.
If read ahead was set using L<SSL_CTX_set_read_ahead(3)>, there might also still
be unprocessed data available in the B<SSL>.
This behaviour can be controlled using the L<SSL_CTX_set_mode(3)> call.
If the underlying BIO is B<blocking>, a read function will only return once the
read operation has been finished or an error occurred, except when a
non-application data record has been processed and B<SSL_MODE_AUTO_RETRY> is
not set.
Note that if B<SSL_MODE_AUTO_RETRY> is set and only non-application data is
available the call will hang.
If the underlying BIO is B<non-blocking>, a read function will also return when
the underlying BIO could not satisfy the needs of the function to continue the
operation.
In this case a call to L<SSL_get_error(3)> with the
return value of the read function will yield B<SSL_ERROR_WANT_READ> or
B<SSL_ERROR_WANT_WRITE>.
As at any time it's possible that non-application data needs to be sent,
a read function can also cause write operations.
The calling process then must repeat the call after taking appropriate action
to satisfy the needs of the read function.
The action depends on the underlying BIO.
When using a non-blocking socket, nothing is to be done, but select() can be
used to check for the required condition.
When using a buffering BIO, like a BIO pair, data must be written into or
retrieved out of the BIO before being able to continue.
L<SSL_pending(3)> can be used to find out whether there
are buffered bytes available for immediate retrieval.
In this case the read function can be called without blocking or actually
receiving new data from the underlying socket.
=head1 RETURN VALUES
SSL_read_ex() and SSL_peek_ex() will return 1 for success or 0 for failure.
Success means that 1 or more application data bytes have been read from the SSL
connection.
Failure means that no bytes could be read from the SSL connection.
Failures can be retryable (e.g. we are waiting for more bytes to
be delivered by the network) or non-retryable (e.g. a fatal network error).
In the event of a failure call L<SSL_get_error(3)> to find out the reason which
indicates whether the call is retryable or not.
For SSL_read() and SSL_peek() the following return values can occur:
=over 4
=item E<gt> 0
The read operation was successful.
The return value is the number of bytes actually read from the TLS/SSL
connection.
=item Z<><= 0
The read operation was not successful, because either the connection was closed,
an error occurred or action must be taken by the calling process.
Call L<SSL_get_error(3)> with the return value B<ret> to find out the reason.
Old documentation indicated a difference between 0 and -1, and that -1 was
retryable.
You should instead call SSL_get_error() to find out if it's retryable.
=back
-=head1 HISTORY
-
-The SSL_read_ex() and SSL_peek_ex() functions were added in OpenSSL 1.1.1.
-
=head1 SEE ALSO
L<SSL_get_error(3)>, L<SSL_write_ex(3)>,
L<SSL_CTX_set_mode(3)>, L<SSL_CTX_new(3)>,
L<SSL_connect(3)>, L<SSL_accept(3)>
L<SSL_set_connect_state(3)>,
L<SSL_pending(3)>,
L<SSL_shutdown(3)>, L<SSL_set_shutdown(3)>,
L<ssl(7)>, L<bio(7)>
+=head1 HISTORY
+
+The SSL_read_ex() and SSL_peek_ex() functions were added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_session_reused.pod b/doc/man3/SSL_session_reused.pod
index 1a3d567bd844..82c59435901a 100644
--- a/doc/man3/SSL_session_reused.pod
+++ b/doc/man3/SSL_session_reused.pod
@@ -1,54 +1,54 @@
=pod
=head1 NAME
SSL_session_reused - query whether a reused session was negotiated during handshake
=head1 SYNOPSIS
#include <openssl/ssl.h>
- int SSL_session_reused(SSL *ssl);
+ int SSL_session_reused(const SSL *ssl);
=head1 DESCRIPTION
Query, whether a reused session was negotiated during the handshake.
=head1 NOTES
During the negotiation, a client can propose to reuse a session. The server
then looks up the session in its cache. If both client and server agree
on the session, it will be reused and a flag is being set that can be
queried by the application.
=head1 RETURN VALUES
The following return values can occur:
=over 4
=item Z<>0
A new session was negotiated.
=item Z<>1
A session was reused.
=back
=head1 SEE ALSO
L<ssl(7)>, L<SSL_set_session(3)>,
L<SSL_CTX_set_session_cache_mode(3)>
=head1 COPYRIGHT
-Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2001-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_shutdown.pod b/doc/man3/SSL_shutdown.pod
index 551fff6308b6..732e5ada04ae 100644
--- a/doc/man3/SSL_shutdown.pod
+++ b/doc/man3/SSL_shutdown.pod
@@ -1,167 +1,167 @@
=pod
=head1 NAME
SSL_shutdown - shut down a TLS/SSL connection
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_shutdown(SSL *ssl);
=head1 DESCRIPTION
SSL_shutdown() shuts down an active TLS/SSL connection. It sends the
close_notify shutdown alert to the peer.
=head1 NOTES
SSL_shutdown() tries to send the close_notify shutdown alert to the peer.
Whether the operation succeeds or not, the SSL_SENT_SHUTDOWN flag is set and
a currently open session is considered closed and good and will be kept in the
session cache for further reuse.
Note that SSL_shutdown() must not be called if a previous fatal error has
occurred on a connection i.e. if SSL_get_error() has returned SSL_ERROR_SYSCALL
or SSL_ERROR_SSL.
The shutdown procedure consists of two steps: sending of the close_notify
shutdown alert, and reception of the peer's close_notify shutdown alert.
The order of those two steps depends on the application.
It is acceptable for an application to only send its shutdown alert and
then close the underlying connection without waiting for the peer's response.
This way resources can be saved, as the process can already terminate or
serve another connection.
This should only be done when it is known that the other side will not send more
data, otherwise there is a risk of a truncation attack.
When a client only writes and never reads from the connection, and the server
has sent a session ticket to establish a session, the client might not be able
to resume the session because it did not received and process the session ticket
from the server.
In case the application wants to be able to resume the session, it is recommended to
do a complete shutdown procedure (bidirectional close_notify alerts).
When the underlying connection shall be used for more communications, the
complete shutdown procedure must be performed, so that the peers stay
synchronized.
SSL_shutdown() only closes the write direction.
It is not possible to call SSL_write() after calling SSL_shutdown().
The read direction is closed by the peer.
=head2 First to close the connection
When the application is the first party to send the close_notify
alert, SSL_shutdown() will only send the alert and then set the
SSL_SENT_SHUTDOWN flag (so that the session is considered good and will
be kept in the cache).
If successful, SSL_shutdown() will return 0.
If a unidirectional shutdown is enough (the underlying connection shall be
closed anyway), this first successful call to SSL_shutdown() is sufficient.
In order to complete the bidirectional shutdown handshake, the peer needs
to send back a close_notify alert.
The SSL_RECEIVED_SHUTDOWN flag will be set after receiving and processing
it.
The peer is still allowed to send data after receiving the close_notify
event.
When it is done sending data, it will send the close_notify alert.
SSL_read() should be called until all data is received.
SSL_read() will indicate the end of the peer data by returning <= 0
and SSL_get_error() returning SSL_ERROR_ZERO_RETURN.
=head2 Peer closes the connection
If the peer already sent the close_notify alert B<and> it was
already processed implicitly inside another function
(L<SSL_read(3)>), the SSL_RECEIVED_SHUTDOWN flag is set.
SSL_read() will return <= 0 in that case, and SSL_get_error() will return
SSL_ERROR_ZERO_RETURN.
SSL_shutdown() will send the close_notify alert, set the SSL_SENT_SHUTDOWN
flag.
If successful, SSL_shutdown() will return 1.
Whether SSL_RECEIVED_SHUTDOWN is already set can be checked using the
SSL_get_shutdown() (see also L<SSL_set_shutdown(3)> call.
=head1 NOTES
The behaviour of SSL_shutdown() additionally depends on the underlying BIO.
If the underlying BIO is B<blocking>, SSL_shutdown() will only return once the
handshake step has been finished or an error occurred.
If the underlying BIO is B<non-blocking>, SSL_shutdown() will also return
when the underlying BIO could not satisfy the needs of SSL_shutdown()
to continue the handshake. In this case a call to SSL_get_error() with the
return value of SSL_shutdown() will yield B<SSL_ERROR_WANT_READ> or
B<SSL_ERROR_WANT_WRITE>. The calling process then must repeat the call after
taking appropriate action to satisfy the needs of SSL_shutdown().
The action depends on the underlying BIO. When using a non-blocking socket,
nothing is to be done, but select() can be used to check for the required
condition. When using a buffering BIO, like a BIO pair, data must be written
into or retrieved out of the BIO before being able to continue.
After SSL_shutdown() returned 0, it is possible to call SSL_shutdown() again
to wait for the peer's close_notify alert.
SSL_shutdown() will return 1 in that case.
However, it is recommended to wait for it using SSL_read() instead.
SSL_shutdown() can be modified to only set the connection to "shutdown"
state but not actually send the close_notify alert messages,
see L<SSL_CTX_set_quiet_shutdown(3)>.
When "quiet shutdown" is enabled, SSL_shutdown() will always succeed
and return 1.
=head1 RETURN VALUES
The following return values can occur:
=over 4
=item Z<>0
The shutdown is not yet finished: the close_notify was sent but the peer
did not send it back yet.
Call SSL_read() to do a bidirectional shutdown.
The output of L<SSL_get_error(3)> may be misleading, as an
erroneous SSL_ERROR_SYSCALL may be flagged even though no error occurred.
=item Z<>1
The shutdown was successfully completed. The close_notify alert was sent
and the peer's close_notify alert was received.
=item E<lt>0
The shutdown was not successful.
Call L<SSL_get_error(3)> with the return value B<ret> to find out the reason.
It can occur if an action is needed to continue the operation for non-blocking
BIOs.
It can also occur when not all data was read using SSL_read().
=back
=head1 SEE ALSO
L<SSL_get_error(3)>, L<SSL_connect(3)>,
L<SSL_accept(3)>, L<SSL_set_shutdown(3)>,
L<SSL_CTX_set_quiet_shutdown(3)>,
L<SSL_clear(3)>, L<SSL_free(3)>,
L<ssl(7)>, L<bio(7)>
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/SSL_write.pod b/doc/man3/SSL_write.pod
index 3956f1def387..84eb948cc6eb 100644
--- a/doc/man3/SSL_write.pod
+++ b/doc/man3/SSL_write.pod
@@ -1,128 +1,128 @@
=pod
=head1 NAME
SSL_write_ex, SSL_write - write bytes to a TLS/SSL connection
=head1 SYNOPSIS
#include <openssl/ssl.h>
int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
int SSL_write(SSL *ssl, const void *buf, int num);
=head1 DESCRIPTION
SSL_write_ex() and SSL_write() write B<num> bytes from the buffer B<buf> into
the specified B<ssl> connection. On success SSL_write_ex() will store the number
of bytes written in B<*written>.
=head1 NOTES
In the paragraphs below a "write function" is defined as one of either
SSL_write_ex(), or SSL_write().
If necessary, a write function will negotiate a TLS/SSL session, if not already
explicitly performed by L<SSL_connect(3)> or L<SSL_accept(3)>. If the peer
requests a re-negotiation, it will be performed transparently during
the write function operation. The behaviour of the write functions depends on the
underlying BIO.
For the transparent negotiation to succeed, the B<ssl> must have been
initialized to client or server mode. This is being done by calling
L<SSL_set_connect_state(3)> or SSL_set_accept_state()
before the first call to a write function.
If the underlying BIO is B<blocking>, the write functions will only return, once
the write operation has been finished or an error occurred.
If the underlying BIO is B<non-blocking> the write functions will also return
when the underlying BIO could not satisfy the needs of the function to continue
the operation. In this case a call to L<SSL_get_error(3)> with the
return value of the write function will yield B<SSL_ERROR_WANT_READ>
or B<SSL_ERROR_WANT_WRITE>. As at any time a re-negotiation is possible, a
call to a write function can also cause read operations! The calling process
then must repeat the call after taking appropriate action to satisfy the needs
of the write function. The action depends on the underlying BIO. When using a
non-blocking socket, nothing is to be done, but select() can be used to check
for the required condition. When using a buffering BIO, like a BIO pair, data
must be written into or retrieved out of the BIO before being able to continue.
The write functions will only return with success when the complete contents of
B<buf> of length B<num> has been written. This default behaviour can be changed
with the SSL_MODE_ENABLE_PARTIAL_WRITE option of L<SSL_CTX_set_mode(3)>. When
this flag is set the write functions will also return with success when a
partial write has been successfully completed. In this case the write function
operation is considered completed. The bytes are sent and a new write call with
a new buffer (with the already sent bytes removed) must be started. A partial
write is performed with the size of a message block, which is 16kB.
=head1 WARNING
When a write function call has to be repeated because L<SSL_get_error(3)>
returned B<SSL_ERROR_WANT_READ> or B<SSL_ERROR_WANT_WRITE>, it must be repeated
with the same arguments.
The data that was passed might have been partially processed.
When B<SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER> was set using L<SSL_CTX_set_mode(3)>
the pointer can be different, but the data and length should still be the same.
You should not call SSL_write() with num=0, it will return an error.
SSL_write_ex() can be called with num=0, but will not send application data to
the peer.
=head1 RETURN VALUES
SSL_write_ex() will return 1 for success or 0 for failure. Success means that
all requested application data bytes have been written to the SSL connection or,
if SSL_MODE_ENABLE_PARTIAL_WRITE is in use, at least 1 application data byte has
been written to the SSL connection. Failure means that not all the requested
bytes have been written yet (if SSL_MODE_ENABLE_PARTIAL_WRITE is not in use) or
no bytes could be written to the SSL connection (if
SSL_MODE_ENABLE_PARTIAL_WRITE is in use). Failures can be retryable (e.g. the
network write buffer has temporarily filled up) or non-retryable (e.g. a fatal
network error). In the event of a failure call L<SSL_get_error(3)> to find out
the reason which indicates whether the call is retryable or not.
For SSL_write() the following return values can occur:
=over 4
=item E<gt> 0
The write operation was successful, the return value is the number of
bytes actually written to the TLS/SSL connection.
=item Z<><= 0
The write operation was not successful, because either the connection was
closed, an error occurred or action must be taken by the calling process.
Call SSL_get_error() with the return value B<ret> to find out the reason.
Old documentation indicated a difference between 0 and -1, and that -1 was
retryable.
You should instead call SSL_get_error() to find out if it's retryable.
=back
-=head1 HISTORY
-
-The SSL_write_ex() function was added in OpenSSL 1.1.1.
-
=head1 SEE ALSO
L<SSL_get_error(3)>, L<SSL_read_ex(3)>, L<SSL_read(3)>
L<SSL_CTX_set_mode(3)>, L<SSL_CTX_new(3)>,
L<SSL_connect(3)>, L<SSL_accept(3)>
L<SSL_set_connect_state(3)>,
L<ssl(7)>, L<bio(7)>
+=head1 HISTORY
+
+The SSL_write_ex() function was added in OpenSSL 1.1.1.
+
=head1 COPYRIGHT
-Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/X509_LOOKUP_meth_new.pod b/doc/man3/X509_LOOKUP_meth_new.pod
index fb165fd6ad9d..e5f0a098b3fa 100644
--- a/doc/man3/X509_LOOKUP_meth_new.pod
+++ b/doc/man3/X509_LOOKUP_meth_new.pod
@@ -1,189 +1,199 @@
=pod
=head1 NAME
X509_LOOKUP_meth_new, X509_LOOKUP_meth_free, X509_LOOKUP_meth_set_new_item,
X509_LOOKUP_meth_get_new_item, X509_LOOKUP_meth_set_free,
X509_LOOKUP_meth_get_free, X509_LOOKUP_meth_set_init,
X509_LOOKUP_meth_get_init, X509_LOOKUP_meth_set_shutdown,
X509_LOOKUP_meth_get_shutdown,
X509_LOOKUP_ctrl_fn, X509_LOOKUP_meth_set_ctrl, X509_LOOKUP_meth_get_ctrl,
X509_LOOKUP_get_by_subject_fn, X509_LOOKUP_meth_set_get_by_subject,
X509_LOOKUP_meth_get_get_by_subject,
X509_LOOKUP_get_by_issuer_serial_fn, X509_LOOKUP_meth_set_get_by_issuer_serial,
X509_LOOKUP_meth_get_get_by_issuer_serial,
X509_LOOKUP_get_by_fingerprint_fn, X509_LOOKUP_meth_set_get_by_fingerprint,
X509_LOOKUP_meth_get_get_by_fingerprint,
X509_LOOKUP_get_by_alias_fn, X509_LOOKUP_meth_set_get_by_alias,
X509_LOOKUP_meth_get_get_by_alias,
X509_LOOKUP_set_method_data, X509_LOOKUP_get_method_data,
X509_LOOKUP_get_store, X509_OBJECT_set1_X509, X509_OBJECT_set1_X509_CRL
- Routines to build up X509_LOOKUP methods
=head1 SYNOPSIS
#include <openssl/x509_vfy.h>
X509_LOOKUP_METHOD *X509_LOOKUP_meth_new(const char *name);
void X509_LOOKUP_meth_free(X509_LOOKUP_METHOD *method);
int X509_LOOKUP_meth_set_new_item(X509_LOOKUP_METHOD *method,
int (*new_item) (X509_LOOKUP *ctx));
int (*X509_LOOKUP_meth_get_new_item(const X509_LOOKUP_METHOD* method))
(X509_LOOKUP *ctx);
int X509_LOOKUP_meth_set_free(X509_LOOKUP_METHOD *method,
void (*free) (X509_LOOKUP *ctx));
void (*X509_LOOKUP_meth_get_free(const X509_LOOKUP_METHOD* method))
(X509_LOOKUP *ctx);
int X509_LOOKUP_meth_set_init(X509_LOOKUP_METHOD *method,
int (*init) (X509_LOOKUP *ctx));
int (*X509_LOOKUP_meth_get_init(const X509_LOOKUP_METHOD* method))
(X509_LOOKUP *ctx);
int X509_LOOKUP_meth_set_shutdown(X509_LOOKUP_METHOD *method,
int (*shutdown) (X509_LOOKUP *ctx));
int (*X509_LOOKUP_meth_get_shutdown(const X509_LOOKUP_METHOD* method))
(X509_LOOKUP *ctx);
typedef int (*X509_LOOKUP_ctrl_fn)(X509_LOOKUP *ctx, int cmd, const char *argc,
long argl, char **ret);
int X509_LOOKUP_meth_set_ctrl(X509_LOOKUP_METHOD *method,
X509_LOOKUP_ctrl_fn ctrl_fn);
X509_LOOKUP_ctrl_fn X509_LOOKUP_meth_get_ctrl(const X509_LOOKUP_METHOD *method);
typedef int (*X509_LOOKUP_get_by_subject_fn)(X509_LOOKUP *ctx,
X509_LOOKUP_TYPE type,
X509_NAME *name,
X509_OBJECT *ret);
int X509_LOOKUP_meth_set_get_by_subject(X509_LOOKUP_METHOD *method,
X509_LOOKUP_get_by_subject_fn fn);
X509_LOOKUP_get_by_subject_fn X509_LOOKUP_meth_get_get_by_subject(
const X509_LOOKUP_METHOD *method);
typedef int (*X509_LOOKUP_get_by_issuer_serial_fn)(X509_LOOKUP *ctx,
X509_LOOKUP_TYPE type,
X509_NAME *name,
ASN1_INTEGER *serial,
X509_OBJECT *ret);
int X509_LOOKUP_meth_set_get_by_issuer_serial(
X509_LOOKUP_METHOD *method, X509_LOOKUP_get_by_issuer_serial_fn fn);
X509_LOOKUP_get_by_issuer_serial_fn X509_LOOKUP_meth_get_get_by_issuer_serial(
const X509_LOOKUP_METHOD *method);
typedef int (*X509_LOOKUP_get_by_fingerprint_fn)(X509_LOOKUP *ctx,
X509_LOOKUP_TYPE type,
const unsigned char* bytes,
int len,
X509_OBJECT *ret);
int X509_LOOKUP_meth_set_get_by_fingerprint(X509_LOOKUP_METHOD *method,
X509_LOOKUP_get_by_fingerprint_fn fn);
X509_LOOKUP_get_by_fingerprint_fn X509_LOOKUP_meth_get_get_by_fingerprint(
const X509_LOOKUP_METHOD *method);
typedef int (*X509_LOOKUP_get_by_alias_fn)(X509_LOOKUP *ctx,
X509_LOOKUP_TYPE type,
const char *str,
int len,
X509_OBJECT *ret);
int X509_LOOKUP_meth_set_get_by_alias(X509_LOOKUP_METHOD *method,
X509_LOOKUP_get_by_alias_fn fn);
X509_LOOKUP_get_by_alias_fn X509_LOOKUP_meth_get_get_by_alias(
const X509_LOOKUP_METHOD *method);
int X509_LOOKUP_set_method_data(X509_LOOKUP *ctx, void *data);
void *X509_LOOKUP_get_method_data(const X509_LOOKUP *ctx);
X509_STORE *X509_LOOKUP_get_store(const X509_LOOKUP *ctx);
int X509_OBJECT_set1_X509(X509_OBJECT *a, X509 *obj);
int X509_OBJECT_set1_X509_CRL(X509_OBJECT *a, X509_CRL *obj);
=head1 DESCRIPTION
The B<X509_LOOKUP_METHOD> type is a structure used for the implementation of new
X509_LOOKUP types. It provides a set of functions used by OpenSSL for the
implementation of various X509 and X509_CRL lookup capabilities. One instance
of an X509_LOOKUP_METHOD can be associated to many instantiations of an
B<X509_LOOKUP> structure.
X509_LOOKUP_meth_new() creates a new B<X509_LOOKUP_METHOD> structure. It should
be given a human-readable string containing a brief description of the lookup
method.
X509_LOOKUP_meth_free() destroys a B<X509_LOOKUP_METHOD> structure.
X509_LOOKUP_get_new_item() and X509_LOOKUP_set_new_item() get and set the
function that is called when an B<X509_LOOKUP> object is created with
X509_LOOKUP_new(). If an X509_LOOKUP_METHOD requires any per-X509_LOOKUP
specific data, the supplied new_item function should allocate this data and
invoke X509_LOOKUP_set_method_data().
X509_LOOKUP_get_free() and X509_LOOKUP_set_free() get and set the function
that is used to free any method data that was allocated and set from within
new_item function.
X509_LOOKUP_meth_get_init() and X509_LOOKUP_meth_set_init() get and set the
function that is used to initialize the method data that was set with
X509_LOOKUP_set_method_data() as part of the new_item routine.
X509_LOOKUP_meth_get_shutdown() and X509_LOOKUP_meth_set_shutdown() get and set
the function that is used to shut down the method data whose state was
previously initialized in the init function.
X509_LOOKUP_meth_get_ctrl() and X509_LOOKUP_meth_set_ctrl() get and set a
function to be used to handle arbitrary control commands issued by
X509_LOOKUP_ctrl(). The control function is given the X509_LOOKUP
B<ctx>, along with the arguments passed by X509_LOOKUP_ctrl. B<cmd> is
an arbitrary integer that defines some operation. B<argc> is a pointer
to an array of characters. B<argl> is an integer. B<ret>, if set,
points to a location where any return data should be written to. How
B<argc> and B<argl> are used depends entirely on the control function.
X509_LOOKUP_set_get_by_subject(), X509_LOOKUP_set_get_by_issuer_serial(),
X509_LOOKUP_set_get_by_fingerprint(), X509_LOOKUP_set_get_by_alias() set
the functions used to retrieve an X509 or X509_CRL object by the object's
subject, issuer, fingerprint, and alias respectively. These functions are given
the X509_LOOKUP context, the type of the X509_OBJECT being requested, parameters
related to the lookup, and an X509_OBJECT that will receive the requested
object.
-Implementations should use either X509_OBJECT_set1_X509() or
-X509_OBJECT_set1_X509_CRL() to set the result. Any method data that was
-created as a result of the new_item function set by
-X509_LOOKUP_meth_set_new_item() can be accessed with
+Implementations must add objects they find to the B<X509_STORE> object
+using X509_STORE_add_cert() or X509_STORE_add_crl(). This increments
+its reference count. However, the X509_STORE_CTX_get_by_subject()
+function also increases the reference count which leads to one too
+many references being held. Therefore applications should
+additionally call X509_free() or X509_CRL_free() to decrement the
+reference count again.
+
+Implementations should also use either X509_OBJECT_set1_X509() or
+X509_OBJECT_set1_X509_CRL() to set the result. Note that this also
+increments the result's reference count.
+
+Any method data that was created as a result of the new_item function
+set by X509_LOOKUP_meth_set_new_item() can be accessed with
X509_LOOKUP_get_method_data(). The B<X509_STORE> object that owns the
X509_LOOKUP may be accessed with X509_LOOKUP_get_store(). Successful lookups
should return 1, and unsuccessful lookups should return 0.
X509_LOOKUP_get_get_by_subject(), X509_LOOKUP_get_get_by_issuer_serial(),
X509_LOOKUP_get_get_by_fingerprint(), X509_LOOKUP_get_get_by_alias() retrieve
the function set by the corresponding setter.
=head1 RETURN VALUES
The B<X509_LOOKUP_meth_set> functions return 1 on success or 0 on error.
The B<X509_LOOKUP_meth_get> functions return the corresponding function
pointers.
=head1 SEE ALSO
L<X509_STORE_new(3)>, L<SSL_CTX_set_cert_store(3)>
=head1 HISTORY
The functions described here were added in OpenSSL 1.1.0i.
=head1 COPYRIGHT
-Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/X509_NAME_add_entry_by_txt.pod b/doc/man3/X509_NAME_add_entry_by_txt.pod
index b48f0908e813..0459cf4a4655 100644
--- a/doc/man3/X509_NAME_add_entry_by_txt.pod
+++ b/doc/man3/X509_NAME_add_entry_by_txt.pod
@@ -1,127 +1,127 @@
=pod
=head1 NAME
X509_NAME_add_entry_by_txt, X509_NAME_add_entry_by_OBJ, X509_NAME_add_entry_by_NID,
X509_NAME_add_entry, X509_NAME_delete_entry - X509_NAME modification functions
=head1 SYNOPSIS
#include <openssl/x509.h>
int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
const unsigned char *bytes, int len, int loc, int set);
int X509_NAME_add_entry_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int type,
const unsigned char *bytes, int len, int loc, int set);
int X509_NAME_add_entry_by_NID(X509_NAME *name, int nid, int type,
const unsigned char *bytes, int len, int loc, int set);
int X509_NAME_add_entry(X509_NAME *name, const X509_NAME_ENTRY *ne, int loc, int set);
X509_NAME_ENTRY *X509_NAME_delete_entry(X509_NAME *name, int loc);
=head1 DESCRIPTION
X509_NAME_add_entry_by_txt(), X509_NAME_add_entry_by_OBJ() and
X509_NAME_add_entry_by_NID() add a field whose name is defined
by a string B<field>, an object B<obj> or a NID B<nid> respectively.
The field value to be added is in B<bytes> of length B<len>. If
B<len> is -1 then the field length is calculated internally using
strlen(bytes).
The type of field is determined by B<type> which can either be a
definition of the type of B<bytes> (such as B<MBSTRING_ASC>) or a
standard ASN1 type (such as B<V_ASN1_IA5STRING>). The new entry is
added to a position determined by B<loc> and B<set>.
X509_NAME_add_entry() adds a copy of B<X509_NAME_ENTRY> structure B<ne>
to B<name>. The new entry is added to a position determined by B<loc>
and B<set>. Since a copy of B<ne> is added B<ne> must be freed up after
the call.
X509_NAME_delete_entry() deletes an entry from B<name> at position
B<loc>. The deleted entry is returned and must be freed up.
=head1 NOTES
The use of string types such as B<MBSTRING_ASC> or B<MBSTRING_UTF8>
is strongly recommended for the B<type> parameter. This allows the
internal code to correctly determine the type of the field and to
apply length checks according to the relevant standards. This is
done using ASN1_STRING_set_by_NID().
If instead an ASN1 type is used no checks are performed and the
supplied data in B<bytes> is used directly.
In X509_NAME_add_entry_by_txt() the B<field> string represents
the field name using OBJ_txt2obj(field, 0).
The B<loc> and B<set> parameters determine where a new entry should
be added. For almost all applications B<loc> can be set to -1 and B<set>
to 0. This adds a new entry to the end of B<name> as a single valued
RelativeDistinguishedName (RDN).
B<loc> actually determines the index where the new entry is inserted:
if it is -1 it is appended.
B<set> determines how the new type is added. If it is zero a
new RDN is created.
If B<set> is -1 or 1 it is added to the previous or next RDN
structure respectively. This will then be a multivalued RDN:
since multivalues RDNs are very seldom used B<set> is almost
always set to zero.
+=head1 RETURN VALUES
+
+X509_NAME_add_entry_by_txt(), X509_NAME_add_entry_by_OBJ(),
+X509_NAME_add_entry_by_NID() and X509_NAME_add_entry() return 1 for
+success of 0 if an error occurred.
+
+X509_NAME_delete_entry() returns either the deleted B<X509_NAME_ENTRY>
+structure of B<NULL> if an error occurred.
+
=head1 EXAMPLES
Create an B<X509_NAME> structure:
"C=UK, O=Disorganized Organization, CN=Joe Bloggs"
X509_NAME *nm;
nm = X509_NAME_new();
if (nm == NULL)
/* Some error */
if (!X509_NAME_add_entry_by_txt(nm, "C", MBSTRING_ASC,
"UK", -1, -1, 0))
/* Error */
if (!X509_NAME_add_entry_by_txt(nm, "O", MBSTRING_ASC,
"Disorganized Organization", -1, -1, 0))
/* Error */
if (!X509_NAME_add_entry_by_txt(nm, "CN", MBSTRING_ASC,
"Joe Bloggs", -1, -1, 0))
/* Error */
-=head1 RETURN VALUES
-
-X509_NAME_add_entry_by_txt(), X509_NAME_add_entry_by_OBJ(),
-X509_NAME_add_entry_by_NID() and X509_NAME_add_entry() return 1 for
-success of 0 if an error occurred.
-
-X509_NAME_delete_entry() returns either the deleted B<X509_NAME_ENTRY>
-structure of B<NULL> if an error occurred.
-
=head1 BUGS
B<type> can still be set to B<V_ASN1_APP_CHOOSE> to use a
different algorithm to determine field types. Since this form does
not understand multicharacter types, performs no length checks and
can result in invalid field types its use is strongly discouraged.
=head1 SEE ALSO
L<ERR_get_error(3)>, L<d2i_X509_NAME(3)>
=head1 COPYRIGHT
-Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/X509_NAME_get_index_by_NID.pod b/doc/man3/X509_NAME_get_index_by_NID.pod
index 5621806bb530..420ace134874 100644
--- a/doc/man3/X509_NAME_get_index_by_NID.pod
+++ b/doc/man3/X509_NAME_get_index_by_NID.pod
@@ -1,122 +1,122 @@
=pod
=head1 NAME
X509_NAME_get_index_by_NID, X509_NAME_get_index_by_OBJ, X509_NAME_get_entry,
X509_NAME_entry_count, X509_NAME_get_text_by_NID, X509_NAME_get_text_by_OBJ -
X509_NAME lookup and enumeration functions
=head1 SYNOPSIS
#include <openssl/x509.h>
int X509_NAME_get_index_by_NID(X509_NAME *name, int nid, int lastpos);
int X509_NAME_get_index_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, int lastpos);
int X509_NAME_entry_count(const X509_NAME *name);
X509_NAME_ENTRY *X509_NAME_get_entry(const X509_NAME *name, int loc);
int X509_NAME_get_text_by_NID(X509_NAME *name, int nid, char *buf, int len);
int X509_NAME_get_text_by_OBJ(X509_NAME *name, const ASN1_OBJECT *obj, char *buf, int len);
=head1 DESCRIPTION
These functions allow an B<X509_NAME> structure to be examined. The
B<X509_NAME> structure is the same as the B<Name> type defined in
RFC2459 (and elsewhere) and used for example in certificate subject
and issuer names.
X509_NAME_get_index_by_NID() and X509_NAME_get_index_by_OBJ() retrieve
the next index matching B<nid> or B<obj> after B<lastpos>. B<lastpos>
should initially be set to -1. If there are no more entries -1 is returned.
If B<nid> is invalid (doesn't correspond to a valid OID) then -2 is returned.
X509_NAME_entry_count() returns the total number of entries in B<name>.
X509_NAME_get_entry() retrieves the B<X509_NAME_ENTRY> from B<name>
corresponding to index B<loc>. Acceptable values for B<loc> run from
0 to (X509_NAME_entry_count(name) - 1). The value returned is an
internal pointer which must not be freed.
X509_NAME_get_text_by_NID(), X509_NAME_get_text_by_OBJ() retrieve
the "text" from the first entry in B<name> which matches B<nid> or
B<obj>, if no such entry exists -1 is returned. At most B<len> bytes
will be written and the text written to B<buf> will be null
terminated. The length of the output string written is returned
excluding the terminating null. If B<buf> is <NULL> then the amount
of space needed in B<buf> (excluding the final null) is returned.
=head1 NOTES
X509_NAME_get_text_by_NID() and X509_NAME_get_text_by_OBJ() should be
considered deprecated because they
have various limitations which make them
of minimal use in practice. They can only find the first matching
entry and will copy the contents of the field verbatim: this can
be highly confusing if the target is a multicharacter string type
like a BMPString or a UTF8String.
For a more general solution X509_NAME_get_index_by_NID() or
X509_NAME_get_index_by_OBJ() should be used followed by
X509_NAME_get_entry() on any matching indices and then the
various B<X509_NAME_ENTRY> utility functions on the result.
The list of all relevant B<NID_*> and B<OBJ_* codes> can be found in
the source code header files E<lt>openssl/obj_mac.hE<gt> and/or
E<lt>openssl/objects.hE<gt>.
Applications which could pass invalid NIDs to X509_NAME_get_index_by_NID()
should check for the return value of -2. Alternatively the NID validity
can be determined first by checking OBJ_nid2obj(nid) is not NULL.
+=head1 RETURN VALUES
+
+X509_NAME_get_index_by_NID() and X509_NAME_get_index_by_OBJ()
+return the index of the next matching entry or -1 if not found.
+X509_NAME_get_index_by_NID() can also return -2 if the supplied
+NID is invalid.
+
+X509_NAME_entry_count() returns the total number of entries.
+
+X509_NAME_get_entry() returns an B<X509_NAME> pointer to the
+requested entry or B<NULL> if the index is invalid.
+
=head1 EXAMPLES
Process all entries:
int i;
X509_NAME_ENTRY *e;
for (i = 0; i < X509_NAME_entry_count(nm); i++) {
e = X509_NAME_get_entry(nm, i);
/* Do something with e */
}
Process all commonName entries:
int lastpos = -1;
X509_NAME_ENTRY *e;
for (;;) {
lastpos = X509_NAME_get_index_by_NID(nm, NID_commonName, lastpos);
if (lastpos == -1)
break;
e = X509_NAME_get_entry(nm, lastpos);
/* Do something with e */
}
-=head1 RETURN VALUES
-
-X509_NAME_get_index_by_NID() and X509_NAME_get_index_by_OBJ()
-return the index of the next matching entry or -1 if not found.
-X509_NAME_get_index_by_NID() can also return -2 if the supplied
-NID is invalid.
-
-X509_NAME_entry_count() returns the total number of entries.
-
-X509_NAME_get_entry() returns an B<X509_NAME> pointer to the
-requested entry or B<NULL> if the index is invalid.
-
=head1 SEE ALSO
L<ERR_get_error(3)>, L<d2i_X509_NAME(3)>
=head1 COPYRIGHT
-Copyright 2002-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2002-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/X509_get_subject_name.pod b/doc/man3/X509_get_subject_name.pod
index 7c4a499225ec..807f9d3d9b19 100644
--- a/doc/man3/X509_get_subject_name.pod
+++ b/doc/man3/X509_get_subject_name.pod
@@ -1,86 +1,86 @@
=pod
=head1 NAME
X509_get_subject_name, X509_set_subject_name, X509_get_issuer_name,
X509_set_issuer_name, X509_REQ_get_subject_name, X509_REQ_set_subject_name,
X509_CRL_get_issuer, X509_CRL_set_issuer_name - get and set issuer or
subject names
=head1 SYNOPSIS
#include <openssl/x509.h>
X509_NAME *X509_get_subject_name(const X509 *x);
int X509_set_subject_name(X509 *x, X509_NAME *name);
X509_NAME *X509_get_issuer_name(const X509 *x);
int X509_set_issuer_name(X509 *x, X509_NAME *name);
X509_NAME *X509_REQ_get_subject_name(const X509_REQ *req);
int X509_REQ_set_subject_name(X509_REQ *req, X509_NAME *name);
X509_NAME *X509_CRL_get_issuer(const X509_CRL *crl);
int X509_CRL_set_issuer_name(X509_CRL *x, X509_NAME *name);
=head1 DESCRIPTION
X509_get_subject_name() returns the subject name of certificate B<x>. The
returned value is an internal pointer which B<MUST NOT> be freed.
X509_set_subject_name() sets the issuer name of certificate B<x> to
B<name>. The B<name> parameter is copied internally and should be freed
up when it is no longer needed.
X509_get_issuer_name() and X509_set_issuer_name() are identical to
X509_get_subject_name() and X509_set_subject_name() except the get and
set the issuer name of B<x>.
Similarly X509_REQ_get_subject_name(), X509_REQ_set_subject_name(),
X509_CRL_get_issuer() and X509_CRL_set_issuer_name() get or set the subject
or issuer names of certificate requests of CRLs respectively.
=head1 RETURN VALUES
X509_get_subject_name(), X509_get_issuer_name(), X509_REQ_get_subject_name()
and X509_CRL_get_issuer() return an B<X509_NAME> pointer.
X509_set_subject_name(), X509_set_issuer_name(), X509_REQ_set_subject_name()
and X509_CRL_set_issuer_name() return 1 for success and 0 for failure.
-=head1 HISTORY
-
-X509_REQ_get_subject_name() is a function in OpenSSL 1.1.0 and a macro in
-earlier versions.
-
-X509_CRL_get_issuer() is a function in OpenSSL 1.1.0. It was previously
-added in OpenSSL 1.0.0 as a macro.
-
=head1 SEE ALSO
L<d2i_X509(3)>,
L<ERR_get_error(3)>, L<d2i_X509(3)>
L<X509_CRL_get0_by_serial(3)>,
L<X509_get0_signature(3)>,
L<X509_get_ext_d2i(3)>,
L<X509_get_extension_flags(3)>,
L<X509_get_pubkey(3)>,
L<X509_NAME_add_entry_by_txt(3)>,
L<X509_NAME_ENTRY_get_object(3)>,
L<X509_NAME_get_index_by_NID(3)>,
L<X509_NAME_print_ex(3)>,
L<X509_new(3)>,
L<X509_sign(3)>,
L<X509V3_get_d2i(3)>,
L<X509_verify_cert(3)>
+=head1 HISTORY
+
+X509_REQ_get_subject_name() is a function in OpenSSL 1.1.0 and a macro in
+earlier versions.
+
+X509_CRL_get_issuer() is a function in OpenSSL 1.1.0. It was previously
+added in OpenSSL 1.0.0 as a macro.
+
=head1 COPYRIGHT
-Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 2015-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/doc/man3/d2i_X509.pod b/doc/man3/d2i_X509.pod
index 71985a44edf4..3d50f5d9081a 100644
--- a/doc/man3/d2i_X509.pod
+++ b/doc/man3/d2i_X509.pod
@@ -1,611 +1,611 @@
=pod
=head1 NAME
d2i_ACCESS_DESCRIPTION,
d2i_ADMISSIONS,
d2i_ADMISSION_SYNTAX,
d2i_ASIdOrRange,
d2i_ASIdentifierChoice,
d2i_ASIdentifiers,
d2i_ASN1_BIT_STRING,
d2i_ASN1_BMPSTRING,
d2i_ASN1_ENUMERATED,
d2i_ASN1_GENERALIZEDTIME,
d2i_ASN1_GENERALSTRING,
d2i_ASN1_IA5STRING,
d2i_ASN1_INTEGER,
d2i_ASN1_NULL,
d2i_ASN1_OBJECT,
d2i_ASN1_OCTET_STRING,
d2i_ASN1_PRINTABLE,
d2i_ASN1_PRINTABLESTRING,
d2i_ASN1_SEQUENCE_ANY,
d2i_ASN1_SET_ANY,
d2i_ASN1_T61STRING,
d2i_ASN1_TIME,
d2i_ASN1_TYPE,
d2i_ASN1_UINTEGER,
d2i_ASN1_UNIVERSALSTRING,
d2i_ASN1_UTCTIME,
d2i_ASN1_UTF8STRING,
d2i_ASN1_VISIBLESTRING,
d2i_ASRange,
d2i_AUTHORITY_INFO_ACCESS,
d2i_AUTHORITY_KEYID,
d2i_BASIC_CONSTRAINTS,
d2i_CERTIFICATEPOLICIES,
d2i_CMS_ContentInfo,
d2i_CMS_ReceiptRequest,
d2i_CMS_bio,
d2i_CRL_DIST_POINTS,
d2i_DHxparams,
d2i_DIRECTORYSTRING,
d2i_DISPLAYTEXT,
d2i_DIST_POINT,
d2i_DIST_POINT_NAME,
d2i_DSAPrivateKey,
d2i_DSAPrivateKey_bio,
d2i_DSAPrivateKey_fp,
d2i_DSAPublicKey,
d2i_DSA_PUBKEY,
d2i_DSA_PUBKEY_bio,
d2i_DSA_PUBKEY_fp,
d2i_DSA_SIG,
d2i_DSAparams,
d2i_ECPKParameters,
d2i_ECParameters,
d2i_ECPrivateKey,
d2i_ECPrivateKey_bio,
d2i_ECPrivateKey_fp,
d2i_EC_PUBKEY,
d2i_EC_PUBKEY_bio,
d2i_EC_PUBKEY_fp,
d2i_EDIPARTYNAME,
d2i_ESS_CERT_ID,
d2i_ESS_ISSUER_SERIAL,
d2i_ESS_SIGNING_CERT,
d2i_EXTENDED_KEY_USAGE,
d2i_GENERAL_NAME,
d2i_GENERAL_NAMES,
d2i_IPAddressChoice,
d2i_IPAddressFamily,
d2i_IPAddressOrRange,
d2i_IPAddressRange,
d2i_ISSUING_DIST_POINT,
d2i_NAMING_AUTHORITY,
d2i_NETSCAPE_CERT_SEQUENCE,
d2i_NETSCAPE_SPKAC,
d2i_NETSCAPE_SPKI,
d2i_NOTICEREF,
d2i_OCSP_BASICRESP,
d2i_OCSP_CERTID,
d2i_OCSP_CERTSTATUS,
d2i_OCSP_CRLID,
d2i_OCSP_ONEREQ,
d2i_OCSP_REQINFO,
d2i_OCSP_REQUEST,
d2i_OCSP_RESPBYTES,
d2i_OCSP_RESPDATA,
d2i_OCSP_RESPID,
d2i_OCSP_RESPONSE,
d2i_OCSP_REVOKEDINFO,
d2i_OCSP_SERVICELOC,
d2i_OCSP_SIGNATURE,
d2i_OCSP_SINGLERESP,
d2i_OTHERNAME,
d2i_PBE2PARAM,
d2i_PBEPARAM,
d2i_PBKDF2PARAM,
d2i_PKCS12,
d2i_PKCS12_BAGS,
d2i_PKCS12_MAC_DATA,
d2i_PKCS12_SAFEBAG,
d2i_PKCS12_bio,
d2i_PKCS12_fp,
d2i_PKCS7,
d2i_PKCS7_DIGEST,
d2i_PKCS7_ENCRYPT,
d2i_PKCS7_ENC_CONTENT,
d2i_PKCS7_ENVELOPE,
d2i_PKCS7_ISSUER_AND_SERIAL,
d2i_PKCS7_RECIP_INFO,
d2i_PKCS7_SIGNED,
d2i_PKCS7_SIGNER_INFO,
d2i_PKCS7_SIGN_ENVELOPE,
d2i_PKCS7_bio,
d2i_PKCS7_fp,
d2i_PKCS8_PRIV_KEY_INFO,
d2i_PKCS8_PRIV_KEY_INFO_bio,
d2i_PKCS8_PRIV_KEY_INFO_fp,
d2i_PKCS8_bio,
d2i_PKCS8_fp,
d2i_PKEY_USAGE_PERIOD,
d2i_POLICYINFO,
d2i_POLICYQUALINFO,
d2i_PROFESSION_INFO,
d2i_PROXY_CERT_INFO_EXTENSION,
d2i_PROXY_POLICY,
d2i_RSAPrivateKey,
d2i_RSAPrivateKey_bio,
d2i_RSAPrivateKey_fp,
d2i_RSAPublicKey,
d2i_RSAPublicKey_bio,
d2i_RSAPublicKey_fp,
d2i_RSA_OAEP_PARAMS,
d2i_RSA_PSS_PARAMS,
d2i_RSA_PUBKEY,
d2i_RSA_PUBKEY_bio,
d2i_RSA_PUBKEY_fp,
d2i_SCRYPT_PARAMS,
d2i_SCT_LIST,
d2i_SXNET,
d2i_SXNETID,
d2i_TS_ACCURACY,
d2i_TS_MSG_IMPRINT,
d2i_TS_MSG_IMPRINT_bio,
d2i_TS_MSG_IMPRINT_fp,
d2i_TS_REQ,
d2i_TS_REQ_bio,
d2i_TS_REQ_fp,
d2i_TS_RESP,
d2i_TS_RESP_bio,
d2i_TS_RESP_fp,
d2i_TS_STATUS_INFO,
d2i_TS_TST_INFO,
d2i_TS_TST_INFO_bio,
d2i_TS_TST_INFO_fp,
d2i_USERNOTICE,
d2i_X509,
d2i_X509_ALGOR,
d2i_X509_ALGORS,
d2i_X509_ATTRIBUTE,
d2i_X509_CERT_AUX,
d2i_X509_CINF,
d2i_X509_CRL,
d2i_X509_CRL_INFO,
d2i_X509_CRL_bio,
d2i_X509_CRL_fp,
d2i_X509_EXTENSION,
d2i_X509_EXTENSIONS,
d2i_X509_NAME,
d2i_X509_NAME_ENTRY,
d2i_X509_PUBKEY,
d2i_X509_REQ,
d2i_X509_REQ_INFO,
d2i_X509_REQ_bio,
d2i_X509_REQ_fp,
d2i_X509_REVOKED,
d2i_X509_SIG,
d2i_X509_VAL,
i2d_ACCESS_DESCRIPTION,
i2d_ADMISSIONS,
i2d_ADMISSION_SYNTAX,
i2d_ASIdOrRange,
i2d_ASIdentifierChoice,
i2d_ASIdentifiers,
i2d_ASN1_BIT_STRING,
i2d_ASN1_BMPSTRING,
i2d_ASN1_ENUMERATED,
i2d_ASN1_GENERALIZEDTIME,
i2d_ASN1_GENERALSTRING,
i2d_ASN1_IA5STRING,
i2d_ASN1_INTEGER,
i2d_ASN1_NULL,
i2d_ASN1_OBJECT,
i2d_ASN1_OCTET_STRING,
i2d_ASN1_PRINTABLE,
i2d_ASN1_PRINTABLESTRING,
i2d_ASN1_SEQUENCE_ANY,
i2d_ASN1_SET_ANY,
i2d_ASN1_T61STRING,
i2d_ASN1_TIME,
i2d_ASN1_TYPE,
i2d_ASN1_UNIVERSALSTRING,
i2d_ASN1_UTCTIME,
i2d_ASN1_UTF8STRING,
i2d_ASN1_VISIBLESTRING,
i2d_ASN1_bio_stream,
i2d_ASRange,
i2d_AUTHORITY_INFO_ACCESS,
i2d_AUTHORITY_KEYID,
i2d_BASIC_CONSTRAINTS,
i2d_CERTIFICATEPOLICIES,
i2d_CMS_ContentInfo,
i2d_CMS_ReceiptRequest,
i2d_CMS_bio,
i2d_CRL_DIST_POINTS,
i2d_DHxparams,
i2d_DIRECTORYSTRING,
i2d_DISPLAYTEXT,
i2d_DIST_POINT,
i2d_DIST_POINT_NAME,
i2d_DSAPrivateKey,
i2d_DSAPrivateKey_bio,
i2d_DSAPrivateKey_fp,
i2d_DSAPublicKey,
i2d_DSA_PUBKEY,
i2d_DSA_PUBKEY_bio,
i2d_DSA_PUBKEY_fp,
i2d_DSA_SIG,
i2d_DSAparams,
i2d_ECPKParameters,
i2d_ECParameters,
i2d_ECPrivateKey,
i2d_ECPrivateKey_bio,
i2d_ECPrivateKey_fp,
i2d_EC_PUBKEY,
i2d_EC_PUBKEY_bio,
i2d_EC_PUBKEY_fp,
i2d_EDIPARTYNAME,
i2d_ESS_CERT_ID,
i2d_ESS_ISSUER_SERIAL,
i2d_ESS_SIGNING_CERT,
i2d_EXTENDED_KEY_USAGE,
i2d_GENERAL_NAME,
i2d_GENERAL_NAMES,
i2d_IPAddressChoice,
i2d_IPAddressFamily,
i2d_IPAddressOrRange,
i2d_IPAddressRange,
i2d_ISSUING_DIST_POINT,
i2d_NAMING_AUTHORITY,
i2d_NETSCAPE_CERT_SEQUENCE,
i2d_NETSCAPE_SPKAC,
i2d_NETSCAPE_SPKI,
i2d_NOTICEREF,
i2d_OCSP_BASICRESP,
i2d_OCSP_CERTID,
i2d_OCSP_CERTSTATUS,
i2d_OCSP_CRLID,
i2d_OCSP_ONEREQ,
i2d_OCSP_REQINFO,
i2d_OCSP_REQUEST,
i2d_OCSP_RESPBYTES,
i2d_OCSP_RESPDATA,
i2d_OCSP_RESPID,
i2d_OCSP_RESPONSE,
i2d_OCSP_REVOKEDINFO,
i2d_OCSP_SERVICELOC,
i2d_OCSP_SIGNATURE,
i2d_OCSP_SINGLERESP,
i2d_OTHERNAME,
i2d_PBE2PARAM,
i2d_PBEPARAM,
i2d_PBKDF2PARAM,
i2d_PKCS12,
i2d_PKCS12_BAGS,
i2d_PKCS12_MAC_DATA,
i2d_PKCS12_SAFEBAG,
i2d_PKCS12_bio,
i2d_PKCS12_fp,
i2d_PKCS7,
i2d_PKCS7_DIGEST,
i2d_PKCS7_ENCRYPT,
i2d_PKCS7_ENC_CONTENT,
i2d_PKCS7_ENVELOPE,
i2d_PKCS7_ISSUER_AND_SERIAL,
i2d_PKCS7_NDEF,
i2d_PKCS7_RECIP_INFO,
i2d_PKCS7_SIGNED,
i2d_PKCS7_SIGNER_INFO,
i2d_PKCS7_SIGN_ENVELOPE,
i2d_PKCS7_bio,
i2d_PKCS7_fp,
i2d_PKCS8PrivateKeyInfo_bio,
i2d_PKCS8PrivateKeyInfo_fp,
i2d_PKCS8_PRIV_KEY_INFO,
i2d_PKCS8_PRIV_KEY_INFO_bio,
i2d_PKCS8_PRIV_KEY_INFO_fp,
i2d_PKCS8_bio,
i2d_PKCS8_fp,
i2d_PKEY_USAGE_PERIOD,
i2d_POLICYINFO,
i2d_POLICYQUALINFO,
i2d_PROFESSION_INFO,
i2d_PROXY_CERT_INFO_EXTENSION,
i2d_PROXY_POLICY,
i2d_PublicKey,
i2d_RSAPrivateKey,
i2d_RSAPrivateKey_bio,
i2d_RSAPrivateKey_fp,
i2d_RSAPublicKey,
i2d_RSAPublicKey_bio,
i2d_RSAPublicKey_fp,
i2d_RSA_OAEP_PARAMS,
i2d_RSA_PSS_PARAMS,
i2d_RSA_PUBKEY,
i2d_RSA_PUBKEY_bio,
i2d_RSA_PUBKEY_fp,
i2d_SCRYPT_PARAMS,
i2d_SCT_LIST,
i2d_SXNET,
i2d_SXNETID,
i2d_TS_ACCURACY,
i2d_TS_MSG_IMPRINT,
i2d_TS_MSG_IMPRINT_bio,
i2d_TS_MSG_IMPRINT_fp,
i2d_TS_REQ,
i2d_TS_REQ_bio,
i2d_TS_REQ_fp,
i2d_TS_RESP,
i2d_TS_RESP_bio,
i2d_TS_RESP_fp,
i2d_TS_STATUS_INFO,
i2d_TS_TST_INFO,
i2d_TS_TST_INFO_bio,
i2d_TS_TST_INFO_fp,
i2d_USERNOTICE,
i2d_X509,
i2d_X509_ALGOR,
i2d_X509_ALGORS,
i2d_X509_ATTRIBUTE,
i2d_X509_CERT_AUX,
i2d_X509_CINF,
i2d_X509_CRL,
i2d_X509_CRL_INFO,
i2d_X509_CRL_bio,
i2d_X509_CRL_fp,
i2d_X509_EXTENSION,
i2d_X509_EXTENSIONS,
i2d_X509_NAME,
i2d_X509_NAME_ENTRY,
i2d_X509_PUBKEY,
i2d_X509_REQ,
i2d_X509_REQ_INFO,
i2d_X509_REQ_bio,
i2d_X509_REQ_fp,
i2d_X509_REVOKED,
i2d_X509_SIG,
i2d_X509_VAL,
- convert objects from/to ASN.1/DER representation
=head1 SYNOPSIS
=for comment generic
TYPE *d2i_TYPE(TYPE **a, unsigned char **ppin, long length);
TYPE *d2i_TYPE_bio(BIO *bp, TYPE **a);
TYPE *d2i_TYPE_fp(FILE *fp, TYPE **a);
int i2d_TYPE(TYPE *a, unsigned char **ppout);
int i2d_TYPE_fp(FILE *fp, TYPE *a);
int i2d_TYPE_bio(BIO *bp, TYPE *a);
=head1 DESCRIPTION
In the description here, I<TYPE> is used a placeholder
for any of the OpenSSL datatypes, such as I<X509_CRL>.
The function parameters I<ppin> and I<ppout> are generally
either both named I<pp> in the headers, or I<in> and I<out>.
These functions convert OpenSSL objects to and from their ASN.1/DER
encoding. Unlike the C structures which can have pointers to sub-objects
within, the DER is a serialized encoding, suitable for sending over the
network, writing to a file, and so on.
d2i_TYPE() attempts to decode B<len> bytes at B<*ppin>. If successful a
pointer to the B<TYPE> structure is returned and B<*ppin> is incremented to
the byte following the parsed data. If B<a> is not B<NULL> then a pointer
to the returned structure is also written to B<*a>. If an error occurred
then B<NULL> is returned.
On a successful return, if B<*a> is not B<NULL> then it is assumed that B<*a>
contains a valid B<TYPE> structure and an attempt is made to reuse it. This
"reuse" capability is present for historical compatibility but its use is
B<strongly discouraged> (see BUGS below, and the discussion in the RETURN
VALUES section).
d2i_TYPE_bio() is similar to d2i_TYPE() except it attempts
to parse data from BIO B<bp>.
d2i_TYPE_fp() is similar to d2i_TYPE() except it attempts
to parse data from FILE pointer B<fp>.
i2d_TYPE() encodes the structure pointed to by B<a> into DER format.
If B<ppout> is not B<NULL>, it writes the DER encoded data to the buffer
at B<*ppout>, and increments it to point after the data just written.
If the return value is negative an error occurred, otherwise it
returns the length of the encoded data.
If B<*ppout> is B<NULL> memory will be allocated for a buffer and the encoded
data written to it. In this case B<*ppout> is not incremented and it points
to the start of the data just written.
i2d_TYPE_bio() is similar to i2d_TYPE() except it writes
the encoding of the structure B<a> to BIO B<bp> and it
returns 1 for success and 0 for failure.
i2d_TYPE_fp() is similar to i2d_TYPE() except it writes
the encoding of the structure B<a> to BIO B<bp> and it
returns 1 for success and 0 for failure.
These routines do not encrypt private keys and therefore offer no
security; use L<PEM_write_PrivateKey(3)> or similar for writing to files.
=head1 NOTES
The letters B<i> and B<d> in B<i2d_TYPE> stand for
"internal" (that is, an internal C structure) and "DER" respectively.
So B<i2d_TYPE> converts from internal to DER.
The functions can also understand B<BER> forms.
The actual TYPE structure passed to i2d_TYPE() must be a valid
populated B<TYPE> structure -- it B<cannot> simply be fed with an
empty structure such as that returned by TYPE_new().
The encoded data is in binary form and may contain embedded zeroes.
Therefore any FILE pointers or BIOs should be opened in binary mode.
Functions such as strlen() will B<not> return the correct length
of the encoded structure.
The ways that B<*ppin> and B<*ppout> are incremented after the operation
can trap the unwary. See the B<WARNINGS> section for some common
errors.
The reason for this-auto increment behaviour is to reflect a typical
usage of ASN1 functions: after one structure is encoded or decoded
another will be processed after it.
The following points about the data types might be useful:
=over 4
=item B<ASN1_OBJECT>
Represents an ASN1 OBJECT IDENTIFIER.
=item B<DHparams>
Represents a PKCS#3 DH parameters structure.
=item B<DHparamx>
Represents an ANSI X9.42 DH parameters structure.
=item B<DSA_PUBKEY>
Represents a DSA public key using a B<SubjectPublicKeyInfo> structure.
=item B<DSAPublicKey, DSAPrivateKey>
Use a non-standard OpenSSL format and should be avoided; use B<DSA_PUBKEY>,
B<PEM_write_PrivateKey(3)>, or similar instead.
=item B<RSAPublicKey>
Represents a PKCS#1 RSA public key structure.
=item B<X509_ALGOR>
Represents an B<AlgorithmIdentifier> structure as used in IETF RFC 6960 and
elsewhere.
=item B<X509_Name>
Represents a B<Name> type as used for subject and issuer names in
IETF RFC 6960 and elsewhere.
=item B<X509_REQ>
Represents a PKCS#10 certificate request.
=item B<X509_SIG>
Represents the B<DigestInfo> structure defined in PKCS#1 and PKCS#7.
=back
+=head1 RETURN VALUES
+
+d2i_TYPE(), d2i_TYPE_bio() and d2i_TYPE_fp() return a valid B<TYPE> structure
+or B<NULL> if an error occurs. If the "reuse" capability has been used with
+a valid structure being passed in via B<a>, then the object is not freed in
+the event of error but may be in a potentially invalid or inconsistent state.
+
+i2d_TYPE() returns the number of bytes successfully encoded or a negative
+value if an error occurs.
+
+i2d_TYPE_bio() and i2d_TYPE_fp() return 1 for success and 0 if an error
+occurs.
+
=head1 EXAMPLES
Allocate and encode the DER encoding of an X509 structure:
int len;
unsigned char *buf;
buf = NULL;
len = i2d_X509(x, &buf);
if (len < 0)
/* error */
Attempt to decode a buffer:
X509 *x;
unsigned char *buf, *p;
int len;
/* Set up buf and len to point to the input buffer. */
p = buf;
x = d2i_X509(NULL, &p, len);
if (x == NULL)
/* error */
Alternative technique:
X509 *x;
unsigned char *buf, *p;
int len;
/* Set up buf and len to point to the input buffer. */
p = buf;
x = NULL;
if (d2i_X509(&x, &p, len) == NULL)
/* error */
=head1 WARNINGS
Using a temporary variable is mandatory. A common
mistake is to attempt to use a buffer directly as follows:
int len;
unsigned char *buf;
len = i2d_X509(x, NULL);
buf = OPENSSL_malloc(len);
...
i2d_X509(x, &buf);
...
OPENSSL_free(buf);
This code will result in B<buf> apparently containing garbage because
it was incremented after the call to point after the data just written.
Also B<buf> will no longer contain the pointer allocated by OPENSSL_malloc()
and the subsequent call to OPENSSL_free() is likely to crash.
Another trap to avoid is misuse of the B<a> argument to d2i_TYPE():
X509 *x;
if (d2i_X509(&x, &p, len) == NULL)
/* error */
This will probably crash somewhere in d2i_X509(). The reason for this
is that the variable B<x> is uninitialized and an attempt will be made to
interpret its (invalid) value as an B<X509> structure, typically causing
a segmentation violation. If B<x> is set to NULL first then this will not
happen.
=head1 BUGS
In some versions of OpenSSL the "reuse" behaviour of d2i_TYPE() when
B<*px> is valid is broken and some parts of the reused structure may
persist if they are not present in the new one. As a result the use
of this "reuse" behaviour is strongly discouraged.
i2d_TYPE() will not return an error in many versions of OpenSSL,
if mandatory fields are not initialized due to a programming error
then the encoded structure may contain invalid data or omit the
fields entirely and will not be parsed by d2i_TYPE(). This may be
fixed in future so code should not assume that i2d_TYPE() will
always succeed.
Any function which encodes a structure (i2d_TYPE(),
i2d_TYPE() or i2d_TYPE()) may return a stale encoding if the
structure has been modified after deserialization or previous
serialization. This is because some objects cache the encoding for
efficiency reasons.
-=head1 RETURN VALUES
-
-d2i_TYPE(), d2i_TYPE_bio() and d2i_TYPE_fp() return a valid B<TYPE> structure
-or B<NULL> if an error occurs. If the "reuse" capability has been used with
-a valid structure being passed in via B<a>, then the object is not freed in
-the event of error but may be in a potentially invalid or inconsistent state.
-
-i2d_TYPE() returns the number of bytes successfully encoded or a negative
-value if an error occurs.
-
-i2d_TYPE_bio() and i2d_TYPE_fp() return 1 for success and 0 if an error
-occurs.
-
=head1 COPYRIGHT
-Copyright 1998-2018 The OpenSSL Project Authors. All Rights Reserved.
+Copyright 1998-2019 The OpenSSL Project Authors. All Rights Reserved.
Licensed under the OpenSSL license (the "License"). You may not use
this file except in compliance with the License. You can obtain a copy
in the file LICENSE in the source distribution or at
L<https://www.openssl.org/source/license.html>.
=cut
diff --git a/e_os.h b/e_os.h
index 8e6efa9616cf..e9ce6c9cc8b9 100644
--- a/e_os.h
+++ b/e_os.h
@@ -1,334 +1,333 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_E_OS_H
# define HEADER_E_OS_H
# include <limits.h>
# include <openssl/opensslconf.h>
# include <openssl/e_os2.h>
# include <openssl/crypto.h>
# include "internal/nelem.h"
/*
* <openssl/e_os2.h> contains what we can justify to make visible to the
* outside; this file e_os.h is not part of the exported interface.
*/
# ifndef DEVRANDOM
/*
* set this to a comma-separated list of 'random' device files to try out. By
* default, we will try to read at least one of these files
*/
-# if defined(__s390__)
-# define DEVRANDOM "/dev/prandom","/dev/urandom","/dev/hwrng","/dev/random"
-# else
-# define DEVRANDOM "/dev/urandom","/dev/random","/dev/srandom"
+# define DEVRANDOM "/dev/urandom", "/dev/random", "/dev/hwrng", "/dev/srandom"
+# ifdef __linux
+# define DEVRANDOM_WAIT "/dev/random"
# endif
# endif
# if !defined(OPENSSL_NO_EGD) && !defined(DEVRANDOM_EGD)
/*
* set this to a comma-separated list of 'egd' sockets to try out. These
* sockets will be tried in the order listed in case accessing the device
* files listed in DEVRANDOM did not return enough randomness.
*/
-# define DEVRANDOM_EGD "/var/run/egd-pool","/dev/egd-pool","/etc/egd-pool","/etc/entropy"
+# define DEVRANDOM_EGD "/var/run/egd-pool", "/dev/egd-pool", "/etc/egd-pool", "/etc/entropy"
# endif
# if defined(OPENSSL_SYS_VXWORKS) || defined(OPENSSL_SYS_UEFI)
# define NO_CHMOD
# define NO_SYSLOG
# endif
# define get_last_sys_error() errno
# define clear_sys_error() errno=0
# define set_sys_error(e) errno=(e)
/********************************************************************
The Microsoft section
********************************************************************/
# if defined(OPENSSL_SYS_WIN32) && !defined(WIN32)
# define WIN32
# endif
# if defined(OPENSSL_SYS_WINDOWS) && !defined(WINDOWS)
# define WINDOWS
# endif
# if defined(OPENSSL_SYS_MSDOS) && !defined(MSDOS)
# define MSDOS
# endif
# ifdef WIN32
# undef get_last_sys_error
# undef clear_sys_error
# undef set_sys_error
# define get_last_sys_error() GetLastError()
# define clear_sys_error() SetLastError(0)
# define set_sys_error(e) SetLastError(e)
# if !defined(WINNT)
# define WIN_CONSOLE_BUG
# endif
# else
# endif
# if (defined(WINDOWS) || defined(MSDOS))
# ifdef __DJGPP__
# include <unistd.h>
# include <sys/stat.h>
# define _setmode setmode
# define _O_TEXT O_TEXT
# define _O_BINARY O_BINARY
# define HAS_LFN_SUPPORT(name) (pathconf((name), _PC_NAME_MAX) > 12)
# undef DEVRANDOM_EGD /* Neither MS-DOS nor FreeDOS provide 'egd' sockets. */
# undef DEVRANDOM
# define DEVRANDOM "/dev/urandom\x24"
# endif /* __DJGPP__ */
# ifndef S_IFDIR
# define S_IFDIR _S_IFDIR
# endif
# ifndef S_IFMT
# define S_IFMT _S_IFMT
# endif
# if !defined(WINNT) && !defined(__DJGPP__)
# define NO_SYSLOG
# endif
# ifdef WINDOWS
# if !defined(_WIN32_WCE) && !defined(_WIN32_WINNT)
/*
* Defining _WIN32_WINNT here in e_os.h implies certain "discipline."
* Most notably we ought to check for availability of each specific
* routine that was introduced after denoted _WIN32_WINNT with
* GetProcAddress(). Normally newer functions are masked with higher
* _WIN32_WINNT in SDK headers. So that if you wish to use them in
* some module, you'd need to override _WIN32_WINNT definition in
* the target module in order to "reach for" prototypes, but replace
* calls to new functions with indirect calls. Alternatively it
* might be possible to achieve the goal by /DELAYLOAD-ing .DLLs
* and check for current OS version instead.
*/
# define _WIN32_WINNT 0x0501
# endif
# if defined(_WIN32_WINNT) || defined(_WIN32_WCE)
/*
* Just like defining _WIN32_WINNT including winsock2.h implies
* certain "discipline" for maintaining [broad] binary compatibility.
* As long as structures are invariant among Winsock versions,
* it's sufficient to check for specific Winsock2 API availability
* at run-time [DSO_global_lookup is recommended]...
*/
# include <winsock2.h>
# include <ws2tcpip.h>
/* yes, they have to be #included prior to <windows.h> */
# endif
# include <windows.h>
# include <stdio.h>
# include <stddef.h>
# include <errno.h>
# if defined(_WIN32_WCE) && !defined(EACCES)
# define EACCES 13
# endif
# include <string.h>
# ifdef _WIN64
# define strlen(s) _strlen31(s)
/* cut strings to 2GB */
static __inline unsigned int _strlen31(const char *str)
{
unsigned int len = 0;
while (*str && len < 0x80000000U)
str++, len++;
return len & 0x7FFFFFFF;
}
# endif
# include <malloc.h>
# if defined(_MSC_VER) && !defined(_WIN32_WCE) && !defined(_DLL) && defined(stdin)
# if _MSC_VER>=1300 && _MSC_VER<1600
# undef stdin
# undef stdout
# undef stderr
FILE *__iob_func();
# define stdin (&__iob_func()[0])
# define stdout (&__iob_func()[1])
# define stderr (&__iob_func()[2])
# elif _MSC_VER<1300 && defined(I_CAN_LIVE_WITH_LNK4049)
# undef stdin
# undef stdout
# undef stderr
/*
* pre-1300 has __p__iob(), but it's available only in msvcrt.lib,
* or in other words with /MD. Declaring implicit import, i.e. with
* _imp_ prefix, works correctly with all compiler options, but
* without /MD results in LINK warning LNK4049: 'locally defined
* symbol "__iob" imported'.
*/
extern FILE *_imp___iob;
# define stdin (&_imp___iob[0])
# define stdout (&_imp___iob[1])
# define stderr (&_imp___iob[2])
# endif
# endif
# endif
# include <io.h>
# include <fcntl.h>
# ifdef OPENSSL_SYS_WINCE
# define OPENSSL_NO_POSIX_IO
# endif
# define EXIT(n) exit(n)
# define LIST_SEPARATOR_CHAR ';'
# ifndef W_OK
# define W_OK 2
# endif
# ifndef R_OK
# define R_OK 4
# endif
# ifdef OPENSSL_SYS_WINCE
# define DEFAULT_HOME ""
# else
# define DEFAULT_HOME "C:"
# endif
/* Avoid Visual Studio 13 GetVersion deprecated problems */
# if defined(_MSC_VER) && _MSC_VER>=1800
# define check_winnt() (1)
# define check_win_minplat(x) (1)
# else
# define check_winnt() (GetVersion() < 0x80000000)
# define check_win_minplat(x) (LOBYTE(LOWORD(GetVersion())) >= (x))
# endif
# else /* The non-microsoft world */
# if defined(OPENSSL_SYS_VXWORKS)
# include <sys/times.h>
# else
# include <sys/time.h>
# endif
# ifdef OPENSSL_SYS_VMS
# define VMS 1
/*
* some programs don't include stdlib, so exit() and others give implicit
* function warnings
*/
# include <stdlib.h>
# if defined(__DECC)
# include <unistd.h>
# else
# include <unixlib.h>
# endif
# define LIST_SEPARATOR_CHAR ','
/* We don't have any well-defined random devices on VMS, yet... */
# undef DEVRANDOM
/*-
We need to do this since VMS has the following coding on status codes:
Bits 0-2: status type: 0 = warning, 1 = success, 2 = error, 3 = info ...
The important thing to know is that odd numbers are considered
good, while even ones are considered errors.
Bits 3-15: actual status number
Bits 16-27: facility number. 0 is considered "unknown"
Bits 28-31: control bits. If bit 28 is set, the shell won't try to
output the message (which, for random codes, just looks ugly)
So, what we do here is to change 0 to 1 to get the default success status,
and everything else is shifted up to fit into the status number field, and
the status is tagged as an error, which is what is wanted here.
Finally, we add the VMS C facility code 0x35a000, because there are some
programs, such as Perl, that will reinterpret the code back to something
POSIX. 'man perlvms' explains it further.
NOTE: the perlvms manual wants to turn all codes 2 to 255 into success
codes (status type = 1). I couldn't disagree more. Fortunately, the
status type doesn't seem to bother Perl.
-- Richard Levitte
*/
# define EXIT(n) exit((n) ? (((n) << 3) | 2 | 0x10000000 | 0x35a000) : 1)
# define DEFAULT_HOME "SYS$LOGIN:"
# else
/* !defined VMS */
# ifdef OPENSSL_UNISTD
# include OPENSSL_UNISTD
# else
# include <unistd.h>
# endif
# include <sys/types.h>
# ifdef OPENSSL_SYS_WIN32_CYGWIN
# include <io.h>
# include <fcntl.h>
# endif
# define LIST_SEPARATOR_CHAR ':'
# define EXIT(n) exit(n)
# endif
# endif
/***********************************************/
# if defined(OPENSSL_SYS_WINDOWS)
# define strcasecmp _stricmp
# define strncasecmp _strnicmp
# if (_MSC_VER >= 1310)
# define open _open
# define fdopen _fdopen
# define close _close
# ifndef strdup
# define strdup _strdup
# endif
# define unlink _unlink
# define fileno _fileno
# endif
# else
# include <strings.h>
# endif
/* vxworks */
# if defined(OPENSSL_SYS_VXWORKS)
# include <ioLib.h>
# include <tickLib.h>
# include <sysLib.h>
# include <vxWorks.h>
# include <sockLib.h>
# include <taskLib.h>
# define TTY_STRUCT int
# define sleep(a) taskDelay((a) * sysClkRateGet())
/*
* NOTE: these are implemented by helpers in database app! if the database is
* not linked, we need to implement them elsewhere
*/
struct hostent *gethostbyname(const char *name);
struct hostent *gethostbyaddr(const char *addr, int length, int type);
struct servent *getservbyname(const char *name, const char *proto);
# endif
/* end vxworks */
# ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
# define CRYPTO_memcmp memcmp
# endif
/* unistd.h defines _POSIX_VERSION */
# if !defined(OPENSSL_NO_SECURE_MEMORY) && defined(OPENSSL_SYS_UNIX) \
&& ( (defined(_POSIX_VERSION) && _POSIX_VERSION >= 200112L) \
|| defined(__sun) || defined(__hpux) || defined(__sgi) \
|| defined(__osf__) )
# define OPENSSL_SECURE_MEMORY /* secure memory is implemented */
# endif
#endif
diff --git a/engines/e_padlock.c b/engines/e_padlock.c
index f6b1f169810e..a82c07e81373 100644
--- a/engines/e_padlock.c
+++ b/engines/e_padlock.c
@@ -1,747 +1,747 @@
/*
- * Copyright 2004-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2004-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <string.h>
#include <openssl/opensslconf.h>
#include <openssl/crypto.h>
#include <openssl/engine.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/rand.h>
#include <openssl/err.h>
#include <openssl/modes.h>
#ifndef OPENSSL_NO_HW
# ifndef OPENSSL_NO_HW_PADLOCK
/* Attempt to have a single source for both 0.9.7 and 0.9.8 :-) */
# if (OPENSSL_VERSION_NUMBER >= 0x00908000L)
# ifndef OPENSSL_NO_DYNAMIC_ENGINE
# define DYNAMIC_ENGINE
# endif
# elif (OPENSSL_VERSION_NUMBER >= 0x00907000L)
# ifdef ENGINE_DYNAMIC_SUPPORT
# define DYNAMIC_ENGINE
# endif
# else
# error "Only OpenSSL >= 0.9.7 is supported"
# endif
/*
* VIA PadLock AES is available *ONLY* on some x86 CPUs. Not only that it
* doesn't exist elsewhere, but it even can't be compiled on other platforms!
*/
# undef COMPILE_HW_PADLOCK
-# if !defined(I386_ONLY) && defined(PADLOCK_ASM)
+# if defined(PADLOCK_ASM)
# define COMPILE_HW_PADLOCK
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
static ENGINE *ENGINE_padlock(void);
# endif
# endif
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
void engine_load_padlock_int(void);
void engine_load_padlock_int(void)
{
/* On non-x86 CPUs it just returns. */
# ifdef COMPILE_HW_PADLOCK
ENGINE *toadd = ENGINE_padlock();
if (!toadd)
return;
ENGINE_add(toadd);
ENGINE_free(toadd);
ERR_clear_error();
# endif
}
# endif
# ifdef COMPILE_HW_PADLOCK
/* Function for ENGINE detection and control */
static int padlock_available(void);
static int padlock_init(ENGINE *e);
/* RNG Stuff */
static RAND_METHOD padlock_rand;
/* Cipher Stuff */
static int padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher,
const int **nids, int nid);
/* Engine names */
static const char *padlock_id = "padlock";
static char padlock_name[100];
/* Available features */
static int padlock_use_ace = 0; /* Advanced Cryptography Engine */
static int padlock_use_rng = 0; /* Random Number Generator */
/* ===== Engine "management" functions ===== */
/* Prepare the ENGINE structure for registration */
static int padlock_bind_helper(ENGINE *e)
{
/* Check available features */
padlock_available();
/*
* RNG is currently disabled for reasons discussed in commentary just
* before padlock_rand_bytes function.
*/
padlock_use_rng = 0;
/* Generate a nice engine name with available features */
BIO_snprintf(padlock_name, sizeof(padlock_name),
"VIA PadLock (%s, %s)",
padlock_use_rng ? "RNG" : "no-RNG",
padlock_use_ace ? "ACE" : "no-ACE");
/* Register everything or return with an error */
if (!ENGINE_set_id(e, padlock_id) ||
!ENGINE_set_name(e, padlock_name) ||
!ENGINE_set_init_function(e, padlock_init) ||
(padlock_use_ace && !ENGINE_set_ciphers(e, padlock_ciphers)) ||
(padlock_use_rng && !ENGINE_set_RAND(e, &padlock_rand))) {
return 0;
}
/* Everything looks good */
return 1;
}
# ifdef OPENSSL_NO_DYNAMIC_ENGINE
/* Constructor */
static ENGINE *ENGINE_padlock(void)
{
ENGINE *eng = ENGINE_new();
if (eng == NULL) {
return NULL;
}
if (!padlock_bind_helper(eng)) {
ENGINE_free(eng);
return NULL;
}
return eng;
}
# endif
/* Check availability of the engine */
static int padlock_init(ENGINE *e)
{
return (padlock_use_rng || padlock_use_ace);
}
/*
* This stuff is needed if this ENGINE is being compiled into a
* self-contained shared-library.
*/
-# ifdef DYNAMIC_ENGINE
+# ifndef OPENSSL_NO_DYNAMIC_ENGINE
static int padlock_bind_fn(ENGINE *e, const char *id)
{
if (id && (strcmp(id, padlock_id) != 0)) {
return 0;
}
if (!padlock_bind_helper(e)) {
return 0;
}
return 1;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
IMPLEMENT_DYNAMIC_BIND_FN(padlock_bind_fn)
-# endif /* DYNAMIC_ENGINE */
+# endif /* !OPENSSL_NO_DYNAMIC_ENGINE */
/* ===== Here comes the "real" engine ===== */
/* Some AES-related constants */
# define AES_BLOCK_SIZE 16
# define AES_KEY_SIZE_128 16
# define AES_KEY_SIZE_192 24
# define AES_KEY_SIZE_256 32
/*
* Here we store the status information relevant to the current context.
*/
/*
* BIG FAT WARNING: Inline assembler in PADLOCK_XCRYPT_ASM() depends on
* the order of items in this structure. Don't blindly modify, reorder,
* etc!
*/
struct padlock_cipher_data {
unsigned char iv[AES_BLOCK_SIZE]; /* Initialization vector */
union {
unsigned int pad[4];
struct {
int rounds:4;
int dgst:1; /* n/a in C3 */
int align:1; /* n/a in C3 */
int ciphr:1; /* n/a in C3 */
unsigned int keygen:1;
int interm:1;
unsigned int encdec:1;
int ksize:2;
} b;
} cword; /* Control word */
AES_KEY ks; /* Encryption key */
};
/* Interface to assembler module */
unsigned int padlock_capability(void);
void padlock_key_bswap(AES_KEY *key);
void padlock_verify_context(struct padlock_cipher_data *ctx);
void padlock_reload_key(void);
void padlock_aes_block(void *out, const void *inp,
struct padlock_cipher_data *ctx);
int padlock_ecb_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_cbc_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_cfb_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_ofb_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_ctr32_encrypt(void *out, const void *inp,
struct padlock_cipher_data *ctx, size_t len);
int padlock_xstore(void *out, int edx);
void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len);
void padlock_sha1(void *ctx, const void *inp, size_t len);
void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len);
void padlock_sha256(void *ctx, const void *inp, size_t len);
/*
* Load supported features of the CPU to see if the PadLock is available.
*/
static int padlock_available(void)
{
unsigned int edx = padlock_capability();
/* Fill up some flags */
padlock_use_ace = ((edx & (0x3 << 6)) == (0x3 << 6));
padlock_use_rng = ((edx & (0x3 << 2)) == (0x3 << 2));
return padlock_use_ace + padlock_use_rng;
}
/* ===== AES encryption/decryption ===== */
# if defined(NID_aes_128_cfb128) && ! defined (NID_aes_128_cfb)
# define NID_aes_128_cfb NID_aes_128_cfb128
# endif
# if defined(NID_aes_128_ofb128) && ! defined (NID_aes_128_ofb)
# define NID_aes_128_ofb NID_aes_128_ofb128
# endif
# if defined(NID_aes_192_cfb128) && ! defined (NID_aes_192_cfb)
# define NID_aes_192_cfb NID_aes_192_cfb128
# endif
# if defined(NID_aes_192_ofb128) && ! defined (NID_aes_192_ofb)
# define NID_aes_192_ofb NID_aes_192_ofb128
# endif
# if defined(NID_aes_256_cfb128) && ! defined (NID_aes_256_cfb)
# define NID_aes_256_cfb NID_aes_256_cfb128
# endif
# if defined(NID_aes_256_ofb128) && ! defined (NID_aes_256_ofb)
# define NID_aes_256_ofb NID_aes_256_ofb128
# endif
/* List of supported ciphers. */
static const int padlock_cipher_nids[] = {
NID_aes_128_ecb,
NID_aes_128_cbc,
NID_aes_128_cfb,
NID_aes_128_ofb,
NID_aes_128_ctr,
NID_aes_192_ecb,
NID_aes_192_cbc,
NID_aes_192_cfb,
NID_aes_192_ofb,
NID_aes_192_ctr,
NID_aes_256_ecb,
NID_aes_256_cbc,
NID_aes_256_cfb,
NID_aes_256_ofb,
NID_aes_256_ctr
};
static int padlock_cipher_nids_num = (sizeof(padlock_cipher_nids) /
sizeof(padlock_cipher_nids[0]));
/* Function prototypes ... */
static int padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc);
# define NEAREST_ALIGNED(ptr) ( (unsigned char *)(ptr) + \
( (0x10 - ((size_t)(ptr) & 0x0F)) & 0x0F ) )
# define ALIGNED_CIPHER_DATA(ctx) ((struct padlock_cipher_data *)\
NEAREST_ALIGNED(EVP_CIPHER_CTX_get_cipher_data(ctx)))
static int
padlock_ecb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
return padlock_ecb_encrypt(out_arg, in_arg,
ALIGNED_CIPHER_DATA(ctx), nbytes);
}
static int
padlock_cbc_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
int ret;
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
if ((ret = padlock_cbc_encrypt(out_arg, in_arg, cdata, nbytes)))
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
return ret;
}
static int
padlock_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
size_t chunk;
if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */
unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
if (chunk >= AES_BLOCK_SIZE)
return 0; /* bogus value */
if (EVP_CIPHER_CTX_encrypting(ctx))
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
ivp[chunk] = *(out_arg++) = *(in_arg++) ^ ivp[chunk];
chunk++, nbytes--;
} else
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
unsigned char c = *(in_arg++);
*(out_arg++) = c ^ ivp[chunk];
ivp[chunk++] = c, nbytes--;
}
EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE);
}
if (nbytes == 0)
return 1;
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) {
if (!padlock_cfb_encrypt(out_arg, in_arg, cdata, chunk))
return 0;
nbytes -= chunk;
}
if (nbytes) {
unsigned char *ivp = cdata->iv;
out_arg += chunk;
in_arg += chunk;
EVP_CIPHER_CTX_set_num(ctx, nbytes);
if (cdata->cword.b.encdec) {
cdata->cword.b.encdec = 0;
padlock_reload_key();
padlock_aes_block(ivp, ivp, cdata);
cdata->cword.b.encdec = 1;
padlock_reload_key();
while (nbytes) {
unsigned char c = *(in_arg++);
*(out_arg++) = c ^ *ivp;
*(ivp++) = c, nbytes--;
}
} else {
padlock_reload_key();
padlock_aes_block(ivp, ivp, cdata);
padlock_reload_key();
while (nbytes) {
*ivp = *(out_arg++) = *(in_arg++) ^ *ivp;
ivp++, nbytes--;
}
}
}
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
return 1;
}
static int
padlock_ofb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
size_t chunk;
/*
* ctx->num is maintained in byte-oriented modes, such as CFB and OFB...
*/
if ((chunk = EVP_CIPHER_CTX_num(ctx))) { /* borrow chunk variable */
unsigned char *ivp = EVP_CIPHER_CTX_iv_noconst(ctx);
if (chunk >= AES_BLOCK_SIZE)
return 0; /* bogus value */
while (chunk < AES_BLOCK_SIZE && nbytes != 0) {
*(out_arg++) = *(in_arg++) ^ ivp[chunk];
chunk++, nbytes--;
}
EVP_CIPHER_CTX_set_num(ctx, chunk % AES_BLOCK_SIZE);
}
if (nbytes == 0)
return 1;
memcpy(cdata->iv, EVP_CIPHER_CTX_iv(ctx), AES_BLOCK_SIZE);
if ((chunk = nbytes & ~(AES_BLOCK_SIZE - 1))) {
if (!padlock_ofb_encrypt(out_arg, in_arg, cdata, chunk))
return 0;
nbytes -= chunk;
}
if (nbytes) {
unsigned char *ivp = cdata->iv;
out_arg += chunk;
in_arg += chunk;
EVP_CIPHER_CTX_set_num(ctx, nbytes);
padlock_reload_key(); /* empirically found */
padlock_aes_block(ivp, ivp, cdata);
padlock_reload_key(); /* empirically found */
while (nbytes) {
*(out_arg++) = *(in_arg++) ^ *ivp;
ivp++, nbytes--;
}
}
memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), cdata->iv, AES_BLOCK_SIZE);
return 1;
}
static void padlock_ctr32_encrypt_glue(const unsigned char *in,
unsigned char *out, size_t blocks,
struct padlock_cipher_data *ctx,
const unsigned char *ivec)
{
memcpy(ctx->iv, ivec, AES_BLOCK_SIZE);
padlock_ctr32_encrypt(out, in, ctx, AES_BLOCK_SIZE * blocks);
}
static int
padlock_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out_arg,
const unsigned char *in_arg, size_t nbytes)
{
struct padlock_cipher_data *cdata = ALIGNED_CIPHER_DATA(ctx);
unsigned int num = EVP_CIPHER_CTX_num(ctx);
CRYPTO_ctr128_encrypt_ctr32(in_arg, out_arg, nbytes,
cdata, EVP_CIPHER_CTX_iv_noconst(ctx),
EVP_CIPHER_CTX_buf_noconst(ctx), &num,
(ctr128_f) padlock_ctr32_encrypt_glue);
EVP_CIPHER_CTX_set_num(ctx, (size_t)num);
return 1;
}
# define EVP_CIPHER_block_size_ECB AES_BLOCK_SIZE
# define EVP_CIPHER_block_size_CBC AES_BLOCK_SIZE
# define EVP_CIPHER_block_size_OFB 1
# define EVP_CIPHER_block_size_CFB 1
# define EVP_CIPHER_block_size_CTR 1
/*
* Declaring so many ciphers by hand would be a pain. Instead introduce a bit
* of preprocessor magic :-)
*/
# define DECLARE_AES_EVP(ksize,lmode,umode) \
static EVP_CIPHER *_hidden_aes_##ksize##_##lmode = NULL; \
static const EVP_CIPHER *padlock_aes_##ksize##_##lmode(void) \
{ \
if (_hidden_aes_##ksize##_##lmode == NULL \
&& ((_hidden_aes_##ksize##_##lmode = \
EVP_CIPHER_meth_new(NID_aes_##ksize##_##lmode, \
EVP_CIPHER_block_size_##umode, \
AES_KEY_SIZE_##ksize)) == NULL \
|| !EVP_CIPHER_meth_set_iv_length(_hidden_aes_##ksize##_##lmode, \
AES_BLOCK_SIZE) \
|| !EVP_CIPHER_meth_set_flags(_hidden_aes_##ksize##_##lmode, \
0 | EVP_CIPH_##umode##_MODE) \
|| !EVP_CIPHER_meth_set_init(_hidden_aes_##ksize##_##lmode, \
padlock_aes_init_key) \
|| !EVP_CIPHER_meth_set_do_cipher(_hidden_aes_##ksize##_##lmode, \
padlock_##lmode##_cipher) \
|| !EVP_CIPHER_meth_set_impl_ctx_size(_hidden_aes_##ksize##_##lmode, \
sizeof(struct padlock_cipher_data) + 16) \
|| !EVP_CIPHER_meth_set_set_asn1_params(_hidden_aes_##ksize##_##lmode, \
EVP_CIPHER_set_asn1_iv) \
|| !EVP_CIPHER_meth_set_get_asn1_params(_hidden_aes_##ksize##_##lmode, \
EVP_CIPHER_get_asn1_iv))) { \
EVP_CIPHER_meth_free(_hidden_aes_##ksize##_##lmode); \
_hidden_aes_##ksize##_##lmode = NULL; \
} \
return _hidden_aes_##ksize##_##lmode; \
}
DECLARE_AES_EVP(128, ecb, ECB)
DECLARE_AES_EVP(128, cbc, CBC)
DECLARE_AES_EVP(128, cfb, CFB)
DECLARE_AES_EVP(128, ofb, OFB)
DECLARE_AES_EVP(128, ctr, CTR)
DECLARE_AES_EVP(192, ecb, ECB)
DECLARE_AES_EVP(192, cbc, CBC)
DECLARE_AES_EVP(192, cfb, CFB)
DECLARE_AES_EVP(192, ofb, OFB)
DECLARE_AES_EVP(192, ctr, CTR)
DECLARE_AES_EVP(256, ecb, ECB)
DECLARE_AES_EVP(256, cbc, CBC)
DECLARE_AES_EVP(256, cfb, CFB)
DECLARE_AES_EVP(256, ofb, OFB)
DECLARE_AES_EVP(256, ctr, CTR)
static int
padlock_ciphers(ENGINE *e, const EVP_CIPHER **cipher, const int **nids,
int nid)
{
/* No specific cipher => return a list of supported nids ... */
if (!cipher) {
*nids = padlock_cipher_nids;
return padlock_cipher_nids_num;
}
/* ... or the requested "cipher" otherwise */
switch (nid) {
case NID_aes_128_ecb:
*cipher = padlock_aes_128_ecb();
break;
case NID_aes_128_cbc:
*cipher = padlock_aes_128_cbc();
break;
case NID_aes_128_cfb:
*cipher = padlock_aes_128_cfb();
break;
case NID_aes_128_ofb:
*cipher = padlock_aes_128_ofb();
break;
case NID_aes_128_ctr:
*cipher = padlock_aes_128_ctr();
break;
case NID_aes_192_ecb:
*cipher = padlock_aes_192_ecb();
break;
case NID_aes_192_cbc:
*cipher = padlock_aes_192_cbc();
break;
case NID_aes_192_cfb:
*cipher = padlock_aes_192_cfb();
break;
case NID_aes_192_ofb:
*cipher = padlock_aes_192_ofb();
break;
case NID_aes_192_ctr:
*cipher = padlock_aes_192_ctr();
break;
case NID_aes_256_ecb:
*cipher = padlock_aes_256_ecb();
break;
case NID_aes_256_cbc:
*cipher = padlock_aes_256_cbc();
break;
case NID_aes_256_cfb:
*cipher = padlock_aes_256_cfb();
break;
case NID_aes_256_ofb:
*cipher = padlock_aes_256_ofb();
break;
case NID_aes_256_ctr:
*cipher = padlock_aes_256_ctr();
break;
default:
/* Sorry, we don't support this NID */
*cipher = NULL;
return 0;
}
return 1;
}
/* Prepare the encryption key for PadLock usage */
static int
padlock_aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc)
{
struct padlock_cipher_data *cdata;
int key_len = EVP_CIPHER_CTX_key_length(ctx) * 8;
unsigned long mode = EVP_CIPHER_CTX_mode(ctx);
if (key == NULL)
return 0; /* ERROR */
cdata = ALIGNED_CIPHER_DATA(ctx);
memset(cdata, 0, sizeof(*cdata));
/* Prepare Control word. */
if (mode == EVP_CIPH_OFB_MODE || mode == EVP_CIPH_CTR_MODE)
cdata->cword.b.encdec = 0;
else
cdata->cword.b.encdec = (EVP_CIPHER_CTX_encrypting(ctx) == 0);
cdata->cword.b.rounds = 10 + (key_len - 128) / 32;
cdata->cword.b.ksize = (key_len - 128) / 64;
switch (key_len) {
case 128:
/*
* PadLock can generate an extended key for AES128 in hardware
*/
memcpy(cdata->ks.rd_key, key, AES_KEY_SIZE_128);
cdata->cword.b.keygen = 0;
break;
case 192:
case 256:
/*
* Generate an extended AES key in software. Needed for AES192/AES256
*/
/*
* Well, the above applies to Stepping 8 CPUs and is listed as
* hardware errata. They most likely will fix it at some point and
* then a check for stepping would be due here.
*/
if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE)
&& !enc)
AES_set_decrypt_key(key, key_len, &cdata->ks);
else
AES_set_encrypt_key(key, key_len, &cdata->ks);
# ifndef AES_ASM
/*
* OpenSSL C functions use byte-swapped extended key.
*/
padlock_key_bswap(&cdata->ks);
# endif
cdata->cword.b.keygen = 1;
break;
default:
/* ERROR */
return 0;
}
/*
* This is done to cover for cases when user reuses the
* context for new key. The catch is that if we don't do
* this, padlock_eas_cipher might proceed with old key...
*/
padlock_reload_key();
return 1;
}
/* ===== Random Number Generator ===== */
/*
* This code is not engaged. The reason is that it does not comply
* with recommendations for VIA RNG usage for secure applications
* (posted at http://www.via.com.tw/en/viac3/c3.jsp) nor does it
* provide meaningful error control...
*/
/*
* Wrapper that provides an interface between the API and the raw PadLock
* RNG
*/
static int padlock_rand_bytes(unsigned char *output, int count)
{
unsigned int eax, buf;
while (count >= 8) {
eax = padlock_xstore(output, 0);
if (!(eax & (1 << 6)))
return 0; /* RNG disabled */
/* this ---vv--- covers DC bias, Raw Bits and String Filter */
if (eax & (0x1F << 10))
return 0;
if ((eax & 0x1F) == 0)
continue; /* no data, retry... */
if ((eax & 0x1F) != 8)
return 0; /* fatal failure... */
output += 8;
count -= 8;
}
while (count > 0) {
eax = padlock_xstore(&buf, 3);
if (!(eax & (1 << 6)))
return 0; /* RNG disabled */
/* this ---vv--- covers DC bias, Raw Bits and String Filter */
if (eax & (0x1F << 10))
return 0;
if ((eax & 0x1F) == 0)
continue; /* no data, retry... */
if ((eax & 0x1F) != 1)
return 0; /* fatal failure... */
*output++ = (unsigned char)buf;
count--;
}
OPENSSL_cleanse(&buf, sizeof(buf));
return 1;
}
/* Dummy but necessary function */
static int padlock_rand_status(void)
{
return 1;
}
/* Prepare structure for registration */
static RAND_METHOD padlock_rand = {
NULL, /* seed */
padlock_rand_bytes, /* bytes */
NULL, /* cleanup */
NULL, /* add */
padlock_rand_bytes, /* pseudorand */
padlock_rand_status, /* rand status */
};
# endif /* COMPILE_HW_PADLOCK */
# endif /* !OPENSSL_NO_HW_PADLOCK */
#endif /* !OPENSSL_NO_HW */
#if defined(OPENSSL_NO_HW) || defined(OPENSSL_NO_HW_PADLOCK) \
|| !defined(COMPILE_HW_PADLOCK)
# ifndef OPENSSL_NO_DYNAMIC_ENGINE
OPENSSL_EXPORT
int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns);
OPENSSL_EXPORT
int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns)
{
return 0;
}
IMPLEMENT_DYNAMIC_CHECK_FN()
# endif
#endif
diff --git a/include/internal/dsoerr.h b/include/internal/dsoerr.h
index a54a18545e3c..0edf277f7051 100644
--- a/include/internal/dsoerr.h
+++ b/include/internal/dsoerr.h
@@ -1,83 +1,80 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_DSOERR_H
# define HEADER_DSOERR_H
# include <openssl/opensslconf.h>
-# ifndef OPENSSL_NO_DSO
-
-# ifdef __cplusplus
+# ifdef __cplusplus
extern "C"
-# endif
+# endif
int ERR_load_DSO_strings(void);
/*
* DSO function codes.
*/
# define DSO_F_DLFCN_BIND_FUNC 100
# define DSO_F_DLFCN_LOAD 102
# define DSO_F_DLFCN_MERGER 130
# define DSO_F_DLFCN_NAME_CONVERTER 123
# define DSO_F_DLFCN_UNLOAD 103
# define DSO_F_DL_BIND_FUNC 104
# define DSO_F_DL_LOAD 106
# define DSO_F_DL_MERGER 131
# define DSO_F_DL_NAME_CONVERTER 124
# define DSO_F_DL_UNLOAD 107
# define DSO_F_DSO_BIND_FUNC 108
# define DSO_F_DSO_CONVERT_FILENAME 126
# define DSO_F_DSO_CTRL 110
# define DSO_F_DSO_FREE 111
# define DSO_F_DSO_GET_FILENAME 127
# define DSO_F_DSO_GLOBAL_LOOKUP 139
# define DSO_F_DSO_LOAD 112
# define DSO_F_DSO_MERGE 132
# define DSO_F_DSO_NEW_METHOD 113
# define DSO_F_DSO_PATHBYADDR 105
# define DSO_F_DSO_SET_FILENAME 129
# define DSO_F_DSO_UP_REF 114
# define DSO_F_VMS_BIND_SYM 115
# define DSO_F_VMS_LOAD 116
# define DSO_F_VMS_MERGER 133
# define DSO_F_VMS_UNLOAD 117
# define DSO_F_WIN32_BIND_FUNC 101
# define DSO_F_WIN32_GLOBALLOOKUP 142
# define DSO_F_WIN32_JOINER 135
# define DSO_F_WIN32_LOAD 120
# define DSO_F_WIN32_MERGER 134
# define DSO_F_WIN32_NAME_CONVERTER 125
# define DSO_F_WIN32_PATHBYADDR 109
# define DSO_F_WIN32_SPLITTER 136
# define DSO_F_WIN32_UNLOAD 121
/*
* DSO reason codes.
*/
# define DSO_R_CTRL_FAILED 100
# define DSO_R_DSO_ALREADY_LOADED 110
# define DSO_R_EMPTY_FILE_STRUCTURE 113
# define DSO_R_FAILURE 114
# define DSO_R_FILENAME_TOO_BIG 101
# define DSO_R_FINISH_FAILED 102
# define DSO_R_INCORRECT_FILE_SYNTAX 115
# define DSO_R_LOAD_FAILED 103
# define DSO_R_NAME_TRANSLATION_FAILED 109
# define DSO_R_NO_FILENAME 111
# define DSO_R_NULL_HANDLE 104
# define DSO_R_SET_FILENAME_FAILED 112
# define DSO_R_STACK_ERROR 105
# define DSO_R_SYM_FAILURE 106
# define DSO_R_UNLOAD_FAILED 107
# define DSO_R_UNSUPPORTED 108
-# endif
#endif
diff --git a/include/internal/refcount.h b/include/internal/refcount.h
index 75d70a6418b7..d2364c621221 100644
--- a/include/internal/refcount.h
+++ b/include/internal/refcount.h
@@ -1,140 +1,150 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_INTERNAL_REFCOUNT_H
# define HEADER_INTERNAL_REFCOUNT_H
/* Used to checking reference counts, most while doing perl5 stuff :-) */
# if defined(OPENSSL_NO_STDIO)
# if defined(REF_PRINT)
# error "REF_PRINT requires stdio"
# endif
# endif
# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
&& !defined(__STDC_NO_ATOMICS__)
# include <stdatomic.h>
# define HAVE_C11_ATOMICS
# endif
# if defined(HAVE_C11_ATOMICS) && defined(ATOMIC_INT_LOCK_FREE) \
&& ATOMIC_INT_LOCK_FREE > 0
# define HAVE_ATOMICS 1
typedef _Atomic int CRYPTO_REF_COUNT;
static inline int CRYPTO_UP_REF(_Atomic int *val, int *ret, void *lock)
{
*ret = atomic_fetch_add_explicit(val, 1, memory_order_relaxed) + 1;
return 1;
}
/*
* Changes to shared structure other than reference counter have to be
* serialized. And any kind of serialization implies a release fence. This
* means that by the time reference counter is decremented all other
* changes are visible on all processors. Hence decrement itself can be
* relaxed. In case it hits zero, object will be destructed. Since it's
* last use of the object, destructor programmer might reason that access
* to mutable members doesn't have to be serialized anymore, which would
* otherwise imply an acquire fence. Hence conditional acquire fence...
*/
static inline int CRYPTO_DOWN_REF(_Atomic int *val, int *ret, void *lock)
{
*ret = atomic_fetch_sub_explicit(val, 1, memory_order_relaxed) - 1;
if (*ret == 0)
atomic_thread_fence(memory_order_acquire);
return 1;
}
# elif defined(__GNUC__) && defined(__ATOMIC_RELAXED) && __GCC_ATOMIC_INT_LOCK_FREE > 0
# define HAVE_ATOMICS 1
typedef int CRYPTO_REF_COUNT;
static __inline__ int CRYPTO_UP_REF(int *val, int *ret, void *lock)
{
*ret = __atomic_fetch_add(val, 1, __ATOMIC_RELAXED) + 1;
return 1;
}
static __inline__ int CRYPTO_DOWN_REF(int *val, int *ret, void *lock)
{
*ret = __atomic_fetch_sub(val, 1, __ATOMIC_RELAXED) - 1;
if (*ret == 0)
__atomic_thread_fence(__ATOMIC_ACQUIRE);
return 1;
}
# elif defined(_MSC_VER) && _MSC_VER>=1200
# define HAVE_ATOMICS 1
typedef volatile int CRYPTO_REF_COUNT;
-# if (defined(_M_ARM) && _M_ARM>=7) || defined(_M_ARM64)
+# if (defined(_M_ARM) && _M_ARM>=7 && !defined(_WIN32_WCE)) || defined(_M_ARM64)
# include <intrin.h>
# if defined(_M_ARM64) && !defined(_ARM_BARRIER_ISH)
# define _ARM_BARRIER_ISH _ARM64_BARRIER_ISH
# endif
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, void *lock)
{
*ret = _InterlockedExchangeAdd_nf(val, 1) + 1;
return 1;
}
static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, void *lock)
{
*ret = _InterlockedExchangeAdd_nf(val, -1) - 1;
if (*ret == 0)
__dmb(_ARM_BARRIER_ISH);
return 1;
}
# else
-# pragma intrinsic(_InterlockedExchangeAdd)
+# if !defined(_WIN32_WCE)
+# pragma intrinsic(_InterlockedExchangeAdd)
+# else
+# if _WIN32_WCE >= 0x600
+ extern long __cdecl _InterlockedExchangeAdd(long volatile*, long);
+# else
+ // under Windows CE we still have old-style Interlocked* functions
+ extern long __cdecl InterlockedExchangeAdd(long volatile*, long);
+# define _InterlockedExchangeAdd InterlockedExchangeAdd
+# endif
+# endif
static __inline int CRYPTO_UP_REF(volatile int *val, int *ret, void *lock)
{
*ret = _InterlockedExchangeAdd(val, 1) + 1;
return 1;
}
static __inline int CRYPTO_DOWN_REF(volatile int *val, int *ret, void *lock)
{
*ret = _InterlockedExchangeAdd(val, -1) - 1;
return 1;
}
# endif
# else
typedef int CRYPTO_REF_COUNT;
# define CRYPTO_UP_REF(val, ret, lock) CRYPTO_atomic_add(val, 1, ret, lock)
# define CRYPTO_DOWN_REF(val, ret, lock) CRYPTO_atomic_add(val, -1, ret, lock)
# endif
# if !defined(NDEBUG) && !defined(OPENSSL_NO_STDIO)
# define REF_ASSERT_ISNT(test) \
(void)((test) ? (OPENSSL_die("refcount error", __FILE__, __LINE__), 1) : 0)
# else
# define REF_ASSERT_ISNT(i)
# endif
# ifdef REF_PRINT
# define REF_PRINT_COUNT(a, b) \
fprintf(stderr, "%p:%4d:%s\n", b, b->references, a)
# else
# define REF_PRINT_COUNT(a, b)
# endif
#endif
diff --git a/include/internal/tsan_assist.h b/include/internal/tsan_assist.h
index 38ba0c7ebbf3..d41ebb341a42 100644
--- a/include/internal/tsan_assist.h
+++ b/include/internal/tsan_assist.h
@@ -1,144 +1,144 @@
/*
* Copyright 2018-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
/*
* Contemporary compilers implement lock-free atomic memory access
* primitives that facilitate writing "thread-opportunistic" or even real
* multi-threading low-overhead code. "Thread-opportunistic" is when
* exact result is not required, e.g. some statistics, or execution flow
* doesn't have to be unambiguous. Simplest example is lazy "constant"
* initialization when one can synchronize on variable itself, e.g.
*
* if (var == NOT_YET_INITIALIZED)
* var = function_returning_same_value();
*
* This does work provided that loads and stores are single-instuction
* operations (and integer ones are on *all* supported platforms), but
* it upsets Thread Sanitizer. Suggested solution is
*
* if (tsan_load(&var) == NOT_YET_INITIALIZED)
* tsan_store(&var, function_returning_same_value());
*
* Production machine code would be the same, so one can wonder why
* bother. Having Thread Sanitizer accept "thread-opportunistic" code
* allows to move on trouble-shooting real bugs.
*
* Resolving Thread Sanitizer nits was the initial purpose for this module,
* but it was later extended with more nuanced primitives that are useful
* even in "non-opportunistic" scenarios. Most notably verifying if a shared
* structure is fully initialized and bypassing the initialization lock.
* It's suggested to view macros defined in this module as "annotations" for
* thread-safe lock-free code, "Thread-Safe ANnotations"...
*
* It's assumed that ATOMIC_{LONG|INT}_LOCK_FREE are assigned same value as
* ATOMIC_POINTER_LOCK_FREE. And check for >= 2 ensures that corresponding
* code is inlined. It should be noted that statistics counters become
* accurate in such case.
*
* Special note about TSAN_QUALIFIER. It might be undesired to use it in
* a shared header. Because whether operation on specific variable or member
* is atomic or not might be irrelevant in other modules. In such case one
* can use TSAN_QUALIFIER in cast specifically when it has to count.
*/
#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
&& !defined(__STDC_NO_ATOMICS__)
# include <stdatomic.h>
# if defined(ATOMIC_POINTER_LOCK_FREE) \
&& ATOMIC_POINTER_LOCK_FREE >= 2
# define TSAN_QUALIFIER _Atomic
# define tsan_load(ptr) atomic_load_explicit((ptr), memory_order_relaxed)
# define tsan_store(ptr, val) atomic_store_explicit((ptr), (val), memory_order_relaxed)
# define tsan_counter(ptr) atomic_fetch_add_explicit((ptr), 1, memory_order_relaxed)
# define tsan_decr(ptr) atomic_fetch_add_explicit((ptr), -1, memory_order_relaxed)
# define tsan_ld_acq(ptr) atomic_load_explicit((ptr), memory_order_acquire)
# define tsan_st_rel(ptr, val) atomic_store_explicit((ptr), (val), memory_order_release)
# endif
#elif defined(__GNUC__) && defined(__ATOMIC_RELAXED)
# if defined(__GCC_ATOMIC_POINTER_LOCK_FREE) \
&& __GCC_ATOMIC_POINTER_LOCK_FREE >= 2
# define TSAN_QUALIFIER volatile
# define tsan_load(ptr) __atomic_load_n((ptr), __ATOMIC_RELAXED)
# define tsan_store(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELAXED)
# define tsan_counter(ptr) __atomic_fetch_add((ptr), 1, __ATOMIC_RELAXED)
# define tsan_decr(ptr) __atomic_fetch_add((ptr), -1, __ATOMIC_RELAXED)
# define tsan_ld_acq(ptr) __atomic_load_n((ptr), __ATOMIC_ACQUIRE)
# define tsan_st_rel(ptr, val) __atomic_store_n((ptr), (val), __ATOMIC_RELEASE)
# endif
#elif defined(_MSC_VER) && _MSC_VER>=1200 \
&& (defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64) || \
- defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7))
+ defined(_M_ARM64) || (defined(_M_ARM) && _M_ARM >= 7 && !defined(_WIN32_WCE)))
/*
* There is subtle dependency on /volatile:<iso|ms> command-line option.
* "ms" implies same semantic as memory_order_acquire for loads and
* memory_order_release for stores, while "iso" - memory_order_relaxed for
* either. Real complication is that defaults are different on x86 and ARM.
* There is explanation for that, "ms" is backward compatible with earlier
* compiler versions, while multi-processor ARM can be viewed as brand new
* platform to MSC and its users, and with non-relaxed semantic taking toll
* with additional instructions and penalties, it kind of makes sense to
* default to "iso"...
*/
# define TSAN_QUALIFIER volatile
# if defined(_M_ARM) || defined(_M_ARM64)
# define _InterlockedExchangeAdd _InterlockedExchangeAdd_nf
# pragma intrinsic(_InterlockedExchangeAdd_nf)
# pragma intrinsic(__iso_volatile_load32, __iso_volatile_store32)
# ifdef _WIN64
# define _InterlockedExchangeAdd64 _InterlockedExchangeAdd64_nf
# pragma intrinsic(_InterlockedExchangeAdd64_nf)
# pragma intrinsic(__iso_volatile_load64, __iso_volatile_store64)
# define tsan_load(ptr) (sizeof(*(ptr)) == 8 ? __iso_volatile_load64(ptr) \
: __iso_volatile_load32(ptr))
# define tsan_store(ptr, val) (sizeof(*(ptr)) == 8 ? __iso_volatile_store64((ptr), (val)) \
: __iso_volatile_store32((ptr), (val)))
# else
# define tsan_load(ptr) __iso_volatile_load32(ptr)
# define tsan_store(ptr, val) __iso_volatile_store32((ptr), (val))
# endif
# else
# define tsan_load(ptr) (*(ptr))
# define tsan_store(ptr, val) (*(ptr) = (val))
# endif
# pragma intrinsic(_InterlockedExchangeAdd)
# ifdef _WIN64
# pragma intrinsic(_InterlockedExchangeAdd64)
# define tsan_counter(ptr) (sizeof(*(ptr)) == 8 ? _InterlockedExchangeAdd64((ptr), 1) \
: _InterlockedExchangeAdd((ptr), 1))
# define tsan_decr(ptr) (sizeof(*(ptr)) == 8 ? _InterlockedExchangeAdd64((ptr), -1) \
: _InterlockedExchangeAdd((ptr), -1))
# else
# define tsan_counter(ptr) _InterlockedExchangeAdd((ptr), 1)
# define tsan_decr(ptr) _InterlockedExchangeAdd((ptr), -1)
# endif
# if !defined(_ISO_VOLATILE)
# define tsan_ld_acq(ptr) (*(ptr))
# define tsan_st_rel(ptr, val) (*(ptr) = (val))
# endif
#endif
#ifndef TSAN_QUALIFIER
# define TSAN_QUALIFIER volatile
# define tsan_load(ptr) (*(ptr))
# define tsan_store(ptr, val) (*(ptr) = (val))
# define tsan_counter(ptr) ((*(ptr))++)
# define tsan_decr(ptr) ((*(ptr))--)
/*
* Lack of tsan_ld_acq and tsan_ld_rel means that compiler support is not
* sophisticated enough to support them. Code that relies on them should be
* protected with #ifdef tsan_ld_acq with locked fallback.
*/
#endif
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 6cae1a36510f..b49f88129e28 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -1,273 +1,274 @@
/*
- * Copyright 1995-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_ERR_H
# define HEADER_ERR_H
# include <openssl/e_os2.h>
# ifndef OPENSSL_NO_STDIO
# include <stdio.h>
# include <stdlib.h>
# endif
# include <openssl/ossl_typ.h>
# include <openssl/bio.h>
# include <openssl/lhash.h>
#ifdef __cplusplus
extern "C" {
#endif
# ifndef OPENSSL_NO_ERR
# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,d,e)
# else
# define ERR_PUT_error(a,b,c,d,e) ERR_put_error(a,b,c,NULL,0)
# endif
# include <errno.h>
# define ERR_TXT_MALLOCED 0x01
# define ERR_TXT_STRING 0x02
# define ERR_FLAG_MARK 0x01
+# define ERR_FLAG_CLEAR 0x02
# define ERR_NUM_ERRORS 16
typedef struct err_state_st {
int err_flags[ERR_NUM_ERRORS];
unsigned long err_buffer[ERR_NUM_ERRORS];
char *err_data[ERR_NUM_ERRORS];
int err_data_flags[ERR_NUM_ERRORS];
const char *err_file[ERR_NUM_ERRORS];
int err_line[ERR_NUM_ERRORS];
int top, bottom;
} ERR_STATE;
/* library */
# define ERR_LIB_NONE 1
# define ERR_LIB_SYS 2
# define ERR_LIB_BN 3
# define ERR_LIB_RSA 4
# define ERR_LIB_DH 5
# define ERR_LIB_EVP 6
# define ERR_LIB_BUF 7
# define ERR_LIB_OBJ 8
# define ERR_LIB_PEM 9
# define ERR_LIB_DSA 10
# define ERR_LIB_X509 11
/* #define ERR_LIB_METH 12 */
# define ERR_LIB_ASN1 13
# define ERR_LIB_CONF 14
# define ERR_LIB_CRYPTO 15
# define ERR_LIB_EC 16
# define ERR_LIB_SSL 20
/* #define ERR_LIB_SSL23 21 */
/* #define ERR_LIB_SSL2 22 */
/* #define ERR_LIB_SSL3 23 */
/* #define ERR_LIB_RSAREF 30 */
/* #define ERR_LIB_PROXY 31 */
# define ERR_LIB_BIO 32
# define ERR_LIB_PKCS7 33
# define ERR_LIB_X509V3 34
# define ERR_LIB_PKCS12 35
# define ERR_LIB_RAND 36
# define ERR_LIB_DSO 37
# define ERR_LIB_ENGINE 38
# define ERR_LIB_OCSP 39
# define ERR_LIB_UI 40
# define ERR_LIB_COMP 41
# define ERR_LIB_ECDSA 42
# define ERR_LIB_ECDH 43
# define ERR_LIB_OSSL_STORE 44
# define ERR_LIB_FIPS 45
# define ERR_LIB_CMS 46
# define ERR_LIB_TS 47
# define ERR_LIB_HMAC 48
/* # define ERR_LIB_JPAKE 49 */
# define ERR_LIB_CT 50
# define ERR_LIB_ASYNC 51
# define ERR_LIB_KDF 52
# define ERR_LIB_SM2 53
# define ERR_LIB_USER 128
# define SYSerr(f,r) ERR_PUT_error(ERR_LIB_SYS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define BNerr(f,r) ERR_PUT_error(ERR_LIB_BN,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define RSAerr(f,r) ERR_PUT_error(ERR_LIB_RSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define DHerr(f,r) ERR_PUT_error(ERR_LIB_DH,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define EVPerr(f,r) ERR_PUT_error(ERR_LIB_EVP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define BUFerr(f,r) ERR_PUT_error(ERR_LIB_BUF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define OBJerr(f,r) ERR_PUT_error(ERR_LIB_OBJ,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define PEMerr(f,r) ERR_PUT_error(ERR_LIB_PEM,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define DSAerr(f,r) ERR_PUT_error(ERR_LIB_DSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define X509err(f,r) ERR_PUT_error(ERR_LIB_X509,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define ASN1err(f,r) ERR_PUT_error(ERR_LIB_ASN1,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define CONFerr(f,r) ERR_PUT_error(ERR_LIB_CONF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define CRYPTOerr(f,r) ERR_PUT_error(ERR_LIB_CRYPTO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define ECerr(f,r) ERR_PUT_error(ERR_LIB_EC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define SSLerr(f,r) ERR_PUT_error(ERR_LIB_SSL,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define BIOerr(f,r) ERR_PUT_error(ERR_LIB_BIO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define PKCS7err(f,r) ERR_PUT_error(ERR_LIB_PKCS7,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define X509V3err(f,r) ERR_PUT_error(ERR_LIB_X509V3,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define PKCS12err(f,r) ERR_PUT_error(ERR_LIB_PKCS12,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define RANDerr(f,r) ERR_PUT_error(ERR_LIB_RAND,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define DSOerr(f,r) ERR_PUT_error(ERR_LIB_DSO,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define ENGINEerr(f,r) ERR_PUT_error(ERR_LIB_ENGINE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define OCSPerr(f,r) ERR_PUT_error(ERR_LIB_OCSP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define UIerr(f,r) ERR_PUT_error(ERR_LIB_UI,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define COMPerr(f,r) ERR_PUT_error(ERR_LIB_COMP,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define ECDSAerr(f,r) ERR_PUT_error(ERR_LIB_ECDSA,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define ECDHerr(f,r) ERR_PUT_error(ERR_LIB_ECDH,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define OSSL_STOREerr(f,r) ERR_PUT_error(ERR_LIB_OSSL_STORE,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define FIPSerr(f,r) ERR_PUT_error(ERR_LIB_FIPS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define CMSerr(f,r) ERR_PUT_error(ERR_LIB_CMS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define TSerr(f,r) ERR_PUT_error(ERR_LIB_TS,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define HMACerr(f,r) ERR_PUT_error(ERR_LIB_HMAC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define CTerr(f,r) ERR_PUT_error(ERR_LIB_CT,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define ASYNCerr(f,r) ERR_PUT_error(ERR_LIB_ASYNC,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define KDFerr(f,r) ERR_PUT_error(ERR_LIB_KDF,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define SM2err(f,r) ERR_PUT_error(ERR_LIB_SM2,(f),(r),OPENSSL_FILE,OPENSSL_LINE)
# define ERR_PACK(l,f,r) ( \
(((unsigned int)(l) & 0x0FF) << 24L) | \
(((unsigned int)(f) & 0xFFF) << 12L) | \
(((unsigned int)(r) & 0xFFF) ) )
# define ERR_GET_LIB(l) (int)(((l) >> 24L) & 0x0FFL)
# define ERR_GET_FUNC(l) (int)(((l) >> 12L) & 0xFFFL)
# define ERR_GET_REASON(l) (int)( (l) & 0xFFFL)
# define ERR_FATAL_ERROR(l) (int)( (l) & ERR_R_FATAL)
/* OS functions */
# define SYS_F_FOPEN 1
# define SYS_F_CONNECT 2
# define SYS_F_GETSERVBYNAME 3
# define SYS_F_SOCKET 4
# define SYS_F_IOCTLSOCKET 5
# define SYS_F_BIND 6
# define SYS_F_LISTEN 7
# define SYS_F_ACCEPT 8
# define SYS_F_WSASTARTUP 9/* Winsock stuff */
# define SYS_F_OPENDIR 10
# define SYS_F_FREAD 11
# define SYS_F_GETADDRINFO 12
# define SYS_F_GETNAMEINFO 13
# define SYS_F_SETSOCKOPT 14
# define SYS_F_GETSOCKOPT 15
# define SYS_F_GETSOCKNAME 16
# define SYS_F_GETHOSTBYNAME 17
# define SYS_F_FFLUSH 18
# define SYS_F_OPEN 19
# define SYS_F_CLOSE 20
# define SYS_F_IOCTL 21
# define SYS_F_STAT 22
# define SYS_F_FCNTL 23
# define SYS_F_FSTAT 24
/* reasons */
# define ERR_R_SYS_LIB ERR_LIB_SYS/* 2 */
# define ERR_R_BN_LIB ERR_LIB_BN/* 3 */
# define ERR_R_RSA_LIB ERR_LIB_RSA/* 4 */
# define ERR_R_DH_LIB ERR_LIB_DH/* 5 */
# define ERR_R_EVP_LIB ERR_LIB_EVP/* 6 */
# define ERR_R_BUF_LIB ERR_LIB_BUF/* 7 */
# define ERR_R_OBJ_LIB ERR_LIB_OBJ/* 8 */
# define ERR_R_PEM_LIB ERR_LIB_PEM/* 9 */
# define ERR_R_DSA_LIB ERR_LIB_DSA/* 10 */
# define ERR_R_X509_LIB ERR_LIB_X509/* 11 */
# define ERR_R_ASN1_LIB ERR_LIB_ASN1/* 13 */
# define ERR_R_EC_LIB ERR_LIB_EC/* 16 */
# define ERR_R_BIO_LIB ERR_LIB_BIO/* 32 */
# define ERR_R_PKCS7_LIB ERR_LIB_PKCS7/* 33 */
# define ERR_R_X509V3_LIB ERR_LIB_X509V3/* 34 */
# define ERR_R_ENGINE_LIB ERR_LIB_ENGINE/* 38 */
# define ERR_R_UI_LIB ERR_LIB_UI/* 40 */
# define ERR_R_ECDSA_LIB ERR_LIB_ECDSA/* 42 */
# define ERR_R_OSSL_STORE_LIB ERR_LIB_OSSL_STORE/* 44 */
# define ERR_R_NESTED_ASN1_ERROR 58
# define ERR_R_MISSING_ASN1_EOS 63
/* fatal error */
# define ERR_R_FATAL 64
# define ERR_R_MALLOC_FAILURE (1|ERR_R_FATAL)
# define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2|ERR_R_FATAL)
# define ERR_R_PASSED_NULL_PARAMETER (3|ERR_R_FATAL)
# define ERR_R_INTERNAL_ERROR (4|ERR_R_FATAL)
# define ERR_R_DISABLED (5|ERR_R_FATAL)
# define ERR_R_INIT_FAIL (6|ERR_R_FATAL)
# define ERR_R_PASSED_INVALID_ARGUMENT (7)
# define ERR_R_OPERATION_FAIL (8|ERR_R_FATAL)
/*
* 99 is the maximum possible ERR_R_... code, higher values are reserved for
* the individual libraries
*/
typedef struct ERR_string_data_st {
unsigned long error;
const char *string;
} ERR_STRING_DATA;
DEFINE_LHASH_OF(ERR_STRING_DATA);
void ERR_put_error(int lib, int func, int reason, const char *file, int line);
void ERR_set_error_data(char *data, int flags);
unsigned long ERR_get_error(void);
unsigned long ERR_get_error_line(const char **file, int *line);
unsigned long ERR_get_error_line_data(const char **file, int *line,
const char **data, int *flags);
unsigned long ERR_peek_error(void);
unsigned long ERR_peek_error_line(const char **file, int *line);
unsigned long ERR_peek_error_line_data(const char **file, int *line,
const char **data, int *flags);
unsigned long ERR_peek_last_error(void);
unsigned long ERR_peek_last_error_line(const char **file, int *line);
unsigned long ERR_peek_last_error_line_data(const char **file, int *line,
const char **data, int *flags);
void ERR_clear_error(void);
char *ERR_error_string(unsigned long e, char *buf);
void ERR_error_string_n(unsigned long e, char *buf, size_t len);
const char *ERR_lib_error_string(unsigned long e);
const char *ERR_func_error_string(unsigned long e);
const char *ERR_reason_error_string(unsigned long e);
void ERR_print_errors_cb(int (*cb) (const char *str, size_t len, void *u),
void *u);
# ifndef OPENSSL_NO_STDIO
void ERR_print_errors_fp(FILE *fp);
# endif
void ERR_print_errors(BIO *bp);
void ERR_add_error_data(int num, ...);
void ERR_add_error_vdata(int num, va_list args);
int ERR_load_strings(int lib, ERR_STRING_DATA *str);
int ERR_load_strings_const(const ERR_STRING_DATA *str);
int ERR_unload_strings(int lib, ERR_STRING_DATA *str);
int ERR_load_ERR_strings(void);
#if OPENSSL_API_COMPAT < 0x10100000L
# define ERR_load_crypto_strings() \
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
# define ERR_free_strings() while(0) continue
#endif
DEPRECATEDIN_1_1_0(void ERR_remove_thread_state(void *))
DEPRECATEDIN_1_0_0(void ERR_remove_state(unsigned long pid))
ERR_STATE *ERR_get_state(void);
int ERR_get_next_error_library(void);
int ERR_set_mark(void);
int ERR_pop_to_mark(void);
int ERR_clear_last_mark(void);
#ifdef __cplusplus
}
#endif
#endif
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index 9f05b5a3b7f5..dd1117d0fe2d 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -1,1633 +1,1634 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_ENVELOPE_H
# define HEADER_ENVELOPE_H
# include <openssl/opensslconf.h>
# include <openssl/ossl_typ.h>
# include <openssl/symhacks.h>
# include <openssl/bio.h>
# include <openssl/evperr.h>
# define EVP_MAX_MD_SIZE 64/* longest known is SHA512 */
# define EVP_MAX_KEY_LENGTH 64
# define EVP_MAX_IV_LENGTH 16
# define EVP_MAX_BLOCK_LENGTH 32
# define PKCS5_SALT_LEN 8
/* Default PKCS#5 iteration count */
# define PKCS5_DEFAULT_ITER 2048
# include <openssl/objects.h>
# define EVP_PK_RSA 0x0001
# define EVP_PK_DSA 0x0002
# define EVP_PK_DH 0x0004
# define EVP_PK_EC 0x0008
# define EVP_PKT_SIGN 0x0010
# define EVP_PKT_ENC 0x0020
# define EVP_PKT_EXCH 0x0040
# define EVP_PKS_RSA 0x0100
# define EVP_PKS_DSA 0x0200
# define EVP_PKS_EC 0x0400
# define EVP_PKEY_NONE NID_undef
# define EVP_PKEY_RSA NID_rsaEncryption
# define EVP_PKEY_RSA2 NID_rsa
# define EVP_PKEY_RSA_PSS NID_rsassaPss
# define EVP_PKEY_DSA NID_dsa
# define EVP_PKEY_DSA1 NID_dsa_2
# define EVP_PKEY_DSA2 NID_dsaWithSHA
# define EVP_PKEY_DSA3 NID_dsaWithSHA1
# define EVP_PKEY_DSA4 NID_dsaWithSHA1_2
# define EVP_PKEY_DH NID_dhKeyAgreement
# define EVP_PKEY_DHX NID_dhpublicnumber
# define EVP_PKEY_EC NID_X9_62_id_ecPublicKey
# define EVP_PKEY_SM2 NID_sm2
# define EVP_PKEY_HMAC NID_hmac
# define EVP_PKEY_CMAC NID_cmac
# define EVP_PKEY_SCRYPT NID_id_scrypt
# define EVP_PKEY_TLS1_PRF NID_tls1_prf
# define EVP_PKEY_HKDF NID_hkdf
# define EVP_PKEY_POLY1305 NID_poly1305
# define EVP_PKEY_SIPHASH NID_siphash
# define EVP_PKEY_X25519 NID_X25519
# define EVP_PKEY_ED25519 NID_ED25519
# define EVP_PKEY_X448 NID_X448
# define EVP_PKEY_ED448 NID_ED448
#ifdef __cplusplus
extern "C" {
#endif
# define EVP_PKEY_MO_SIGN 0x0001
# define EVP_PKEY_MO_VERIFY 0x0002
# define EVP_PKEY_MO_ENCRYPT 0x0004
# define EVP_PKEY_MO_DECRYPT 0x0008
# ifndef EVP_MD
EVP_MD *EVP_MD_meth_new(int md_type, int pkey_type);
EVP_MD *EVP_MD_meth_dup(const EVP_MD *md);
void EVP_MD_meth_free(EVP_MD *md);
int EVP_MD_meth_set_input_blocksize(EVP_MD *md, int blocksize);
int EVP_MD_meth_set_result_size(EVP_MD *md, int resultsize);
int EVP_MD_meth_set_app_datasize(EVP_MD *md, int datasize);
int EVP_MD_meth_set_flags(EVP_MD *md, unsigned long flags);
int EVP_MD_meth_set_init(EVP_MD *md, int (*init)(EVP_MD_CTX *ctx));
int EVP_MD_meth_set_update(EVP_MD *md, int (*update)(EVP_MD_CTX *ctx,
const void *data,
size_t count));
int EVP_MD_meth_set_final(EVP_MD *md, int (*final)(EVP_MD_CTX *ctx,
unsigned char *md));
int EVP_MD_meth_set_copy(EVP_MD *md, int (*copy)(EVP_MD_CTX *to,
const EVP_MD_CTX *from));
int EVP_MD_meth_set_cleanup(EVP_MD *md, int (*cleanup)(EVP_MD_CTX *ctx));
int EVP_MD_meth_set_ctrl(EVP_MD *md, int (*ctrl)(EVP_MD_CTX *ctx, int cmd,
int p1, void *p2));
int EVP_MD_meth_get_input_blocksize(const EVP_MD *md);
int EVP_MD_meth_get_result_size(const EVP_MD *md);
int EVP_MD_meth_get_app_datasize(const EVP_MD *md);
unsigned long EVP_MD_meth_get_flags(const EVP_MD *md);
int (*EVP_MD_meth_get_init(const EVP_MD *md))(EVP_MD_CTX *ctx);
int (*EVP_MD_meth_get_update(const EVP_MD *md))(EVP_MD_CTX *ctx,
const void *data,
size_t count);
int (*EVP_MD_meth_get_final(const EVP_MD *md))(EVP_MD_CTX *ctx,
unsigned char *md);
int (*EVP_MD_meth_get_copy(const EVP_MD *md))(EVP_MD_CTX *to,
const EVP_MD_CTX *from);
int (*EVP_MD_meth_get_cleanup(const EVP_MD *md))(EVP_MD_CTX *ctx);
int (*EVP_MD_meth_get_ctrl(const EVP_MD *md))(EVP_MD_CTX *ctx, int cmd,
int p1, void *p2);
/* digest can only handle a single block */
# define EVP_MD_FLAG_ONESHOT 0x0001
/* digest is extensible-output function, XOF */
# define EVP_MD_FLAG_XOF 0x0002
/* DigestAlgorithmIdentifier flags... */
# define EVP_MD_FLAG_DIGALGID_MASK 0x0018
/* NULL or absent parameter accepted. Use NULL */
# define EVP_MD_FLAG_DIGALGID_NULL 0x0000
/* NULL or absent parameter accepted. Use NULL for PKCS#1 otherwise absent */
# define EVP_MD_FLAG_DIGALGID_ABSENT 0x0008
/* Custom handling via ctrl */
# define EVP_MD_FLAG_DIGALGID_CUSTOM 0x0018
/* Note if suitable for use in FIPS mode */
# define EVP_MD_FLAG_FIPS 0x0400
/* Digest ctrls */
# define EVP_MD_CTRL_DIGALGID 0x1
# define EVP_MD_CTRL_MICALG 0x2
# define EVP_MD_CTRL_XOF_LEN 0x3
/* Minimum Algorithm specific ctrl value */
# define EVP_MD_CTRL_ALG_CTRL 0x1000
# endif /* !EVP_MD */
/* values for EVP_MD_CTX flags */
# define EVP_MD_CTX_FLAG_ONESHOT 0x0001/* digest update will be
* called once only */
# define EVP_MD_CTX_FLAG_CLEANED 0x0002/* context has already been
* cleaned */
# define EVP_MD_CTX_FLAG_REUSE 0x0004/* Don't free up ctx->md_data
* in EVP_MD_CTX_reset */
/*
* FIPS and pad options are ignored in 1.0.0, definitions are here so we
* don't accidentally reuse the values for other purposes.
*/
# define EVP_MD_CTX_FLAG_NON_FIPS_ALLOW 0x0008/* Allow use of non FIPS
* digest in FIPS mode */
/*
* The following PAD options are also currently ignored in 1.0.0, digest
* parameters are handled through EVP_DigestSign*() and EVP_DigestVerify*()
* instead.
*/
# define EVP_MD_CTX_FLAG_PAD_MASK 0xF0/* RSA mode to use */
# define EVP_MD_CTX_FLAG_PAD_PKCS1 0x00/* PKCS#1 v1.5 mode */
# define EVP_MD_CTX_FLAG_PAD_X931 0x10/* X9.31 mode */
# define EVP_MD_CTX_FLAG_PAD_PSS 0x20/* PSS mode */
# define EVP_MD_CTX_FLAG_NO_INIT 0x0100/* Don't initialize md_data */
/*
* Some functions such as EVP_DigestSign only finalise copies of internal
* contexts so additional data can be included after the finalisation call.
* This is inefficient if this functionality is not required: it is disabled
* if the following flag is set.
*/
# define EVP_MD_CTX_FLAG_FINALISE 0x0200
/* NOTE: 0x0400 is reserved for internal usage in evp_int.h */
EVP_CIPHER *EVP_CIPHER_meth_new(int cipher_type, int block_size, int key_len);
EVP_CIPHER *EVP_CIPHER_meth_dup(const EVP_CIPHER *cipher);
void EVP_CIPHER_meth_free(EVP_CIPHER *cipher);
int EVP_CIPHER_meth_set_iv_length(EVP_CIPHER *cipher, int iv_len);
int EVP_CIPHER_meth_set_flags(EVP_CIPHER *cipher, unsigned long flags);
int EVP_CIPHER_meth_set_impl_ctx_size(EVP_CIPHER *cipher, int ctx_size);
int EVP_CIPHER_meth_set_init(EVP_CIPHER *cipher,
int (*init) (EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc));
int EVP_CIPHER_meth_set_do_cipher(EVP_CIPHER *cipher,
int (*do_cipher) (EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl));
int EVP_CIPHER_meth_set_cleanup(EVP_CIPHER *cipher,
int (*cleanup) (EVP_CIPHER_CTX *));
int EVP_CIPHER_meth_set_set_asn1_params(EVP_CIPHER *cipher,
int (*set_asn1_parameters) (EVP_CIPHER_CTX *,
ASN1_TYPE *));
int EVP_CIPHER_meth_set_get_asn1_params(EVP_CIPHER *cipher,
int (*get_asn1_parameters) (EVP_CIPHER_CTX *,
ASN1_TYPE *));
int EVP_CIPHER_meth_set_ctrl(EVP_CIPHER *cipher,
int (*ctrl) (EVP_CIPHER_CTX *, int type,
int arg, void *ptr));
int (*EVP_CIPHER_meth_get_init(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
const unsigned char *key,
const unsigned char *iv,
int enc);
int (*EVP_CIPHER_meth_get_do_cipher(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *ctx,
unsigned char *out,
const unsigned char *in,
size_t inl);
int (*EVP_CIPHER_meth_get_cleanup(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *);
int (*EVP_CIPHER_meth_get_set_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
ASN1_TYPE *);
int (*EVP_CIPHER_meth_get_get_asn1_params(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
ASN1_TYPE *);
int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *,
int type, int arg,
void *ptr);
/* Values for cipher flags */
/* Modes for ciphers */
# define EVP_CIPH_STREAM_CIPHER 0x0
# define EVP_CIPH_ECB_MODE 0x1
# define EVP_CIPH_CBC_MODE 0x2
# define EVP_CIPH_CFB_MODE 0x3
# define EVP_CIPH_OFB_MODE 0x4
# define EVP_CIPH_CTR_MODE 0x5
# define EVP_CIPH_GCM_MODE 0x6
# define EVP_CIPH_CCM_MODE 0x7
# define EVP_CIPH_XTS_MODE 0x10001
# define EVP_CIPH_WRAP_MODE 0x10002
# define EVP_CIPH_OCB_MODE 0x10003
# define EVP_CIPH_MODE 0xF0007
/* Set if variable length cipher */
# define EVP_CIPH_VARIABLE_LENGTH 0x8
/* Set if the iv handling should be done by the cipher itself */
# define EVP_CIPH_CUSTOM_IV 0x10
/* Set if the cipher's init() function should be called if key is NULL */
# define EVP_CIPH_ALWAYS_CALL_INIT 0x20
/* Call ctrl() to init cipher parameters */
# define EVP_CIPH_CTRL_INIT 0x40
/* Don't use standard key length function */
# define EVP_CIPH_CUSTOM_KEY_LENGTH 0x80
/* Don't use standard block padding */
# define EVP_CIPH_NO_PADDING 0x100
/* cipher handles random key generation */
# define EVP_CIPH_RAND_KEY 0x200
/* cipher has its own additional copying logic */
# define EVP_CIPH_CUSTOM_COPY 0x400
/* Allow use default ASN1 get/set iv */
# define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000
/* Buffer length in bits not bytes: CFB1 mode only */
# define EVP_CIPH_FLAG_LENGTH_BITS 0x2000
/* Note if suitable for use in FIPS mode */
# define EVP_CIPH_FLAG_FIPS 0x4000
/* Allow non FIPS cipher in FIPS mode */
# define EVP_CIPH_FLAG_NON_FIPS_ALLOW 0x8000
/*
* Cipher handles any and all padding logic as well as finalisation.
*/
# define EVP_CIPH_FLAG_CUSTOM_CIPHER 0x100000
# define EVP_CIPH_FLAG_AEAD_CIPHER 0x200000
# define EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK 0x400000
/* Cipher can handle pipeline operations */
# define EVP_CIPH_FLAG_PIPELINE 0X800000
/*
* Cipher context flag to indicate we can handle wrap mode: if allowed in
* older applications it could overflow buffers.
*/
# define EVP_CIPHER_CTX_FLAG_WRAP_ALLOW 0x1
/* ctrl() values */
# define EVP_CTRL_INIT 0x0
# define EVP_CTRL_SET_KEY_LENGTH 0x1
# define EVP_CTRL_GET_RC2_KEY_BITS 0x2
# define EVP_CTRL_SET_RC2_KEY_BITS 0x3
# define EVP_CTRL_GET_RC5_ROUNDS 0x4
# define EVP_CTRL_SET_RC5_ROUNDS 0x5
# define EVP_CTRL_RAND_KEY 0x6
# define EVP_CTRL_PBE_PRF_NID 0x7
# define EVP_CTRL_COPY 0x8
# define EVP_CTRL_AEAD_SET_IVLEN 0x9
# define EVP_CTRL_AEAD_GET_TAG 0x10
# define EVP_CTRL_AEAD_SET_TAG 0x11
# define EVP_CTRL_AEAD_SET_IV_FIXED 0x12
# define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN
# define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG
# define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG
# define EVP_CTRL_GCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED
# define EVP_CTRL_GCM_IV_GEN 0x13
# define EVP_CTRL_CCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN
# define EVP_CTRL_CCM_GET_TAG EVP_CTRL_AEAD_GET_TAG
# define EVP_CTRL_CCM_SET_TAG EVP_CTRL_AEAD_SET_TAG
# define EVP_CTRL_CCM_SET_IV_FIXED EVP_CTRL_AEAD_SET_IV_FIXED
# define EVP_CTRL_CCM_SET_L 0x14
# define EVP_CTRL_CCM_SET_MSGLEN 0x15
/*
* AEAD cipher deduces payload length and returns number of bytes required to
* store MAC and eventual padding. Subsequent call to EVP_Cipher even
* appends/verifies MAC.
*/
# define EVP_CTRL_AEAD_TLS1_AAD 0x16
/* Used by composite AEAD ciphers, no-op in GCM, CCM... */
# define EVP_CTRL_AEAD_SET_MAC_KEY 0x17
/* Set the GCM invocation field, decrypt only */
# define EVP_CTRL_GCM_SET_IV_INV 0x18
# define EVP_CTRL_TLS1_1_MULTIBLOCK_AAD 0x19
# define EVP_CTRL_TLS1_1_MULTIBLOCK_ENCRYPT 0x1a
# define EVP_CTRL_TLS1_1_MULTIBLOCK_DECRYPT 0x1b
# define EVP_CTRL_TLS1_1_MULTIBLOCK_MAX_BUFSIZE 0x1c
# define EVP_CTRL_SSL3_MASTER_SECRET 0x1d
/* EVP_CTRL_SET_SBOX takes the char * specifying S-boxes */
# define EVP_CTRL_SET_SBOX 0x1e
/*
* EVP_CTRL_SBOX_USED takes a 'size_t' and 'char *', pointing at a
* pre-allocated buffer with specified size
*/
# define EVP_CTRL_SBOX_USED 0x1f
/* EVP_CTRL_KEY_MESH takes 'size_t' number of bytes to mesh the key after,
* 0 switches meshing off
*/
# define EVP_CTRL_KEY_MESH 0x20
/* EVP_CTRL_BLOCK_PADDING_MODE takes the padding mode */
# define EVP_CTRL_BLOCK_PADDING_MODE 0x21
/* Set the output buffers to use for a pipelined operation */
# define EVP_CTRL_SET_PIPELINE_OUTPUT_BUFS 0x22
/* Set the input buffers to use for a pipelined operation */
# define EVP_CTRL_SET_PIPELINE_INPUT_BUFS 0x23
/* Set the input buffer lengths to use for a pipelined operation */
# define EVP_CTRL_SET_PIPELINE_INPUT_LENS 0x24
/* Padding modes */
#define EVP_PADDING_PKCS7 1
#define EVP_PADDING_ISO7816_4 2
#define EVP_PADDING_ANSI923 3
#define EVP_PADDING_ISO10126 4
#define EVP_PADDING_ZERO 5
/* RFC 5246 defines additional data to be 13 bytes in length */
# define EVP_AEAD_TLS1_AAD_LEN 13
typedef struct {
unsigned char *out;
const unsigned char *inp;
size_t len;
unsigned int interleave;
} EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM;
/* GCM TLS constants */
/* Length of fixed part of IV derived from PRF */
# define EVP_GCM_TLS_FIXED_IV_LEN 4
/* Length of explicit part of IV part of TLS records */
# define EVP_GCM_TLS_EXPLICIT_IV_LEN 8
/* Length of tag for TLS */
# define EVP_GCM_TLS_TAG_LEN 16
/* CCM TLS constants */
/* Length of fixed part of IV derived from PRF */
# define EVP_CCM_TLS_FIXED_IV_LEN 4
/* Length of explicit part of IV part of TLS records */
# define EVP_CCM_TLS_EXPLICIT_IV_LEN 8
/* Total length of CCM IV length for TLS */
# define EVP_CCM_TLS_IV_LEN 12
/* Length of tag for TLS */
# define EVP_CCM_TLS_TAG_LEN 16
/* Length of CCM8 tag for TLS */
# define EVP_CCM8_TLS_TAG_LEN 8
/* Length of tag for TLS */
# define EVP_CHACHAPOLY_TLS_TAG_LEN 16
typedef struct evp_cipher_info_st {
const EVP_CIPHER *cipher;
unsigned char iv[EVP_MAX_IV_LENGTH];
} EVP_CIPHER_INFO;
/* Password based encryption function */
typedef int (EVP_PBE_KEYGEN) (EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *cipher, const EVP_MD *md,
int en_de);
# ifndef OPENSSL_NO_RSA
# define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
(char *)(rsa))
# endif
# ifndef OPENSSL_NO_DSA
# define EVP_PKEY_assign_DSA(pkey,dsa) EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
(char *)(dsa))
# endif
# ifndef OPENSSL_NO_DH
# define EVP_PKEY_assign_DH(pkey,dh) EVP_PKEY_assign((pkey),EVP_PKEY_DH,\
(char *)(dh))
# endif
# ifndef OPENSSL_NO_EC
# define EVP_PKEY_assign_EC_KEY(pkey,eckey) EVP_PKEY_assign((pkey),EVP_PKEY_EC,\
(char *)(eckey))
# endif
# ifndef OPENSSL_NO_SIPHASH
# define EVP_PKEY_assign_SIPHASH(pkey,shkey) EVP_PKEY_assign((pkey),EVP_PKEY_SIPHASH,\
(char *)(shkey))
# endif
# ifndef OPENSSL_NO_POLY1305
# define EVP_PKEY_assign_POLY1305(pkey,polykey) EVP_PKEY_assign((pkey),EVP_PKEY_POLY1305,\
(char *)(polykey))
# endif
/* Add some extra combinations */
# define EVP_get_digestbynid(a) EVP_get_digestbyname(OBJ_nid2sn(a))
# define EVP_get_digestbyobj(a) EVP_get_digestbynid(OBJ_obj2nid(a))
# define EVP_get_cipherbynid(a) EVP_get_cipherbyname(OBJ_nid2sn(a))
# define EVP_get_cipherbyobj(a) EVP_get_cipherbynid(OBJ_obj2nid(a))
int EVP_MD_type(const EVP_MD *md);
# define EVP_MD_nid(e) EVP_MD_type(e)
# define EVP_MD_name(e) OBJ_nid2sn(EVP_MD_nid(e))
int EVP_MD_pkey_type(const EVP_MD *md);
int EVP_MD_size(const EVP_MD *md);
int EVP_MD_block_size(const EVP_MD *md);
unsigned long EVP_MD_flags(const EVP_MD *md);
const EVP_MD *EVP_MD_CTX_md(const EVP_MD_CTX *ctx);
int (*EVP_MD_CTX_update_fn(EVP_MD_CTX *ctx))(EVP_MD_CTX *ctx,
const void *data, size_t count);
void EVP_MD_CTX_set_update_fn(EVP_MD_CTX *ctx,
int (*update) (EVP_MD_CTX *ctx,
const void *data, size_t count));
# define EVP_MD_CTX_size(e) EVP_MD_size(EVP_MD_CTX_md(e))
# define EVP_MD_CTX_block_size(e) EVP_MD_block_size(EVP_MD_CTX_md(e))
# define EVP_MD_CTX_type(e) EVP_MD_type(EVP_MD_CTX_md(e))
EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx);
void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx);
void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx);
int EVP_CIPHER_nid(const EVP_CIPHER *cipher);
# define EVP_CIPHER_name(e) OBJ_nid2sn(EVP_CIPHER_nid(e))
int EVP_CIPHER_block_size(const EVP_CIPHER *cipher);
int EVP_CIPHER_impl_ctx_size(const EVP_CIPHER *cipher);
int EVP_CIPHER_key_length(const EVP_CIPHER *cipher);
int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher);
unsigned long EVP_CIPHER_flags(const EVP_CIPHER *cipher);
# define EVP_CIPHER_mode(e) (EVP_CIPHER_flags(e) & EVP_CIPH_MODE)
const EVP_CIPHER *EVP_CIPHER_CTX_cipher(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_encrypting(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_nid(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_block_size(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_key_length(const EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx);
const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx);
const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx);
unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx);
unsigned char *EVP_CIPHER_CTX_buf_noconst(EVP_CIPHER_CTX *ctx);
int EVP_CIPHER_CTX_num(const EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_set_num(EVP_CIPHER_CTX *ctx, int num);
int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in);
void *EVP_CIPHER_CTX_get_app_data(const EVP_CIPHER_CTX *ctx);
void EVP_CIPHER_CTX_set_app_data(EVP_CIPHER_CTX *ctx, void *data);
void *EVP_CIPHER_CTX_get_cipher_data(const EVP_CIPHER_CTX *ctx);
void *EVP_CIPHER_CTX_set_cipher_data(EVP_CIPHER_CTX *ctx, void *cipher_data);
# define EVP_CIPHER_CTX_type(c) EVP_CIPHER_type(EVP_CIPHER_CTX_cipher(c))
# if OPENSSL_API_COMPAT < 0x10100000L
# define EVP_CIPHER_CTX_flags(c) EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(c))
# endif
# define EVP_CIPHER_CTX_mode(c) EVP_CIPHER_mode(EVP_CIPHER_CTX_cipher(c))
# define EVP_ENCODE_LENGTH(l) ((((l)+2)/3*4)+((l)/48+1)*2+80)
# define EVP_DECODE_LENGTH(l) (((l)+3)/4*3+80)
# define EVP_SignInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c)
# define EVP_SignInit(a,b) EVP_DigestInit(a,b)
# define EVP_SignUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
# define EVP_VerifyInit_ex(a,b,c) EVP_DigestInit_ex(a,b,c)
# define EVP_VerifyInit(a,b) EVP_DigestInit(a,b)
# define EVP_VerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
# define EVP_OpenUpdate(a,b,c,d,e) EVP_DecryptUpdate(a,b,c,d,e)
# define EVP_SealUpdate(a,b,c,d,e) EVP_EncryptUpdate(a,b,c,d,e)
# define EVP_DigestSignUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
# define EVP_DigestVerifyUpdate(a,b,c) EVP_DigestUpdate(a,b,c)
# ifdef CONST_STRICT
void BIO_set_md(BIO *, const EVP_MD *md);
# else
# define BIO_set_md(b,md) BIO_ctrl(b,BIO_C_SET_MD,0,(char *)(md))
# endif
# define BIO_get_md(b,mdp) BIO_ctrl(b,BIO_C_GET_MD,0,(char *)(mdp))
# define BIO_get_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_GET_MD_CTX,0, \
(char *)(mdcp))
# define BIO_set_md_ctx(b,mdcp) BIO_ctrl(b,BIO_C_SET_MD_CTX,0, \
(char *)(mdcp))
# define BIO_get_cipher_status(b) BIO_ctrl(b,BIO_C_GET_CIPHER_STATUS,0,NULL)
# define BIO_get_cipher_ctx(b,c_pp) BIO_ctrl(b,BIO_C_GET_CIPHER_CTX,0, \
(char *)(c_pp))
/*__owur*/ int EVP_Cipher(EVP_CIPHER_CTX *c,
unsigned char *out,
const unsigned char *in, unsigned int inl);
# define EVP_add_cipher_alias(n,alias) \
OBJ_NAME_add((alias),OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS,(n))
# define EVP_add_digest_alias(n,alias) \
OBJ_NAME_add((alias),OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS,(n))
# define EVP_delete_cipher_alias(alias) \
OBJ_NAME_remove(alias,OBJ_NAME_TYPE_CIPHER_METH|OBJ_NAME_ALIAS);
# define EVP_delete_digest_alias(alias) \
OBJ_NAME_remove(alias,OBJ_NAME_TYPE_MD_METH|OBJ_NAME_ALIAS);
int EVP_MD_CTX_ctrl(EVP_MD_CTX *ctx, int cmd, int p1, void *p2);
EVP_MD_CTX *EVP_MD_CTX_new(void);
int EVP_MD_CTX_reset(EVP_MD_CTX *ctx);
void EVP_MD_CTX_free(EVP_MD_CTX *ctx);
# define EVP_MD_CTX_create() EVP_MD_CTX_new()
# define EVP_MD_CTX_init(ctx) EVP_MD_CTX_reset((ctx))
# define EVP_MD_CTX_destroy(ctx) EVP_MD_CTX_free((ctx))
__owur int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in);
void EVP_MD_CTX_set_flags(EVP_MD_CTX *ctx, int flags);
void EVP_MD_CTX_clear_flags(EVP_MD_CTX *ctx, int flags);
int EVP_MD_CTX_test_flags(const EVP_MD_CTX *ctx, int flags);
__owur int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type,
ENGINE *impl);
__owur int EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d,
size_t cnt);
__owur int EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md,
unsigned int *s);
__owur int EVP_Digest(const void *data, size_t count,
unsigned char *md, unsigned int *size,
const EVP_MD *type, ENGINE *impl);
__owur int EVP_MD_CTX_copy(EVP_MD_CTX *out, const EVP_MD_CTX *in);
__owur int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
__owur int EVP_DigestFinal(EVP_MD_CTX *ctx, unsigned char *md,
unsigned int *s);
__owur int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md,
size_t len);
int EVP_read_pw_string(char *buf, int length, const char *prompt, int verify);
int EVP_read_pw_string_min(char *buf, int minlen, int maxlen,
const char *prompt, int verify);
void EVP_set_pw_prompt(const char *prompt);
char *EVP_get_pw_prompt(void);
__owur int EVP_BytesToKey(const EVP_CIPHER *type, const EVP_MD *md,
const unsigned char *salt,
const unsigned char *data, int datal, int count,
unsigned char *key, unsigned char *iv);
void EVP_CIPHER_CTX_set_flags(EVP_CIPHER_CTX *ctx, int flags);
void EVP_CIPHER_CTX_clear_flags(EVP_CIPHER_CTX *ctx, int flags);
int EVP_CIPHER_CTX_test_flags(const EVP_CIPHER_CTX *ctx, int flags);
__owur int EVP_EncryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv);
/*__owur*/ int EVP_EncryptInit_ex(EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher, ENGINE *impl,
const unsigned char *key,
const unsigned char *iv);
/*__owur*/ int EVP_EncryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
/*__owur*/ int EVP_EncryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl);
/*__owur*/ int EVP_EncryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl);
__owur int EVP_DecryptInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv);
/*__owur*/ int EVP_DecryptInit_ex(EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher, ENGINE *impl,
const unsigned char *key,
const unsigned char *iv);
/*__owur*/ int EVP_DecryptUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
__owur int EVP_DecryptFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm,
int *outl);
/*__owur*/ int EVP_DecryptFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm,
int *outl);
__owur int EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher,
const unsigned char *key, const unsigned char *iv,
int enc);
/*__owur*/ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx,
const EVP_CIPHER *cipher, ENGINE *impl,
const unsigned char *key,
const unsigned char *iv, int enc);
__owur int EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out,
int *outl, const unsigned char *in, int inl);
__owur int EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *outm,
int *outl);
__owur int EVP_CipherFinal_ex(EVP_CIPHER_CTX *ctx, unsigned char *outm,
int *outl);
__owur int EVP_SignFinal(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s,
EVP_PKEY *pkey);
__owur int EVP_DigestSign(EVP_MD_CTX *ctx, unsigned char *sigret,
size_t *siglen, const unsigned char *tbs,
size_t tbslen);
__owur int EVP_VerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sigbuf,
unsigned int siglen, EVP_PKEY *pkey);
__owur int EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret,
size_t siglen, const unsigned char *tbs,
size_t tbslen);
/*__owur*/ int EVP_DigestSignInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e,
EVP_PKEY *pkey);
__owur int EVP_DigestSignFinal(EVP_MD_CTX *ctx, unsigned char *sigret,
size_t *siglen);
__owur int EVP_DigestVerifyInit(EVP_MD_CTX *ctx, EVP_PKEY_CTX **pctx,
const EVP_MD *type, ENGINE *e,
EVP_PKEY *pkey);
__owur int EVP_DigestVerifyFinal(EVP_MD_CTX *ctx, const unsigned char *sig,
size_t siglen);
# ifndef OPENSSL_NO_RSA
__owur int EVP_OpenInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
const unsigned char *ek, int ekl,
const unsigned char *iv, EVP_PKEY *priv);
__owur int EVP_OpenFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
__owur int EVP_SealInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type,
unsigned char **ek, int *ekl, unsigned char *iv,
EVP_PKEY **pubk, int npubk);
__owur int EVP_SealFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
# endif
EVP_ENCODE_CTX *EVP_ENCODE_CTX_new(void);
void EVP_ENCODE_CTX_free(EVP_ENCODE_CTX *ctx);
int EVP_ENCODE_CTX_copy(EVP_ENCODE_CTX *dctx, EVP_ENCODE_CTX *sctx);
int EVP_ENCODE_CTX_num(EVP_ENCODE_CTX *ctx);
void EVP_EncodeInit(EVP_ENCODE_CTX *ctx);
int EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl);
void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl);
int EVP_EncodeBlock(unsigned char *t, const unsigned char *f, int n);
void EVP_DecodeInit(EVP_ENCODE_CTX *ctx);
int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, unsigned char *out, int *outl,
const unsigned char *in, int inl);
int EVP_DecodeFinal(EVP_ENCODE_CTX *ctx, unsigned
char *out, int *outl);
int EVP_DecodeBlock(unsigned char *t, const unsigned char *f, int n);
# if OPENSSL_API_COMPAT < 0x10100000L
# define EVP_CIPHER_CTX_init(c) EVP_CIPHER_CTX_reset(c)
# define EVP_CIPHER_CTX_cleanup(c) EVP_CIPHER_CTX_reset(c)
# endif
EVP_CIPHER_CTX *EVP_CIPHER_CTX_new(void);
int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c);
void EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *c);
int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
int EVP_CIPHER_CTX_set_padding(EVP_CIPHER_CTX *c, int pad);
int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key);
const BIO_METHOD *BIO_f_md(void);
const BIO_METHOD *BIO_f_base64(void);
const BIO_METHOD *BIO_f_cipher(void);
const BIO_METHOD *BIO_f_reliable(void);
__owur int BIO_set_cipher(BIO *b, const EVP_CIPHER *c, const unsigned char *k,
const unsigned char *i, int enc);
const EVP_MD *EVP_md_null(void);
# ifndef OPENSSL_NO_MD2
const EVP_MD *EVP_md2(void);
# endif
# ifndef OPENSSL_NO_MD4
const EVP_MD *EVP_md4(void);
# endif
# ifndef OPENSSL_NO_MD5
const EVP_MD *EVP_md5(void);
const EVP_MD *EVP_md5_sha1(void);
# endif
# ifndef OPENSSL_NO_BLAKE2
const EVP_MD *EVP_blake2b512(void);
const EVP_MD *EVP_blake2s256(void);
# endif
const EVP_MD *EVP_sha1(void);
const EVP_MD *EVP_sha224(void);
const EVP_MD *EVP_sha256(void);
const EVP_MD *EVP_sha384(void);
const EVP_MD *EVP_sha512(void);
const EVP_MD *EVP_sha512_224(void);
const EVP_MD *EVP_sha512_256(void);
const EVP_MD *EVP_sha3_224(void);
const EVP_MD *EVP_sha3_256(void);
const EVP_MD *EVP_sha3_384(void);
const EVP_MD *EVP_sha3_512(void);
const EVP_MD *EVP_shake128(void);
const EVP_MD *EVP_shake256(void);
# ifndef OPENSSL_NO_MDC2
const EVP_MD *EVP_mdc2(void);
# endif
# ifndef OPENSSL_NO_RMD160
const EVP_MD *EVP_ripemd160(void);
# endif
# ifndef OPENSSL_NO_WHIRLPOOL
const EVP_MD *EVP_whirlpool(void);
# endif
# ifndef OPENSSL_NO_SM3
const EVP_MD *EVP_sm3(void);
# endif
const EVP_CIPHER *EVP_enc_null(void); /* does nothing :-) */
# ifndef OPENSSL_NO_DES
const EVP_CIPHER *EVP_des_ecb(void);
const EVP_CIPHER *EVP_des_ede(void);
const EVP_CIPHER *EVP_des_ede3(void);
const EVP_CIPHER *EVP_des_ede_ecb(void);
const EVP_CIPHER *EVP_des_ede3_ecb(void);
const EVP_CIPHER *EVP_des_cfb64(void);
# define EVP_des_cfb EVP_des_cfb64
const EVP_CIPHER *EVP_des_cfb1(void);
const EVP_CIPHER *EVP_des_cfb8(void);
const EVP_CIPHER *EVP_des_ede_cfb64(void);
# define EVP_des_ede_cfb EVP_des_ede_cfb64
const EVP_CIPHER *EVP_des_ede3_cfb64(void);
# define EVP_des_ede3_cfb EVP_des_ede3_cfb64
const EVP_CIPHER *EVP_des_ede3_cfb1(void);
const EVP_CIPHER *EVP_des_ede3_cfb8(void);
const EVP_CIPHER *EVP_des_ofb(void);
const EVP_CIPHER *EVP_des_ede_ofb(void);
const EVP_CIPHER *EVP_des_ede3_ofb(void);
const EVP_CIPHER *EVP_des_cbc(void);
const EVP_CIPHER *EVP_des_ede_cbc(void);
const EVP_CIPHER *EVP_des_ede3_cbc(void);
const EVP_CIPHER *EVP_desx_cbc(void);
const EVP_CIPHER *EVP_des_ede3_wrap(void);
/*
* This should now be supported through the dev_crypto ENGINE. But also, why
* are rc4 and md5 declarations made here inside a "NO_DES" precompiler
* branch?
*/
# endif
# ifndef OPENSSL_NO_RC4
const EVP_CIPHER *EVP_rc4(void);
const EVP_CIPHER *EVP_rc4_40(void);
# ifndef OPENSSL_NO_MD5
const EVP_CIPHER *EVP_rc4_hmac_md5(void);
# endif
# endif
# ifndef OPENSSL_NO_IDEA
const EVP_CIPHER *EVP_idea_ecb(void);
const EVP_CIPHER *EVP_idea_cfb64(void);
# define EVP_idea_cfb EVP_idea_cfb64
const EVP_CIPHER *EVP_idea_ofb(void);
const EVP_CIPHER *EVP_idea_cbc(void);
# endif
# ifndef OPENSSL_NO_RC2
const EVP_CIPHER *EVP_rc2_ecb(void);
const EVP_CIPHER *EVP_rc2_cbc(void);
const EVP_CIPHER *EVP_rc2_40_cbc(void);
const EVP_CIPHER *EVP_rc2_64_cbc(void);
const EVP_CIPHER *EVP_rc2_cfb64(void);
# define EVP_rc2_cfb EVP_rc2_cfb64
const EVP_CIPHER *EVP_rc2_ofb(void);
# endif
# ifndef OPENSSL_NO_BF
const EVP_CIPHER *EVP_bf_ecb(void);
const EVP_CIPHER *EVP_bf_cbc(void);
const EVP_CIPHER *EVP_bf_cfb64(void);
# define EVP_bf_cfb EVP_bf_cfb64
const EVP_CIPHER *EVP_bf_ofb(void);
# endif
# ifndef OPENSSL_NO_CAST
const EVP_CIPHER *EVP_cast5_ecb(void);
const EVP_CIPHER *EVP_cast5_cbc(void);
const EVP_CIPHER *EVP_cast5_cfb64(void);
# define EVP_cast5_cfb EVP_cast5_cfb64
const EVP_CIPHER *EVP_cast5_ofb(void);
# endif
# ifndef OPENSSL_NO_RC5
const EVP_CIPHER *EVP_rc5_32_12_16_cbc(void);
const EVP_CIPHER *EVP_rc5_32_12_16_ecb(void);
const EVP_CIPHER *EVP_rc5_32_12_16_cfb64(void);
# define EVP_rc5_32_12_16_cfb EVP_rc5_32_12_16_cfb64
const EVP_CIPHER *EVP_rc5_32_12_16_ofb(void);
# endif
const EVP_CIPHER *EVP_aes_128_ecb(void);
const EVP_CIPHER *EVP_aes_128_cbc(void);
const EVP_CIPHER *EVP_aes_128_cfb1(void);
const EVP_CIPHER *EVP_aes_128_cfb8(void);
const EVP_CIPHER *EVP_aes_128_cfb128(void);
# define EVP_aes_128_cfb EVP_aes_128_cfb128
const EVP_CIPHER *EVP_aes_128_ofb(void);
const EVP_CIPHER *EVP_aes_128_ctr(void);
const EVP_CIPHER *EVP_aes_128_ccm(void);
const EVP_CIPHER *EVP_aes_128_gcm(void);
const EVP_CIPHER *EVP_aes_128_xts(void);
const EVP_CIPHER *EVP_aes_128_wrap(void);
const EVP_CIPHER *EVP_aes_128_wrap_pad(void);
# ifndef OPENSSL_NO_OCB
const EVP_CIPHER *EVP_aes_128_ocb(void);
# endif
const EVP_CIPHER *EVP_aes_192_ecb(void);
const EVP_CIPHER *EVP_aes_192_cbc(void);
const EVP_CIPHER *EVP_aes_192_cfb1(void);
const EVP_CIPHER *EVP_aes_192_cfb8(void);
const EVP_CIPHER *EVP_aes_192_cfb128(void);
# define EVP_aes_192_cfb EVP_aes_192_cfb128
const EVP_CIPHER *EVP_aes_192_ofb(void);
const EVP_CIPHER *EVP_aes_192_ctr(void);
const EVP_CIPHER *EVP_aes_192_ccm(void);
const EVP_CIPHER *EVP_aes_192_gcm(void);
const EVP_CIPHER *EVP_aes_192_wrap(void);
const EVP_CIPHER *EVP_aes_192_wrap_pad(void);
# ifndef OPENSSL_NO_OCB
const EVP_CIPHER *EVP_aes_192_ocb(void);
# endif
const EVP_CIPHER *EVP_aes_256_ecb(void);
const EVP_CIPHER *EVP_aes_256_cbc(void);
const EVP_CIPHER *EVP_aes_256_cfb1(void);
const EVP_CIPHER *EVP_aes_256_cfb8(void);
const EVP_CIPHER *EVP_aes_256_cfb128(void);
# define EVP_aes_256_cfb EVP_aes_256_cfb128
const EVP_CIPHER *EVP_aes_256_ofb(void);
const EVP_CIPHER *EVP_aes_256_ctr(void);
const EVP_CIPHER *EVP_aes_256_ccm(void);
const EVP_CIPHER *EVP_aes_256_gcm(void);
const EVP_CIPHER *EVP_aes_256_xts(void);
const EVP_CIPHER *EVP_aes_256_wrap(void);
const EVP_CIPHER *EVP_aes_256_wrap_pad(void);
# ifndef OPENSSL_NO_OCB
const EVP_CIPHER *EVP_aes_256_ocb(void);
# endif
const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void);
const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void);
const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha256(void);
const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha256(void);
# ifndef OPENSSL_NO_ARIA
const EVP_CIPHER *EVP_aria_128_ecb(void);
const EVP_CIPHER *EVP_aria_128_cbc(void);
const EVP_CIPHER *EVP_aria_128_cfb1(void);
const EVP_CIPHER *EVP_aria_128_cfb8(void);
const EVP_CIPHER *EVP_aria_128_cfb128(void);
# define EVP_aria_128_cfb EVP_aria_128_cfb128
const EVP_CIPHER *EVP_aria_128_ctr(void);
const EVP_CIPHER *EVP_aria_128_ofb(void);
const EVP_CIPHER *EVP_aria_128_gcm(void);
const EVP_CIPHER *EVP_aria_128_ccm(void);
const EVP_CIPHER *EVP_aria_192_ecb(void);
const EVP_CIPHER *EVP_aria_192_cbc(void);
const EVP_CIPHER *EVP_aria_192_cfb1(void);
const EVP_CIPHER *EVP_aria_192_cfb8(void);
const EVP_CIPHER *EVP_aria_192_cfb128(void);
# define EVP_aria_192_cfb EVP_aria_192_cfb128
const EVP_CIPHER *EVP_aria_192_ctr(void);
const EVP_CIPHER *EVP_aria_192_ofb(void);
const EVP_CIPHER *EVP_aria_192_gcm(void);
const EVP_CIPHER *EVP_aria_192_ccm(void);
const EVP_CIPHER *EVP_aria_256_ecb(void);
const EVP_CIPHER *EVP_aria_256_cbc(void);
const EVP_CIPHER *EVP_aria_256_cfb1(void);
const EVP_CIPHER *EVP_aria_256_cfb8(void);
const EVP_CIPHER *EVP_aria_256_cfb128(void);
# define EVP_aria_256_cfb EVP_aria_256_cfb128
const EVP_CIPHER *EVP_aria_256_ctr(void);
const EVP_CIPHER *EVP_aria_256_ofb(void);
const EVP_CIPHER *EVP_aria_256_gcm(void);
const EVP_CIPHER *EVP_aria_256_ccm(void);
# endif
# ifndef OPENSSL_NO_CAMELLIA
const EVP_CIPHER *EVP_camellia_128_ecb(void);
const EVP_CIPHER *EVP_camellia_128_cbc(void);
const EVP_CIPHER *EVP_camellia_128_cfb1(void);
const EVP_CIPHER *EVP_camellia_128_cfb8(void);
const EVP_CIPHER *EVP_camellia_128_cfb128(void);
# define EVP_camellia_128_cfb EVP_camellia_128_cfb128
const EVP_CIPHER *EVP_camellia_128_ofb(void);
const EVP_CIPHER *EVP_camellia_128_ctr(void);
const EVP_CIPHER *EVP_camellia_192_ecb(void);
const EVP_CIPHER *EVP_camellia_192_cbc(void);
const EVP_CIPHER *EVP_camellia_192_cfb1(void);
const EVP_CIPHER *EVP_camellia_192_cfb8(void);
const EVP_CIPHER *EVP_camellia_192_cfb128(void);
# define EVP_camellia_192_cfb EVP_camellia_192_cfb128
const EVP_CIPHER *EVP_camellia_192_ofb(void);
const EVP_CIPHER *EVP_camellia_192_ctr(void);
const EVP_CIPHER *EVP_camellia_256_ecb(void);
const EVP_CIPHER *EVP_camellia_256_cbc(void);
const EVP_CIPHER *EVP_camellia_256_cfb1(void);
const EVP_CIPHER *EVP_camellia_256_cfb8(void);
const EVP_CIPHER *EVP_camellia_256_cfb128(void);
# define EVP_camellia_256_cfb EVP_camellia_256_cfb128
const EVP_CIPHER *EVP_camellia_256_ofb(void);
const EVP_CIPHER *EVP_camellia_256_ctr(void);
# endif
# ifndef OPENSSL_NO_CHACHA
const EVP_CIPHER *EVP_chacha20(void);
# ifndef OPENSSL_NO_POLY1305
const EVP_CIPHER *EVP_chacha20_poly1305(void);
# endif
# endif
# ifndef OPENSSL_NO_SEED
const EVP_CIPHER *EVP_seed_ecb(void);
const EVP_CIPHER *EVP_seed_cbc(void);
const EVP_CIPHER *EVP_seed_cfb128(void);
# define EVP_seed_cfb EVP_seed_cfb128
const EVP_CIPHER *EVP_seed_ofb(void);
# endif
# ifndef OPENSSL_NO_SM4
const EVP_CIPHER *EVP_sm4_ecb(void);
const EVP_CIPHER *EVP_sm4_cbc(void);
const EVP_CIPHER *EVP_sm4_cfb128(void);
# define EVP_sm4_cfb EVP_sm4_cfb128
const EVP_CIPHER *EVP_sm4_ofb(void);
const EVP_CIPHER *EVP_sm4_ctr(void);
# endif
# if OPENSSL_API_COMPAT < 0x10100000L
# define OPENSSL_add_all_algorithms_conf() \
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
| OPENSSL_INIT_ADD_ALL_DIGESTS \
| OPENSSL_INIT_LOAD_CONFIG, NULL)
# define OPENSSL_add_all_algorithms_noconf() \
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
| OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
# ifdef OPENSSL_LOAD_CONF
# define OpenSSL_add_all_algorithms() OPENSSL_add_all_algorithms_conf()
# else
# define OpenSSL_add_all_algorithms() OPENSSL_add_all_algorithms_noconf()
# endif
# define OpenSSL_add_all_ciphers() \
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS, NULL)
# define OpenSSL_add_all_digests() \
OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
# define EVP_cleanup() while(0) continue
# endif
int EVP_add_cipher(const EVP_CIPHER *cipher);
int EVP_add_digest(const EVP_MD *digest);
const EVP_CIPHER *EVP_get_cipherbyname(const char *name);
const EVP_MD *EVP_get_digestbyname(const char *name);
void EVP_CIPHER_do_all(void (*fn) (const EVP_CIPHER *ciph,
const char *from, const char *to, void *x),
void *arg);
void EVP_CIPHER_do_all_sorted(void (*fn)
(const EVP_CIPHER *ciph, const char *from,
const char *to, void *x), void *arg);
void EVP_MD_do_all(void (*fn) (const EVP_MD *ciph,
const char *from, const char *to, void *x),
void *arg);
void EVP_MD_do_all_sorted(void (*fn)
(const EVP_MD *ciph, const char *from,
const char *to, void *x), void *arg);
int EVP_PKEY_decrypt_old(unsigned char *dec_key,
const unsigned char *enc_key, int enc_key_len,
EVP_PKEY *private_key);
int EVP_PKEY_encrypt_old(unsigned char *enc_key,
const unsigned char *key, int key_len,
EVP_PKEY *pub_key);
int EVP_PKEY_type(int type);
int EVP_PKEY_id(const EVP_PKEY *pkey);
int EVP_PKEY_base_id(const EVP_PKEY *pkey);
int EVP_PKEY_bits(const EVP_PKEY *pkey);
int EVP_PKEY_security_bits(const EVP_PKEY *pkey);
int EVP_PKEY_size(const EVP_PKEY *pkey);
int EVP_PKEY_set_type(EVP_PKEY *pkey, int type);
int EVP_PKEY_set_type_str(EVP_PKEY *pkey, const char *str, int len);
int EVP_PKEY_set_alias_type(EVP_PKEY *pkey, int type);
# ifndef OPENSSL_NO_ENGINE
int EVP_PKEY_set1_engine(EVP_PKEY *pkey, ENGINE *e);
+ENGINE *EVP_PKEY_get0_engine(const EVP_PKEY *pkey);
# endif
int EVP_PKEY_assign(EVP_PKEY *pkey, int type, void *key);
void *EVP_PKEY_get0(const EVP_PKEY *pkey);
const unsigned char *EVP_PKEY_get0_hmac(const EVP_PKEY *pkey, size_t *len);
# ifndef OPENSSL_NO_POLY1305
const unsigned char *EVP_PKEY_get0_poly1305(const EVP_PKEY *pkey, size_t *len);
# endif
# ifndef OPENSSL_NO_SIPHASH
const unsigned char *EVP_PKEY_get0_siphash(const EVP_PKEY *pkey, size_t *len);
# endif
# ifndef OPENSSL_NO_RSA
struct rsa_st;
int EVP_PKEY_set1_RSA(EVP_PKEY *pkey, struct rsa_st *key);
struct rsa_st *EVP_PKEY_get0_RSA(EVP_PKEY *pkey);
struct rsa_st *EVP_PKEY_get1_RSA(EVP_PKEY *pkey);
# endif
# ifndef OPENSSL_NO_DSA
struct dsa_st;
int EVP_PKEY_set1_DSA(EVP_PKEY *pkey, struct dsa_st *key);
struct dsa_st *EVP_PKEY_get0_DSA(EVP_PKEY *pkey);
struct dsa_st *EVP_PKEY_get1_DSA(EVP_PKEY *pkey);
# endif
# ifndef OPENSSL_NO_DH
struct dh_st;
int EVP_PKEY_set1_DH(EVP_PKEY *pkey, struct dh_st *key);
struct dh_st *EVP_PKEY_get0_DH(EVP_PKEY *pkey);
struct dh_st *EVP_PKEY_get1_DH(EVP_PKEY *pkey);
# endif
# ifndef OPENSSL_NO_EC
struct ec_key_st;
int EVP_PKEY_set1_EC_KEY(EVP_PKEY *pkey, struct ec_key_st *key);
struct ec_key_st *EVP_PKEY_get0_EC_KEY(EVP_PKEY *pkey);
struct ec_key_st *EVP_PKEY_get1_EC_KEY(EVP_PKEY *pkey);
# endif
EVP_PKEY *EVP_PKEY_new(void);
int EVP_PKEY_up_ref(EVP_PKEY *pkey);
void EVP_PKEY_free(EVP_PKEY *pkey);
EVP_PKEY *d2i_PublicKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length);
int i2d_PublicKey(EVP_PKEY *a, unsigned char **pp);
EVP_PKEY *d2i_PrivateKey(int type, EVP_PKEY **a, const unsigned char **pp,
long length);
EVP_PKEY *d2i_AutoPrivateKey(EVP_PKEY **a, const unsigned char **pp,
long length);
int i2d_PrivateKey(EVP_PKEY *a, unsigned char **pp);
int EVP_PKEY_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from);
int EVP_PKEY_missing_parameters(const EVP_PKEY *pkey);
int EVP_PKEY_save_parameters(EVP_PKEY *pkey, int mode);
int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b);
int EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b);
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx);
int EVP_PKEY_get_default_digest_nid(EVP_PKEY *pkey, int *pnid);
int EVP_PKEY_set1_tls_encodedpoint(EVP_PKEY *pkey,
const unsigned char *pt, size_t ptlen);
size_t EVP_PKEY_get1_tls_encodedpoint(EVP_PKEY *pkey, unsigned char **ppt);
int EVP_CIPHER_type(const EVP_CIPHER *ctx);
/* calls methods */
int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
int EVP_CIPHER_asn1_to_param(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
/* These are used by EVP_CIPHER methods */
int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type);
/* PKCS5 password based encryption */
int PKCS5_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
ASN1_TYPE *param, const EVP_CIPHER *cipher,
const EVP_MD *md, int en_de);
int PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
int keylen, unsigned char *out);
int PKCS5_PBKDF2_HMAC(const char *pass, int passlen,
const unsigned char *salt, int saltlen, int iter,
const EVP_MD *digest, int keylen, unsigned char *out);
int PKCS5_v2_PBE_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass, int passlen,
ASN1_TYPE *param, const EVP_CIPHER *cipher,
const EVP_MD *md, int en_de);
#ifndef OPENSSL_NO_SCRYPT
int EVP_PBE_scrypt(const char *pass, size_t passlen,
const unsigned char *salt, size_t saltlen,
uint64_t N, uint64_t r, uint64_t p, uint64_t maxmem,
unsigned char *key, size_t keylen);
int PKCS5_v2_scrypt_keyivgen(EVP_CIPHER_CTX *ctx, const char *pass,
int passlen, ASN1_TYPE *param,
const EVP_CIPHER *c, const EVP_MD *md, int en_de);
#endif
void PKCS5_PBE_add(void);
int EVP_PBE_CipherInit(ASN1_OBJECT *pbe_obj, const char *pass, int passlen,
ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de);
/* PBE type */
/* Can appear as the outermost AlgorithmIdentifier */
# define EVP_PBE_TYPE_OUTER 0x0
/* Is an PRF type OID */
# define EVP_PBE_TYPE_PRF 0x1
/* Is a PKCS#5 v2.0 KDF */
# define EVP_PBE_TYPE_KDF 0x2
int EVP_PBE_alg_add_type(int pbe_type, int pbe_nid, int cipher_nid,
int md_nid, EVP_PBE_KEYGEN *keygen);
int EVP_PBE_alg_add(int nid, const EVP_CIPHER *cipher, const EVP_MD *md,
EVP_PBE_KEYGEN *keygen);
int EVP_PBE_find(int type, int pbe_nid, int *pcnid, int *pmnid,
EVP_PBE_KEYGEN **pkeygen);
void EVP_PBE_cleanup(void);
int EVP_PBE_get(int *ptype, int *ppbe_nid, size_t num);
# define ASN1_PKEY_ALIAS 0x1
# define ASN1_PKEY_DYNAMIC 0x2
# define ASN1_PKEY_SIGPARAM_NULL 0x4
# define ASN1_PKEY_CTRL_PKCS7_SIGN 0x1
# define ASN1_PKEY_CTRL_PKCS7_ENCRYPT 0x2
# define ASN1_PKEY_CTRL_DEFAULT_MD_NID 0x3
# define ASN1_PKEY_CTRL_CMS_SIGN 0x5
# define ASN1_PKEY_CTRL_CMS_ENVELOPE 0x7
# define ASN1_PKEY_CTRL_CMS_RI_TYPE 0x8
# define ASN1_PKEY_CTRL_SET1_TLS_ENCPT 0x9
# define ASN1_PKEY_CTRL_GET1_TLS_ENCPT 0xa
int EVP_PKEY_asn1_get_count(void);
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx);
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type);
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
const char *str, int len);
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth);
int EVP_PKEY_asn1_add_alias(int to, int from);
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *pkey_base_id,
int *ppkey_flags, const char **pinfo,
const char **ppem_str,
const EVP_PKEY_ASN1_METHOD *ameth);
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey);
EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
const char *pem_str,
const char *info);
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
const EVP_PKEY_ASN1_METHOD *src);
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth);
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
int (*pub_decode) (EVP_PKEY *pk,
X509_PUBKEY *pub),
int (*pub_encode) (X509_PUBKEY *pub,
const EVP_PKEY *pk),
int (*pub_cmp) (const EVP_PKEY *a,
const EVP_PKEY *b),
int (*pub_print) (BIO *out,
const EVP_PKEY *pkey,
int indent, ASN1_PCTX *pctx),
int (*pkey_size) (const EVP_PKEY *pk),
int (*pkey_bits) (const EVP_PKEY *pk));
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
int (*priv_decode) (EVP_PKEY *pk,
const PKCS8_PRIV_KEY_INFO
*p8inf),
int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8,
const EVP_PKEY *pk),
int (*priv_print) (BIO *out,
const EVP_PKEY *pkey,
int indent,
ASN1_PCTX *pctx));
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
int (*param_decode) (EVP_PKEY *pkey,
const unsigned char **pder,
int derlen),
int (*param_encode) (const EVP_PKEY *pkey,
unsigned char **pder),
int (*param_missing) (const EVP_PKEY *pk),
int (*param_copy) (EVP_PKEY *to,
const EVP_PKEY *from),
int (*param_cmp) (const EVP_PKEY *a,
const EVP_PKEY *b),
int (*param_print) (BIO *out,
const EVP_PKEY *pkey,
int indent,
ASN1_PCTX *pctx));
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
void (*pkey_free) (EVP_PKEY *pkey));
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
long arg1, void *arg2));
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
int (*item_verify) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
void *asn,
X509_ALGOR *a,
ASN1_BIT_STRING *sig,
EVP_PKEY *pkey),
int (*item_sign) (EVP_MD_CTX *ctx,
const ASN1_ITEM *it,
void *asn,
X509_ALGOR *alg1,
X509_ALGOR *alg2,
ASN1_BIT_STRING *sig));
void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth,
int (*siginf_set) (X509_SIG_INFO *siginf,
const X509_ALGOR *alg,
const ASN1_STRING *sig));
void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_check) (const EVP_PKEY *pk));
void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_pub_check) (const EVP_PKEY *pk));
void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_param_check) (const EVP_PKEY *pk));
void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
int (*set_priv_key) (EVP_PKEY *pk,
const unsigned char
*priv,
size_t len));
void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
int (*set_pub_key) (EVP_PKEY *pk,
const unsigned char *pub,
size_t len));
void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
int (*get_priv_key) (const EVP_PKEY *pk,
unsigned char *priv,
size_t *len));
void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
int (*get_pub_key) (const EVP_PKEY *pk,
unsigned char *pub,
size_t *len));
void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
int (*pkey_security_bits) (const EVP_PKEY
*pk));
# define EVP_PKEY_OP_UNDEFINED 0
# define EVP_PKEY_OP_PARAMGEN (1<<1)
# define EVP_PKEY_OP_KEYGEN (1<<2)
# define EVP_PKEY_OP_SIGN (1<<3)
# define EVP_PKEY_OP_VERIFY (1<<4)
# define EVP_PKEY_OP_VERIFYRECOVER (1<<5)
# define EVP_PKEY_OP_SIGNCTX (1<<6)
# define EVP_PKEY_OP_VERIFYCTX (1<<7)
# define EVP_PKEY_OP_ENCRYPT (1<<8)
# define EVP_PKEY_OP_DECRYPT (1<<9)
# define EVP_PKEY_OP_DERIVE (1<<10)
# define EVP_PKEY_OP_TYPE_SIG \
(EVP_PKEY_OP_SIGN | EVP_PKEY_OP_VERIFY | EVP_PKEY_OP_VERIFYRECOVER \
| EVP_PKEY_OP_SIGNCTX | EVP_PKEY_OP_VERIFYCTX)
# define EVP_PKEY_OP_TYPE_CRYPT \
(EVP_PKEY_OP_ENCRYPT | EVP_PKEY_OP_DECRYPT)
# define EVP_PKEY_OP_TYPE_NOGEN \
(EVP_PKEY_OP_TYPE_SIG | EVP_PKEY_OP_TYPE_CRYPT | EVP_PKEY_OP_DERIVE)
# define EVP_PKEY_OP_TYPE_GEN \
(EVP_PKEY_OP_PARAMGEN | EVP_PKEY_OP_KEYGEN)
# define EVP_PKEY_CTX_set_signature_md(ctx, md) \
EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \
EVP_PKEY_CTRL_MD, 0, (void *)(md))
# define EVP_PKEY_CTX_get_signature_md(ctx, pmd) \
EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, \
EVP_PKEY_CTRL_GET_MD, 0, (void *)(pmd))
# define EVP_PKEY_CTX_set_mac_key(ctx, key, len) \
EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_KEYGEN, \
EVP_PKEY_CTRL_SET_MAC_KEY, len, (void *)(key))
# define EVP_PKEY_CTRL_MD 1
# define EVP_PKEY_CTRL_PEER_KEY 2
# define EVP_PKEY_CTRL_PKCS7_ENCRYPT 3
# define EVP_PKEY_CTRL_PKCS7_DECRYPT 4
# define EVP_PKEY_CTRL_PKCS7_SIGN 5
# define EVP_PKEY_CTRL_SET_MAC_KEY 6
# define EVP_PKEY_CTRL_DIGESTINIT 7
/* Used by GOST key encryption in TLS */
# define EVP_PKEY_CTRL_SET_IV 8
# define EVP_PKEY_CTRL_CMS_ENCRYPT 9
# define EVP_PKEY_CTRL_CMS_DECRYPT 10
# define EVP_PKEY_CTRL_CMS_SIGN 11
# define EVP_PKEY_CTRL_CIPHER 12
# define EVP_PKEY_CTRL_GET_MD 13
# define EVP_PKEY_CTRL_SET_DIGEST_SIZE 14
# define EVP_PKEY_ALG_CTRL 0x1000
# define EVP_PKEY_FLAG_AUTOARGLEN 2
/*
* Method handles all operations: don't assume any digest related defaults.
*/
# define EVP_PKEY_FLAG_SIGCTX_CUSTOM 4
const EVP_PKEY_METHOD *EVP_PKEY_meth_find(int type);
EVP_PKEY_METHOD *EVP_PKEY_meth_new(int id, int flags);
void EVP_PKEY_meth_get0_info(int *ppkey_id, int *pflags,
const EVP_PKEY_METHOD *meth);
void EVP_PKEY_meth_copy(EVP_PKEY_METHOD *dst, const EVP_PKEY_METHOD *src);
void EVP_PKEY_meth_free(EVP_PKEY_METHOD *pmeth);
int EVP_PKEY_meth_add0(const EVP_PKEY_METHOD *pmeth);
int EVP_PKEY_meth_remove(const EVP_PKEY_METHOD *pmeth);
size_t EVP_PKEY_meth_get_count(void);
const EVP_PKEY_METHOD *EVP_PKEY_meth_get0(size_t idx);
EVP_PKEY_CTX *EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e);
EVP_PKEY_CTX *EVP_PKEY_CTX_new_id(int id, ENGINE *e);
EVP_PKEY_CTX *EVP_PKEY_CTX_dup(EVP_PKEY_CTX *ctx);
void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx);
int EVP_PKEY_CTX_ctrl(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, int p1, void *p2);
int EVP_PKEY_CTX_ctrl_str(EVP_PKEY_CTX *ctx, const char *type,
const char *value);
int EVP_PKEY_CTX_ctrl_uint64(EVP_PKEY_CTX *ctx, int keytype, int optype,
int cmd, uint64_t value);
int EVP_PKEY_CTX_str2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *str);
int EVP_PKEY_CTX_hex2ctrl(EVP_PKEY_CTX *ctx, int cmd, const char *hex);
int EVP_PKEY_CTX_md(EVP_PKEY_CTX *ctx, int optype, int cmd, const char *md);
int EVP_PKEY_CTX_get_operation(EVP_PKEY_CTX *ctx);
void EVP_PKEY_CTX_set0_keygen_info(EVP_PKEY_CTX *ctx, int *dat, int datlen);
EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
const unsigned char *key, int keylen);
EVP_PKEY *EVP_PKEY_new_raw_private_key(int type, ENGINE *e,
const unsigned char *priv,
size_t len);
EVP_PKEY *EVP_PKEY_new_raw_public_key(int type, ENGINE *e,
const unsigned char *pub,
size_t len);
int EVP_PKEY_get_raw_private_key(const EVP_PKEY *pkey, unsigned char *priv,
size_t *len);
int EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub,
size_t *len);
EVP_PKEY *EVP_PKEY_new_CMAC_key(ENGINE *e, const unsigned char *priv,
size_t len, const EVP_CIPHER *cipher);
void EVP_PKEY_CTX_set_data(EVP_PKEY_CTX *ctx, void *data);
void *EVP_PKEY_CTX_get_data(EVP_PKEY_CTX *ctx);
EVP_PKEY *EVP_PKEY_CTX_get0_pkey(EVP_PKEY_CTX *ctx);
EVP_PKEY *EVP_PKEY_CTX_get0_peerkey(EVP_PKEY_CTX *ctx);
void EVP_PKEY_CTX_set_app_data(EVP_PKEY_CTX *ctx, void *data);
void *EVP_PKEY_CTX_get_app_data(EVP_PKEY_CTX *ctx);
int EVP_PKEY_sign_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_sign(EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs, size_t tbslen);
int EVP_PKEY_verify_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_verify(EVP_PKEY_CTX *ctx,
const unsigned char *sig, size_t siglen,
const unsigned char *tbs, size_t tbslen);
int EVP_PKEY_verify_recover_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_verify_recover(EVP_PKEY_CTX *ctx,
unsigned char *rout, size_t *routlen,
const unsigned char *sig, size_t siglen);
int EVP_PKEY_encrypt_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_encrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen);
int EVP_PKEY_decrypt_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, size_t *outlen,
const unsigned char *in, size_t inlen);
int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen);
typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey);
int EVP_PKEY_check(EVP_PKEY_CTX *ctx);
int EVP_PKEY_public_check(EVP_PKEY_CTX *ctx);
int EVP_PKEY_param_check(EVP_PKEY_CTX *ctx);
void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb);
EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx);
int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx);
void EVP_PKEY_meth_set_init(EVP_PKEY_METHOD *pmeth,
int (*init) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_set_copy(EVP_PKEY_METHOD *pmeth,
int (*copy) (EVP_PKEY_CTX *dst,
EVP_PKEY_CTX *src));
void EVP_PKEY_meth_set_cleanup(EVP_PKEY_METHOD *pmeth,
void (*cleanup) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_set_paramgen(EVP_PKEY_METHOD *pmeth,
int (*paramgen_init) (EVP_PKEY_CTX *ctx),
int (*paramgen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey));
void EVP_PKEY_meth_set_keygen(EVP_PKEY_METHOD *pmeth,
int (*keygen_init) (EVP_PKEY_CTX *ctx),
int (*keygen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey));
void EVP_PKEY_meth_set_sign(EVP_PKEY_METHOD *pmeth,
int (*sign_init) (EVP_PKEY_CTX *ctx),
int (*sign) (EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen));
void EVP_PKEY_meth_set_verify(EVP_PKEY_METHOD *pmeth,
int (*verify_init) (EVP_PKEY_CTX *ctx),
int (*verify) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen));
void EVP_PKEY_meth_set_verify_recover(EVP_PKEY_METHOD *pmeth,
int (*verify_recover_init) (EVP_PKEY_CTX
*ctx),
int (*verify_recover) (EVP_PKEY_CTX
*ctx,
unsigned char
*sig,
size_t *siglen,
const unsigned
char *tbs,
size_t tbslen));
void EVP_PKEY_meth_set_signctx(EVP_PKEY_METHOD *pmeth,
int (*signctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (*signctx) (EVP_PKEY_CTX *ctx,
unsigned char *sig,
size_t *siglen,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_set_verifyctx(EVP_PKEY_METHOD *pmeth,
int (*verifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (*verifyctx) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
int siglen,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_set_encrypt(EVP_PKEY_METHOD *pmeth,
int (*encrypt_init) (EVP_PKEY_CTX *ctx),
int (*encryptfn) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen));
void EVP_PKEY_meth_set_decrypt(EVP_PKEY_METHOD *pmeth,
int (*decrypt_init) (EVP_PKEY_CTX *ctx),
int (*decrypt) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen));
void EVP_PKEY_meth_set_derive(EVP_PKEY_METHOD *pmeth,
int (*derive_init) (EVP_PKEY_CTX *ctx),
int (*derive) (EVP_PKEY_CTX *ctx,
unsigned char *key,
size_t *keylen));
void EVP_PKEY_meth_set_ctrl(EVP_PKEY_METHOD *pmeth,
int (*ctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
void *p2),
int (*ctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value));
void EVP_PKEY_meth_set_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_public_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_param_check(EVP_PKEY_METHOD *pmeth,
int (*check) (EVP_PKEY *pkey));
void EVP_PKEY_meth_set_digest_custom(EVP_PKEY_METHOD *pmeth,
int (*digest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_get_init(const EVP_PKEY_METHOD *pmeth,
int (**pinit) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_get_copy(const EVP_PKEY_METHOD *pmeth,
int (**pcopy) (EVP_PKEY_CTX *dst,
EVP_PKEY_CTX *src));
void EVP_PKEY_meth_get_cleanup(const EVP_PKEY_METHOD *pmeth,
void (**pcleanup) (EVP_PKEY_CTX *ctx));
void EVP_PKEY_meth_get_paramgen(const EVP_PKEY_METHOD *pmeth,
int (**pparamgen_init) (EVP_PKEY_CTX *ctx),
int (**pparamgen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey));
void EVP_PKEY_meth_get_keygen(const EVP_PKEY_METHOD *pmeth,
int (**pkeygen_init) (EVP_PKEY_CTX *ctx),
int (**pkeygen) (EVP_PKEY_CTX *ctx,
EVP_PKEY *pkey));
void EVP_PKEY_meth_get_sign(const EVP_PKEY_METHOD *pmeth,
int (**psign_init) (EVP_PKEY_CTX *ctx),
int (**psign) (EVP_PKEY_CTX *ctx,
unsigned char *sig, size_t *siglen,
const unsigned char *tbs,
size_t tbslen));
void EVP_PKEY_meth_get_verify(const EVP_PKEY_METHOD *pmeth,
int (**pverify_init) (EVP_PKEY_CTX *ctx),
int (**pverify) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
size_t siglen,
const unsigned char *tbs,
size_t tbslen));
void EVP_PKEY_meth_get_verify_recover(const EVP_PKEY_METHOD *pmeth,
int (**pverify_recover_init) (EVP_PKEY_CTX
*ctx),
int (**pverify_recover) (EVP_PKEY_CTX
*ctx,
unsigned char
*sig,
size_t *siglen,
const unsigned
char *tbs,
size_t tbslen));
void EVP_PKEY_meth_get_signctx(const EVP_PKEY_METHOD *pmeth,
int (**psignctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (**psignctx) (EVP_PKEY_CTX *ctx,
unsigned char *sig,
size_t *siglen,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_get_verifyctx(const EVP_PKEY_METHOD *pmeth,
int (**pverifyctx_init) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx),
int (**pverifyctx) (EVP_PKEY_CTX *ctx,
const unsigned char *sig,
int siglen,
EVP_MD_CTX *mctx));
void EVP_PKEY_meth_get_encrypt(const EVP_PKEY_METHOD *pmeth,
int (**pencrypt_init) (EVP_PKEY_CTX *ctx),
int (**pencryptfn) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen));
void EVP_PKEY_meth_get_decrypt(const EVP_PKEY_METHOD *pmeth,
int (**pdecrypt_init) (EVP_PKEY_CTX *ctx),
int (**pdecrypt) (EVP_PKEY_CTX *ctx,
unsigned char *out,
size_t *outlen,
const unsigned char *in,
size_t inlen));
void EVP_PKEY_meth_get_derive(const EVP_PKEY_METHOD *pmeth,
int (**pderive_init) (EVP_PKEY_CTX *ctx),
int (**pderive) (EVP_PKEY_CTX *ctx,
unsigned char *key,
size_t *keylen));
void EVP_PKEY_meth_get_ctrl(const EVP_PKEY_METHOD *pmeth,
int (**pctrl) (EVP_PKEY_CTX *ctx, int type, int p1,
void *p2),
int (**pctrl_str) (EVP_PKEY_CTX *ctx,
const char *type,
const char *value));
void EVP_PKEY_meth_get_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey));
void EVP_PKEY_meth_get_public_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey));
void EVP_PKEY_meth_get_param_check(const EVP_PKEY_METHOD *pmeth,
int (**pcheck) (EVP_PKEY *pkey));
void EVP_PKEY_meth_get_digest_custom(EVP_PKEY_METHOD *pmeth,
int (**pdigest_custom) (EVP_PKEY_CTX *ctx,
EVP_MD_CTX *mctx));
void EVP_add_alg_module(void);
# ifdef __cplusplus
}
# endif
#endif
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
index 31fad4640fe4..47dafe48d056 100644
--- a/include/openssl/obj_mac.h
+++ b/include/openssl/obj_mac.h
@@ -1,5198 +1,5198 @@
/*
* WARNING: do not edit!
* Generated by crypto/objects/objects.pl
*
* Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#define SN_undef "UNDEF"
#define LN_undef "undefined"
#define NID_undef 0
#define OBJ_undef 0L
#define SN_itu_t "ITU-T"
#define LN_itu_t "itu-t"
#define NID_itu_t 645
#define OBJ_itu_t 0L
#define NID_ccitt 404
#define OBJ_ccitt OBJ_itu_t
#define SN_iso "ISO"
#define LN_iso "iso"
#define NID_iso 181
#define OBJ_iso 1L
#define SN_joint_iso_itu_t "JOINT-ISO-ITU-T"
#define LN_joint_iso_itu_t "joint-iso-itu-t"
#define NID_joint_iso_itu_t 646
#define OBJ_joint_iso_itu_t 2L
#define NID_joint_iso_ccitt 393
#define OBJ_joint_iso_ccitt OBJ_joint_iso_itu_t
#define SN_member_body "member-body"
#define LN_member_body "ISO Member Body"
#define NID_member_body 182
#define OBJ_member_body OBJ_iso,2L
#define SN_identified_organization "identified-organization"
#define NID_identified_organization 676
#define OBJ_identified_organization OBJ_iso,3L
#define SN_hmac_md5 "HMAC-MD5"
#define LN_hmac_md5 "hmac-md5"
#define NID_hmac_md5 780
#define OBJ_hmac_md5 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,1L
#define SN_hmac_sha1 "HMAC-SHA1"
#define LN_hmac_sha1 "hmac-sha1"
#define NID_hmac_sha1 781
#define OBJ_hmac_sha1 OBJ_identified_organization,6L,1L,5L,5L,8L,1L,2L
#define SN_x509ExtAdmission "x509ExtAdmission"
#define LN_x509ExtAdmission "Professional Information or basis for Admission"
#define NID_x509ExtAdmission 1093
#define OBJ_x509ExtAdmission OBJ_identified_organization,36L,8L,3L,3L
#define SN_certicom_arc "certicom-arc"
#define NID_certicom_arc 677
#define OBJ_certicom_arc OBJ_identified_organization,132L
#define SN_ieee "ieee"
#define NID_ieee 1170
#define OBJ_ieee OBJ_identified_organization,111L
#define SN_ieee_siswg "ieee-siswg"
#define LN_ieee_siswg "IEEE Security in Storage Working Group"
#define NID_ieee_siswg 1171
#define OBJ_ieee_siswg OBJ_ieee,2L,1619L
#define SN_international_organizations "international-organizations"
#define LN_international_organizations "International Organizations"
#define NID_international_organizations 647
#define OBJ_international_organizations OBJ_joint_iso_itu_t,23L
#define SN_wap "wap"
#define NID_wap 678
#define OBJ_wap OBJ_international_organizations,43L
#define SN_wap_wsg "wap-wsg"
#define NID_wap_wsg 679
#define OBJ_wap_wsg OBJ_wap,1L
#define SN_selected_attribute_types "selected-attribute-types"
#define LN_selected_attribute_types "Selected Attribute Types"
#define NID_selected_attribute_types 394
#define OBJ_selected_attribute_types OBJ_joint_iso_itu_t,5L,1L,5L
#define SN_clearance "clearance"
#define NID_clearance 395
#define OBJ_clearance OBJ_selected_attribute_types,55L
#define SN_ISO_US "ISO-US"
#define LN_ISO_US "ISO US Member Body"
#define NID_ISO_US 183
#define OBJ_ISO_US OBJ_member_body,840L
#define SN_X9_57 "X9-57"
#define LN_X9_57 "X9.57"
#define NID_X9_57 184
#define OBJ_X9_57 OBJ_ISO_US,10040L
#define SN_X9cm "X9cm"
#define LN_X9cm "X9.57 CM ?"
#define NID_X9cm 185
#define OBJ_X9cm OBJ_X9_57,4L
#define SN_ISO_CN "ISO-CN"
#define LN_ISO_CN "ISO CN Member Body"
#define NID_ISO_CN 1140
#define OBJ_ISO_CN OBJ_member_body,156L
#define SN_oscca "oscca"
#define NID_oscca 1141
#define OBJ_oscca OBJ_ISO_CN,10197L
#define SN_sm_scheme "sm-scheme"
#define NID_sm_scheme 1142
#define OBJ_sm_scheme OBJ_oscca,1L
#define SN_dsa "DSA"
#define LN_dsa "dsaEncryption"
#define NID_dsa 116
#define OBJ_dsa OBJ_X9cm,1L
#define SN_dsaWithSHA1 "DSA-SHA1"
#define LN_dsaWithSHA1 "dsaWithSHA1"
#define NID_dsaWithSHA1 113
#define OBJ_dsaWithSHA1 OBJ_X9cm,3L
#define SN_ansi_X9_62 "ansi-X9-62"
#define LN_ansi_X9_62 "ANSI X9.62"
#define NID_ansi_X9_62 405
#define OBJ_ansi_X9_62 OBJ_ISO_US,10045L
#define OBJ_X9_62_id_fieldType OBJ_ansi_X9_62,1L
#define SN_X9_62_prime_field "prime-field"
#define NID_X9_62_prime_field 406
#define OBJ_X9_62_prime_field OBJ_X9_62_id_fieldType,1L
#define SN_X9_62_characteristic_two_field "characteristic-two-field"
#define NID_X9_62_characteristic_two_field 407
#define OBJ_X9_62_characteristic_two_field OBJ_X9_62_id_fieldType,2L
#define SN_X9_62_id_characteristic_two_basis "id-characteristic-two-basis"
#define NID_X9_62_id_characteristic_two_basis 680
#define OBJ_X9_62_id_characteristic_two_basis OBJ_X9_62_characteristic_two_field,3L
#define SN_X9_62_onBasis "onBasis"
#define NID_X9_62_onBasis 681
#define OBJ_X9_62_onBasis OBJ_X9_62_id_characteristic_two_basis,1L
#define SN_X9_62_tpBasis "tpBasis"
#define NID_X9_62_tpBasis 682
#define OBJ_X9_62_tpBasis OBJ_X9_62_id_characteristic_two_basis,2L
#define SN_X9_62_ppBasis "ppBasis"
#define NID_X9_62_ppBasis 683
#define OBJ_X9_62_ppBasis OBJ_X9_62_id_characteristic_two_basis,3L
#define OBJ_X9_62_id_publicKeyType OBJ_ansi_X9_62,2L
#define SN_X9_62_id_ecPublicKey "id-ecPublicKey"
#define NID_X9_62_id_ecPublicKey 408
#define OBJ_X9_62_id_ecPublicKey OBJ_X9_62_id_publicKeyType,1L
#define OBJ_X9_62_ellipticCurve OBJ_ansi_X9_62,3L
#define OBJ_X9_62_c_TwoCurve OBJ_X9_62_ellipticCurve,0L
#define SN_X9_62_c2pnb163v1 "c2pnb163v1"
#define NID_X9_62_c2pnb163v1 684
#define OBJ_X9_62_c2pnb163v1 OBJ_X9_62_c_TwoCurve,1L
#define SN_X9_62_c2pnb163v2 "c2pnb163v2"
#define NID_X9_62_c2pnb163v2 685
#define OBJ_X9_62_c2pnb163v2 OBJ_X9_62_c_TwoCurve,2L
#define SN_X9_62_c2pnb163v3 "c2pnb163v3"
#define NID_X9_62_c2pnb163v3 686
#define OBJ_X9_62_c2pnb163v3 OBJ_X9_62_c_TwoCurve,3L
#define SN_X9_62_c2pnb176v1 "c2pnb176v1"
#define NID_X9_62_c2pnb176v1 687
#define OBJ_X9_62_c2pnb176v1 OBJ_X9_62_c_TwoCurve,4L
#define SN_X9_62_c2tnb191v1 "c2tnb191v1"
#define NID_X9_62_c2tnb191v1 688
#define OBJ_X9_62_c2tnb191v1 OBJ_X9_62_c_TwoCurve,5L
#define SN_X9_62_c2tnb191v2 "c2tnb191v2"
#define NID_X9_62_c2tnb191v2 689
#define OBJ_X9_62_c2tnb191v2 OBJ_X9_62_c_TwoCurve,6L
#define SN_X9_62_c2tnb191v3 "c2tnb191v3"
#define NID_X9_62_c2tnb191v3 690
#define OBJ_X9_62_c2tnb191v3 OBJ_X9_62_c_TwoCurve,7L
#define SN_X9_62_c2onb191v4 "c2onb191v4"
#define NID_X9_62_c2onb191v4 691
#define OBJ_X9_62_c2onb191v4 OBJ_X9_62_c_TwoCurve,8L
#define SN_X9_62_c2onb191v5 "c2onb191v5"
#define NID_X9_62_c2onb191v5 692
#define OBJ_X9_62_c2onb191v5 OBJ_X9_62_c_TwoCurve,9L
#define SN_X9_62_c2pnb208w1 "c2pnb208w1"
#define NID_X9_62_c2pnb208w1 693
#define OBJ_X9_62_c2pnb208w1 OBJ_X9_62_c_TwoCurve,10L
#define SN_X9_62_c2tnb239v1 "c2tnb239v1"
#define NID_X9_62_c2tnb239v1 694
#define OBJ_X9_62_c2tnb239v1 OBJ_X9_62_c_TwoCurve,11L
#define SN_X9_62_c2tnb239v2 "c2tnb239v2"
#define NID_X9_62_c2tnb239v2 695
#define OBJ_X9_62_c2tnb239v2 OBJ_X9_62_c_TwoCurve,12L
#define SN_X9_62_c2tnb239v3 "c2tnb239v3"
#define NID_X9_62_c2tnb239v3 696
#define OBJ_X9_62_c2tnb239v3 OBJ_X9_62_c_TwoCurve,13L
#define SN_X9_62_c2onb239v4 "c2onb239v4"
#define NID_X9_62_c2onb239v4 697
#define OBJ_X9_62_c2onb239v4 OBJ_X9_62_c_TwoCurve,14L
#define SN_X9_62_c2onb239v5 "c2onb239v5"
#define NID_X9_62_c2onb239v5 698
#define OBJ_X9_62_c2onb239v5 OBJ_X9_62_c_TwoCurve,15L
#define SN_X9_62_c2pnb272w1 "c2pnb272w1"
#define NID_X9_62_c2pnb272w1 699
#define OBJ_X9_62_c2pnb272w1 OBJ_X9_62_c_TwoCurve,16L
#define SN_X9_62_c2pnb304w1 "c2pnb304w1"
#define NID_X9_62_c2pnb304w1 700
#define OBJ_X9_62_c2pnb304w1 OBJ_X9_62_c_TwoCurve,17L
#define SN_X9_62_c2tnb359v1 "c2tnb359v1"
#define NID_X9_62_c2tnb359v1 701
#define OBJ_X9_62_c2tnb359v1 OBJ_X9_62_c_TwoCurve,18L
#define SN_X9_62_c2pnb368w1 "c2pnb368w1"
#define NID_X9_62_c2pnb368w1 702
#define OBJ_X9_62_c2pnb368w1 OBJ_X9_62_c_TwoCurve,19L
#define SN_X9_62_c2tnb431r1 "c2tnb431r1"
#define NID_X9_62_c2tnb431r1 703
#define OBJ_X9_62_c2tnb431r1 OBJ_X9_62_c_TwoCurve,20L
#define OBJ_X9_62_primeCurve OBJ_X9_62_ellipticCurve,1L
#define SN_X9_62_prime192v1 "prime192v1"
#define NID_X9_62_prime192v1 409
#define OBJ_X9_62_prime192v1 OBJ_X9_62_primeCurve,1L
#define SN_X9_62_prime192v2 "prime192v2"
#define NID_X9_62_prime192v2 410
#define OBJ_X9_62_prime192v2 OBJ_X9_62_primeCurve,2L
#define SN_X9_62_prime192v3 "prime192v3"
#define NID_X9_62_prime192v3 411
#define OBJ_X9_62_prime192v3 OBJ_X9_62_primeCurve,3L
#define SN_X9_62_prime239v1 "prime239v1"
#define NID_X9_62_prime239v1 412
#define OBJ_X9_62_prime239v1 OBJ_X9_62_primeCurve,4L
#define SN_X9_62_prime239v2 "prime239v2"
#define NID_X9_62_prime239v2 413
#define OBJ_X9_62_prime239v2 OBJ_X9_62_primeCurve,5L
#define SN_X9_62_prime239v3 "prime239v3"
#define NID_X9_62_prime239v3 414
#define OBJ_X9_62_prime239v3 OBJ_X9_62_primeCurve,6L
#define SN_X9_62_prime256v1 "prime256v1"
#define NID_X9_62_prime256v1 415
#define OBJ_X9_62_prime256v1 OBJ_X9_62_primeCurve,7L
#define OBJ_X9_62_id_ecSigType OBJ_ansi_X9_62,4L
#define SN_ecdsa_with_SHA1 "ecdsa-with-SHA1"
#define NID_ecdsa_with_SHA1 416
#define OBJ_ecdsa_with_SHA1 OBJ_X9_62_id_ecSigType,1L
#define SN_ecdsa_with_Recommended "ecdsa-with-Recommended"
#define NID_ecdsa_with_Recommended 791
#define OBJ_ecdsa_with_Recommended OBJ_X9_62_id_ecSigType,2L
#define SN_ecdsa_with_Specified "ecdsa-with-Specified"
#define NID_ecdsa_with_Specified 792
#define OBJ_ecdsa_with_Specified OBJ_X9_62_id_ecSigType,3L
#define SN_ecdsa_with_SHA224 "ecdsa-with-SHA224"
#define NID_ecdsa_with_SHA224 793
#define OBJ_ecdsa_with_SHA224 OBJ_ecdsa_with_Specified,1L
#define SN_ecdsa_with_SHA256 "ecdsa-with-SHA256"
#define NID_ecdsa_with_SHA256 794
#define OBJ_ecdsa_with_SHA256 OBJ_ecdsa_with_Specified,2L
#define SN_ecdsa_with_SHA384 "ecdsa-with-SHA384"
#define NID_ecdsa_with_SHA384 795
#define OBJ_ecdsa_with_SHA384 OBJ_ecdsa_with_Specified,3L
#define SN_ecdsa_with_SHA512 "ecdsa-with-SHA512"
#define NID_ecdsa_with_SHA512 796
#define OBJ_ecdsa_with_SHA512 OBJ_ecdsa_with_Specified,4L
#define OBJ_secg_ellipticCurve OBJ_certicom_arc,0L
#define SN_secp112r1 "secp112r1"
#define NID_secp112r1 704
#define OBJ_secp112r1 OBJ_secg_ellipticCurve,6L
#define SN_secp112r2 "secp112r2"
#define NID_secp112r2 705
#define OBJ_secp112r2 OBJ_secg_ellipticCurve,7L
#define SN_secp128r1 "secp128r1"
#define NID_secp128r1 706
#define OBJ_secp128r1 OBJ_secg_ellipticCurve,28L
#define SN_secp128r2 "secp128r2"
#define NID_secp128r2 707
#define OBJ_secp128r2 OBJ_secg_ellipticCurve,29L
#define SN_secp160k1 "secp160k1"
#define NID_secp160k1 708
#define OBJ_secp160k1 OBJ_secg_ellipticCurve,9L
#define SN_secp160r1 "secp160r1"
#define NID_secp160r1 709
#define OBJ_secp160r1 OBJ_secg_ellipticCurve,8L
#define SN_secp160r2 "secp160r2"
#define NID_secp160r2 710
#define OBJ_secp160r2 OBJ_secg_ellipticCurve,30L
#define SN_secp192k1 "secp192k1"
#define NID_secp192k1 711
#define OBJ_secp192k1 OBJ_secg_ellipticCurve,31L
#define SN_secp224k1 "secp224k1"
#define NID_secp224k1 712
#define OBJ_secp224k1 OBJ_secg_ellipticCurve,32L
#define SN_secp224r1 "secp224r1"
#define NID_secp224r1 713
#define OBJ_secp224r1 OBJ_secg_ellipticCurve,33L
#define SN_secp256k1 "secp256k1"
#define NID_secp256k1 714
#define OBJ_secp256k1 OBJ_secg_ellipticCurve,10L
#define SN_secp384r1 "secp384r1"
#define NID_secp384r1 715
#define OBJ_secp384r1 OBJ_secg_ellipticCurve,34L
#define SN_secp521r1 "secp521r1"
#define NID_secp521r1 716
#define OBJ_secp521r1 OBJ_secg_ellipticCurve,35L
#define SN_sect113r1 "sect113r1"
#define NID_sect113r1 717
#define OBJ_sect113r1 OBJ_secg_ellipticCurve,4L
#define SN_sect113r2 "sect113r2"
#define NID_sect113r2 718
#define OBJ_sect113r2 OBJ_secg_ellipticCurve,5L
#define SN_sect131r1 "sect131r1"
#define NID_sect131r1 719
#define OBJ_sect131r1 OBJ_secg_ellipticCurve,22L
#define SN_sect131r2 "sect131r2"
#define NID_sect131r2 720
#define OBJ_sect131r2 OBJ_secg_ellipticCurve,23L
#define SN_sect163k1 "sect163k1"
#define NID_sect163k1 721
#define OBJ_sect163k1 OBJ_secg_ellipticCurve,1L
#define SN_sect163r1 "sect163r1"
#define NID_sect163r1 722
#define OBJ_sect163r1 OBJ_secg_ellipticCurve,2L
#define SN_sect163r2 "sect163r2"
#define NID_sect163r2 723
#define OBJ_sect163r2 OBJ_secg_ellipticCurve,15L
#define SN_sect193r1 "sect193r1"
#define NID_sect193r1 724
#define OBJ_sect193r1 OBJ_secg_ellipticCurve,24L
#define SN_sect193r2 "sect193r2"
#define NID_sect193r2 725
#define OBJ_sect193r2 OBJ_secg_ellipticCurve,25L
#define SN_sect233k1 "sect233k1"
#define NID_sect233k1 726
#define OBJ_sect233k1 OBJ_secg_ellipticCurve,26L
#define SN_sect233r1 "sect233r1"
#define NID_sect233r1 727
#define OBJ_sect233r1 OBJ_secg_ellipticCurve,27L
#define SN_sect239k1 "sect239k1"
#define NID_sect239k1 728
#define OBJ_sect239k1 OBJ_secg_ellipticCurve,3L
#define SN_sect283k1 "sect283k1"
#define NID_sect283k1 729
#define OBJ_sect283k1 OBJ_secg_ellipticCurve,16L
#define SN_sect283r1 "sect283r1"
#define NID_sect283r1 730
#define OBJ_sect283r1 OBJ_secg_ellipticCurve,17L
#define SN_sect409k1 "sect409k1"
#define NID_sect409k1 731
#define OBJ_sect409k1 OBJ_secg_ellipticCurve,36L
#define SN_sect409r1 "sect409r1"
#define NID_sect409r1 732
#define OBJ_sect409r1 OBJ_secg_ellipticCurve,37L
#define SN_sect571k1 "sect571k1"
#define NID_sect571k1 733
#define OBJ_sect571k1 OBJ_secg_ellipticCurve,38L
#define SN_sect571r1 "sect571r1"
#define NID_sect571r1 734
#define OBJ_sect571r1 OBJ_secg_ellipticCurve,39L
#define OBJ_wap_wsg_idm_ecid OBJ_wap_wsg,4L
#define SN_wap_wsg_idm_ecid_wtls1 "wap-wsg-idm-ecid-wtls1"
#define NID_wap_wsg_idm_ecid_wtls1 735
#define OBJ_wap_wsg_idm_ecid_wtls1 OBJ_wap_wsg_idm_ecid,1L
#define SN_wap_wsg_idm_ecid_wtls3 "wap-wsg-idm-ecid-wtls3"
#define NID_wap_wsg_idm_ecid_wtls3 736
#define OBJ_wap_wsg_idm_ecid_wtls3 OBJ_wap_wsg_idm_ecid,3L
#define SN_wap_wsg_idm_ecid_wtls4 "wap-wsg-idm-ecid-wtls4"
#define NID_wap_wsg_idm_ecid_wtls4 737
#define OBJ_wap_wsg_idm_ecid_wtls4 OBJ_wap_wsg_idm_ecid,4L
#define SN_wap_wsg_idm_ecid_wtls5 "wap-wsg-idm-ecid-wtls5"
#define NID_wap_wsg_idm_ecid_wtls5 738
#define OBJ_wap_wsg_idm_ecid_wtls5 OBJ_wap_wsg_idm_ecid,5L
#define SN_wap_wsg_idm_ecid_wtls6 "wap-wsg-idm-ecid-wtls6"
#define NID_wap_wsg_idm_ecid_wtls6 739
#define OBJ_wap_wsg_idm_ecid_wtls6 OBJ_wap_wsg_idm_ecid,6L
#define SN_wap_wsg_idm_ecid_wtls7 "wap-wsg-idm-ecid-wtls7"
#define NID_wap_wsg_idm_ecid_wtls7 740
#define OBJ_wap_wsg_idm_ecid_wtls7 OBJ_wap_wsg_idm_ecid,7L
#define SN_wap_wsg_idm_ecid_wtls8 "wap-wsg-idm-ecid-wtls8"
#define NID_wap_wsg_idm_ecid_wtls8 741
#define OBJ_wap_wsg_idm_ecid_wtls8 OBJ_wap_wsg_idm_ecid,8L
#define SN_wap_wsg_idm_ecid_wtls9 "wap-wsg-idm-ecid-wtls9"
#define NID_wap_wsg_idm_ecid_wtls9 742
#define OBJ_wap_wsg_idm_ecid_wtls9 OBJ_wap_wsg_idm_ecid,9L
#define SN_wap_wsg_idm_ecid_wtls10 "wap-wsg-idm-ecid-wtls10"
#define NID_wap_wsg_idm_ecid_wtls10 743
#define OBJ_wap_wsg_idm_ecid_wtls10 OBJ_wap_wsg_idm_ecid,10L
#define SN_wap_wsg_idm_ecid_wtls11 "wap-wsg-idm-ecid-wtls11"
#define NID_wap_wsg_idm_ecid_wtls11 744
#define OBJ_wap_wsg_idm_ecid_wtls11 OBJ_wap_wsg_idm_ecid,11L
#define SN_wap_wsg_idm_ecid_wtls12 "wap-wsg-idm-ecid-wtls12"
#define NID_wap_wsg_idm_ecid_wtls12 745
#define OBJ_wap_wsg_idm_ecid_wtls12 OBJ_wap_wsg_idm_ecid,12L
#define SN_cast5_cbc "CAST5-CBC"
#define LN_cast5_cbc "cast5-cbc"
#define NID_cast5_cbc 108
#define OBJ_cast5_cbc OBJ_ISO_US,113533L,7L,66L,10L
#define SN_cast5_ecb "CAST5-ECB"
#define LN_cast5_ecb "cast5-ecb"
#define NID_cast5_ecb 109
#define SN_cast5_cfb64 "CAST5-CFB"
#define LN_cast5_cfb64 "cast5-cfb"
#define NID_cast5_cfb64 110
#define SN_cast5_ofb64 "CAST5-OFB"
#define LN_cast5_ofb64 "cast5-ofb"
#define NID_cast5_ofb64 111
#define LN_pbeWithMD5AndCast5_CBC "pbeWithMD5AndCast5CBC"
#define NID_pbeWithMD5AndCast5_CBC 112
#define OBJ_pbeWithMD5AndCast5_CBC OBJ_ISO_US,113533L,7L,66L,12L
#define SN_id_PasswordBasedMAC "id-PasswordBasedMAC"
#define LN_id_PasswordBasedMAC "password based MAC"
#define NID_id_PasswordBasedMAC 782
#define OBJ_id_PasswordBasedMAC OBJ_ISO_US,113533L,7L,66L,13L
#define SN_id_DHBasedMac "id-DHBasedMac"
#define LN_id_DHBasedMac "Diffie-Hellman based MAC"
#define NID_id_DHBasedMac 783
#define OBJ_id_DHBasedMac OBJ_ISO_US,113533L,7L,66L,30L
#define SN_rsadsi "rsadsi"
#define LN_rsadsi "RSA Data Security, Inc."
#define NID_rsadsi 1
#define OBJ_rsadsi OBJ_ISO_US,113549L
#define SN_pkcs "pkcs"
#define LN_pkcs "RSA Data Security, Inc. PKCS"
#define NID_pkcs 2
#define OBJ_pkcs OBJ_rsadsi,1L
#define SN_pkcs1 "pkcs1"
#define NID_pkcs1 186
#define OBJ_pkcs1 OBJ_pkcs,1L
#define LN_rsaEncryption "rsaEncryption"
#define NID_rsaEncryption 6
#define OBJ_rsaEncryption OBJ_pkcs1,1L
#define SN_md2WithRSAEncryption "RSA-MD2"
#define LN_md2WithRSAEncryption "md2WithRSAEncryption"
#define NID_md2WithRSAEncryption 7
#define OBJ_md2WithRSAEncryption OBJ_pkcs1,2L
#define SN_md4WithRSAEncryption "RSA-MD4"
#define LN_md4WithRSAEncryption "md4WithRSAEncryption"
#define NID_md4WithRSAEncryption 396
#define OBJ_md4WithRSAEncryption OBJ_pkcs1,3L
#define SN_md5WithRSAEncryption "RSA-MD5"
#define LN_md5WithRSAEncryption "md5WithRSAEncryption"
#define NID_md5WithRSAEncryption 8
#define OBJ_md5WithRSAEncryption OBJ_pkcs1,4L
#define SN_sha1WithRSAEncryption "RSA-SHA1"
#define LN_sha1WithRSAEncryption "sha1WithRSAEncryption"
#define NID_sha1WithRSAEncryption 65
#define OBJ_sha1WithRSAEncryption OBJ_pkcs1,5L
#define SN_rsaesOaep "RSAES-OAEP"
#define LN_rsaesOaep "rsaesOaep"
#define NID_rsaesOaep 919
#define OBJ_rsaesOaep OBJ_pkcs1,7L
#define SN_mgf1 "MGF1"
#define LN_mgf1 "mgf1"
#define NID_mgf1 911
#define OBJ_mgf1 OBJ_pkcs1,8L
#define SN_pSpecified "PSPECIFIED"
#define LN_pSpecified "pSpecified"
#define NID_pSpecified 935
#define OBJ_pSpecified OBJ_pkcs1,9L
#define SN_rsassaPss "RSASSA-PSS"
#define LN_rsassaPss "rsassaPss"
#define NID_rsassaPss 912
#define OBJ_rsassaPss OBJ_pkcs1,10L
#define SN_sha256WithRSAEncryption "RSA-SHA256"
#define LN_sha256WithRSAEncryption "sha256WithRSAEncryption"
#define NID_sha256WithRSAEncryption 668
#define OBJ_sha256WithRSAEncryption OBJ_pkcs1,11L
#define SN_sha384WithRSAEncryption "RSA-SHA384"
#define LN_sha384WithRSAEncryption "sha384WithRSAEncryption"
#define NID_sha384WithRSAEncryption 669
#define OBJ_sha384WithRSAEncryption OBJ_pkcs1,12L
#define SN_sha512WithRSAEncryption "RSA-SHA512"
#define LN_sha512WithRSAEncryption "sha512WithRSAEncryption"
#define NID_sha512WithRSAEncryption 670
#define OBJ_sha512WithRSAEncryption OBJ_pkcs1,13L
#define SN_sha224WithRSAEncryption "RSA-SHA224"
#define LN_sha224WithRSAEncryption "sha224WithRSAEncryption"
#define NID_sha224WithRSAEncryption 671
#define OBJ_sha224WithRSAEncryption OBJ_pkcs1,14L
#define SN_sha512_224WithRSAEncryption "RSA-SHA512/224"
#define LN_sha512_224WithRSAEncryption "sha512-224WithRSAEncryption"
#define NID_sha512_224WithRSAEncryption 1145
#define OBJ_sha512_224WithRSAEncryption OBJ_pkcs1,15L
#define SN_sha512_256WithRSAEncryption "RSA-SHA512/256"
#define LN_sha512_256WithRSAEncryption "sha512-256WithRSAEncryption"
#define NID_sha512_256WithRSAEncryption 1146
#define OBJ_sha512_256WithRSAEncryption OBJ_pkcs1,16L
#define SN_pkcs3 "pkcs3"
#define NID_pkcs3 27
#define OBJ_pkcs3 OBJ_pkcs,3L
#define LN_dhKeyAgreement "dhKeyAgreement"
#define NID_dhKeyAgreement 28
#define OBJ_dhKeyAgreement OBJ_pkcs3,1L
#define SN_pkcs5 "pkcs5"
#define NID_pkcs5 187
#define OBJ_pkcs5 OBJ_pkcs,5L
#define SN_pbeWithMD2AndDES_CBC "PBE-MD2-DES"
#define LN_pbeWithMD2AndDES_CBC "pbeWithMD2AndDES-CBC"
#define NID_pbeWithMD2AndDES_CBC 9
#define OBJ_pbeWithMD2AndDES_CBC OBJ_pkcs5,1L
#define SN_pbeWithMD5AndDES_CBC "PBE-MD5-DES"
#define LN_pbeWithMD5AndDES_CBC "pbeWithMD5AndDES-CBC"
#define NID_pbeWithMD5AndDES_CBC 10
#define OBJ_pbeWithMD5AndDES_CBC OBJ_pkcs5,3L
#define SN_pbeWithMD2AndRC2_CBC "PBE-MD2-RC2-64"
#define LN_pbeWithMD2AndRC2_CBC "pbeWithMD2AndRC2-CBC"
#define NID_pbeWithMD2AndRC2_CBC 168
#define OBJ_pbeWithMD2AndRC2_CBC OBJ_pkcs5,4L
#define SN_pbeWithMD5AndRC2_CBC "PBE-MD5-RC2-64"
#define LN_pbeWithMD5AndRC2_CBC "pbeWithMD5AndRC2-CBC"
#define NID_pbeWithMD5AndRC2_CBC 169
#define OBJ_pbeWithMD5AndRC2_CBC OBJ_pkcs5,6L
#define SN_pbeWithSHA1AndDES_CBC "PBE-SHA1-DES"
#define LN_pbeWithSHA1AndDES_CBC "pbeWithSHA1AndDES-CBC"
#define NID_pbeWithSHA1AndDES_CBC 170
#define OBJ_pbeWithSHA1AndDES_CBC OBJ_pkcs5,10L
#define SN_pbeWithSHA1AndRC2_CBC "PBE-SHA1-RC2-64"
#define LN_pbeWithSHA1AndRC2_CBC "pbeWithSHA1AndRC2-CBC"
#define NID_pbeWithSHA1AndRC2_CBC 68
#define OBJ_pbeWithSHA1AndRC2_CBC OBJ_pkcs5,11L
#define LN_id_pbkdf2 "PBKDF2"
#define NID_id_pbkdf2 69
#define OBJ_id_pbkdf2 OBJ_pkcs5,12L
#define LN_pbes2 "PBES2"
#define NID_pbes2 161
#define OBJ_pbes2 OBJ_pkcs5,13L
#define LN_pbmac1 "PBMAC1"
#define NID_pbmac1 162
#define OBJ_pbmac1 OBJ_pkcs5,14L
#define SN_pkcs7 "pkcs7"
#define NID_pkcs7 20
#define OBJ_pkcs7 OBJ_pkcs,7L
#define LN_pkcs7_data "pkcs7-data"
#define NID_pkcs7_data 21
#define OBJ_pkcs7_data OBJ_pkcs7,1L
#define LN_pkcs7_signed "pkcs7-signedData"
#define NID_pkcs7_signed 22
#define OBJ_pkcs7_signed OBJ_pkcs7,2L
#define LN_pkcs7_enveloped "pkcs7-envelopedData"
#define NID_pkcs7_enveloped 23
#define OBJ_pkcs7_enveloped OBJ_pkcs7,3L
#define LN_pkcs7_signedAndEnveloped "pkcs7-signedAndEnvelopedData"
#define NID_pkcs7_signedAndEnveloped 24
#define OBJ_pkcs7_signedAndEnveloped OBJ_pkcs7,4L
#define LN_pkcs7_digest "pkcs7-digestData"
#define NID_pkcs7_digest 25
#define OBJ_pkcs7_digest OBJ_pkcs7,5L
#define LN_pkcs7_encrypted "pkcs7-encryptedData"
#define NID_pkcs7_encrypted 26
#define OBJ_pkcs7_encrypted OBJ_pkcs7,6L
#define SN_pkcs9 "pkcs9"
#define NID_pkcs9 47
#define OBJ_pkcs9 OBJ_pkcs,9L
#define LN_pkcs9_emailAddress "emailAddress"
#define NID_pkcs9_emailAddress 48
#define OBJ_pkcs9_emailAddress OBJ_pkcs9,1L
#define LN_pkcs9_unstructuredName "unstructuredName"
#define NID_pkcs9_unstructuredName 49
#define OBJ_pkcs9_unstructuredName OBJ_pkcs9,2L
#define LN_pkcs9_contentType "contentType"
#define NID_pkcs9_contentType 50
#define OBJ_pkcs9_contentType OBJ_pkcs9,3L
#define LN_pkcs9_messageDigest "messageDigest"
#define NID_pkcs9_messageDigest 51
#define OBJ_pkcs9_messageDigest OBJ_pkcs9,4L
#define LN_pkcs9_signingTime "signingTime"
#define NID_pkcs9_signingTime 52
#define OBJ_pkcs9_signingTime OBJ_pkcs9,5L
#define LN_pkcs9_countersignature "countersignature"
#define NID_pkcs9_countersignature 53
#define OBJ_pkcs9_countersignature OBJ_pkcs9,6L
#define LN_pkcs9_challengePassword "challengePassword"
#define NID_pkcs9_challengePassword 54
#define OBJ_pkcs9_challengePassword OBJ_pkcs9,7L
#define LN_pkcs9_unstructuredAddress "unstructuredAddress"
#define NID_pkcs9_unstructuredAddress 55
#define OBJ_pkcs9_unstructuredAddress OBJ_pkcs9,8L
#define LN_pkcs9_extCertAttributes "extendedCertificateAttributes"
#define NID_pkcs9_extCertAttributes 56
#define OBJ_pkcs9_extCertAttributes OBJ_pkcs9,9L
#define SN_ext_req "extReq"
#define LN_ext_req "Extension Request"
#define NID_ext_req 172
#define OBJ_ext_req OBJ_pkcs9,14L
#define SN_SMIMECapabilities "SMIME-CAPS"
#define LN_SMIMECapabilities "S/MIME Capabilities"
#define NID_SMIMECapabilities 167
#define OBJ_SMIMECapabilities OBJ_pkcs9,15L
#define SN_SMIME "SMIME"
#define LN_SMIME "S/MIME"
#define NID_SMIME 188
#define OBJ_SMIME OBJ_pkcs9,16L
#define SN_id_smime_mod "id-smime-mod"
#define NID_id_smime_mod 189
#define OBJ_id_smime_mod OBJ_SMIME,0L
#define SN_id_smime_ct "id-smime-ct"
#define NID_id_smime_ct 190
#define OBJ_id_smime_ct OBJ_SMIME,1L
#define SN_id_smime_aa "id-smime-aa"
#define NID_id_smime_aa 191
#define OBJ_id_smime_aa OBJ_SMIME,2L
#define SN_id_smime_alg "id-smime-alg"
#define NID_id_smime_alg 192
#define OBJ_id_smime_alg OBJ_SMIME,3L
#define SN_id_smime_cd "id-smime-cd"
#define NID_id_smime_cd 193
#define OBJ_id_smime_cd OBJ_SMIME,4L
#define SN_id_smime_spq "id-smime-spq"
#define NID_id_smime_spq 194
#define OBJ_id_smime_spq OBJ_SMIME,5L
#define SN_id_smime_cti "id-smime-cti"
#define NID_id_smime_cti 195
#define OBJ_id_smime_cti OBJ_SMIME,6L
#define SN_id_smime_mod_cms "id-smime-mod-cms"
#define NID_id_smime_mod_cms 196
#define OBJ_id_smime_mod_cms OBJ_id_smime_mod,1L
#define SN_id_smime_mod_ess "id-smime-mod-ess"
#define NID_id_smime_mod_ess 197
#define OBJ_id_smime_mod_ess OBJ_id_smime_mod,2L
#define SN_id_smime_mod_oid "id-smime-mod-oid"
#define NID_id_smime_mod_oid 198
#define OBJ_id_smime_mod_oid OBJ_id_smime_mod,3L
#define SN_id_smime_mod_msg_v3 "id-smime-mod-msg-v3"
#define NID_id_smime_mod_msg_v3 199
#define OBJ_id_smime_mod_msg_v3 OBJ_id_smime_mod,4L
#define SN_id_smime_mod_ets_eSignature_88 "id-smime-mod-ets-eSignature-88"
#define NID_id_smime_mod_ets_eSignature_88 200
#define OBJ_id_smime_mod_ets_eSignature_88 OBJ_id_smime_mod,5L
#define SN_id_smime_mod_ets_eSignature_97 "id-smime-mod-ets-eSignature-97"
#define NID_id_smime_mod_ets_eSignature_97 201
#define OBJ_id_smime_mod_ets_eSignature_97 OBJ_id_smime_mod,6L
#define SN_id_smime_mod_ets_eSigPolicy_88 "id-smime-mod-ets-eSigPolicy-88"
#define NID_id_smime_mod_ets_eSigPolicy_88 202
#define OBJ_id_smime_mod_ets_eSigPolicy_88 OBJ_id_smime_mod,7L
#define SN_id_smime_mod_ets_eSigPolicy_97 "id-smime-mod-ets-eSigPolicy-97"
#define NID_id_smime_mod_ets_eSigPolicy_97 203
#define OBJ_id_smime_mod_ets_eSigPolicy_97 OBJ_id_smime_mod,8L
#define SN_id_smime_ct_receipt "id-smime-ct-receipt"
#define NID_id_smime_ct_receipt 204
#define OBJ_id_smime_ct_receipt OBJ_id_smime_ct,1L
#define SN_id_smime_ct_authData "id-smime-ct-authData"
#define NID_id_smime_ct_authData 205
#define OBJ_id_smime_ct_authData OBJ_id_smime_ct,2L
#define SN_id_smime_ct_publishCert "id-smime-ct-publishCert"
#define NID_id_smime_ct_publishCert 206
#define OBJ_id_smime_ct_publishCert OBJ_id_smime_ct,3L
#define SN_id_smime_ct_TSTInfo "id-smime-ct-TSTInfo"
#define NID_id_smime_ct_TSTInfo 207
#define OBJ_id_smime_ct_TSTInfo OBJ_id_smime_ct,4L
#define SN_id_smime_ct_TDTInfo "id-smime-ct-TDTInfo"
#define NID_id_smime_ct_TDTInfo 208
#define OBJ_id_smime_ct_TDTInfo OBJ_id_smime_ct,5L
#define SN_id_smime_ct_contentInfo "id-smime-ct-contentInfo"
#define NID_id_smime_ct_contentInfo 209
#define OBJ_id_smime_ct_contentInfo OBJ_id_smime_ct,6L
#define SN_id_smime_ct_DVCSRequestData "id-smime-ct-DVCSRequestData"
#define NID_id_smime_ct_DVCSRequestData 210
#define OBJ_id_smime_ct_DVCSRequestData OBJ_id_smime_ct,7L
#define SN_id_smime_ct_DVCSResponseData "id-smime-ct-DVCSResponseData"
#define NID_id_smime_ct_DVCSResponseData 211
#define OBJ_id_smime_ct_DVCSResponseData OBJ_id_smime_ct,8L
#define SN_id_smime_ct_compressedData "id-smime-ct-compressedData"
#define NID_id_smime_ct_compressedData 786
#define OBJ_id_smime_ct_compressedData OBJ_id_smime_ct,9L
#define SN_id_smime_ct_contentCollection "id-smime-ct-contentCollection"
#define NID_id_smime_ct_contentCollection 1058
#define OBJ_id_smime_ct_contentCollection OBJ_id_smime_ct,19L
#define SN_id_smime_ct_authEnvelopedData "id-smime-ct-authEnvelopedData"
#define NID_id_smime_ct_authEnvelopedData 1059
#define OBJ_id_smime_ct_authEnvelopedData OBJ_id_smime_ct,23L
#define SN_id_ct_asciiTextWithCRLF "id-ct-asciiTextWithCRLF"
#define NID_id_ct_asciiTextWithCRLF 787
#define OBJ_id_ct_asciiTextWithCRLF OBJ_id_smime_ct,27L
#define SN_id_ct_xml "id-ct-xml"
#define NID_id_ct_xml 1060
#define OBJ_id_ct_xml OBJ_id_smime_ct,28L
#define SN_id_smime_aa_receiptRequest "id-smime-aa-receiptRequest"
#define NID_id_smime_aa_receiptRequest 212
#define OBJ_id_smime_aa_receiptRequest OBJ_id_smime_aa,1L
#define SN_id_smime_aa_securityLabel "id-smime-aa-securityLabel"
#define NID_id_smime_aa_securityLabel 213
#define OBJ_id_smime_aa_securityLabel OBJ_id_smime_aa,2L
#define SN_id_smime_aa_mlExpandHistory "id-smime-aa-mlExpandHistory"
#define NID_id_smime_aa_mlExpandHistory 214
#define OBJ_id_smime_aa_mlExpandHistory OBJ_id_smime_aa,3L
#define SN_id_smime_aa_contentHint "id-smime-aa-contentHint"
#define NID_id_smime_aa_contentHint 215
#define OBJ_id_smime_aa_contentHint OBJ_id_smime_aa,4L
#define SN_id_smime_aa_msgSigDigest "id-smime-aa-msgSigDigest"
#define NID_id_smime_aa_msgSigDigest 216
#define OBJ_id_smime_aa_msgSigDigest OBJ_id_smime_aa,5L
#define SN_id_smime_aa_encapContentType "id-smime-aa-encapContentType"
#define NID_id_smime_aa_encapContentType 217
#define OBJ_id_smime_aa_encapContentType OBJ_id_smime_aa,6L
#define SN_id_smime_aa_contentIdentifier "id-smime-aa-contentIdentifier"
#define NID_id_smime_aa_contentIdentifier 218
#define OBJ_id_smime_aa_contentIdentifier OBJ_id_smime_aa,7L
#define SN_id_smime_aa_macValue "id-smime-aa-macValue"
#define NID_id_smime_aa_macValue 219
#define OBJ_id_smime_aa_macValue OBJ_id_smime_aa,8L
#define SN_id_smime_aa_equivalentLabels "id-smime-aa-equivalentLabels"
#define NID_id_smime_aa_equivalentLabels 220
#define OBJ_id_smime_aa_equivalentLabels OBJ_id_smime_aa,9L
#define SN_id_smime_aa_contentReference "id-smime-aa-contentReference"
#define NID_id_smime_aa_contentReference 221
#define OBJ_id_smime_aa_contentReference OBJ_id_smime_aa,10L
#define SN_id_smime_aa_encrypKeyPref "id-smime-aa-encrypKeyPref"
#define NID_id_smime_aa_encrypKeyPref 222
#define OBJ_id_smime_aa_encrypKeyPref OBJ_id_smime_aa,11L
#define SN_id_smime_aa_signingCertificate "id-smime-aa-signingCertificate"
#define NID_id_smime_aa_signingCertificate 223
#define OBJ_id_smime_aa_signingCertificate OBJ_id_smime_aa,12L
#define SN_id_smime_aa_smimeEncryptCerts "id-smime-aa-smimeEncryptCerts"
#define NID_id_smime_aa_smimeEncryptCerts 224
#define OBJ_id_smime_aa_smimeEncryptCerts OBJ_id_smime_aa,13L
#define SN_id_smime_aa_timeStampToken "id-smime-aa-timeStampToken"
#define NID_id_smime_aa_timeStampToken 225
#define OBJ_id_smime_aa_timeStampToken OBJ_id_smime_aa,14L
#define SN_id_smime_aa_ets_sigPolicyId "id-smime-aa-ets-sigPolicyId"
#define NID_id_smime_aa_ets_sigPolicyId 226
#define OBJ_id_smime_aa_ets_sigPolicyId OBJ_id_smime_aa,15L
#define SN_id_smime_aa_ets_commitmentType "id-smime-aa-ets-commitmentType"
#define NID_id_smime_aa_ets_commitmentType 227
#define OBJ_id_smime_aa_ets_commitmentType OBJ_id_smime_aa,16L
#define SN_id_smime_aa_ets_signerLocation "id-smime-aa-ets-signerLocation"
#define NID_id_smime_aa_ets_signerLocation 228
#define OBJ_id_smime_aa_ets_signerLocation OBJ_id_smime_aa,17L
#define SN_id_smime_aa_ets_signerAttr "id-smime-aa-ets-signerAttr"
#define NID_id_smime_aa_ets_signerAttr 229
#define OBJ_id_smime_aa_ets_signerAttr OBJ_id_smime_aa,18L
#define SN_id_smime_aa_ets_otherSigCert "id-smime-aa-ets-otherSigCert"
#define NID_id_smime_aa_ets_otherSigCert 230
#define OBJ_id_smime_aa_ets_otherSigCert OBJ_id_smime_aa,19L
#define SN_id_smime_aa_ets_contentTimestamp "id-smime-aa-ets-contentTimestamp"
#define NID_id_smime_aa_ets_contentTimestamp 231
#define OBJ_id_smime_aa_ets_contentTimestamp OBJ_id_smime_aa,20L
#define SN_id_smime_aa_ets_CertificateRefs "id-smime-aa-ets-CertificateRefs"
#define NID_id_smime_aa_ets_CertificateRefs 232
#define OBJ_id_smime_aa_ets_CertificateRefs OBJ_id_smime_aa,21L
#define SN_id_smime_aa_ets_RevocationRefs "id-smime-aa-ets-RevocationRefs"
#define NID_id_smime_aa_ets_RevocationRefs 233
#define OBJ_id_smime_aa_ets_RevocationRefs OBJ_id_smime_aa,22L
#define SN_id_smime_aa_ets_certValues "id-smime-aa-ets-certValues"
#define NID_id_smime_aa_ets_certValues 234
#define OBJ_id_smime_aa_ets_certValues OBJ_id_smime_aa,23L
#define SN_id_smime_aa_ets_revocationValues "id-smime-aa-ets-revocationValues"
#define NID_id_smime_aa_ets_revocationValues 235
#define OBJ_id_smime_aa_ets_revocationValues OBJ_id_smime_aa,24L
#define SN_id_smime_aa_ets_escTimeStamp "id-smime-aa-ets-escTimeStamp"
#define NID_id_smime_aa_ets_escTimeStamp 236
#define OBJ_id_smime_aa_ets_escTimeStamp OBJ_id_smime_aa,25L
#define SN_id_smime_aa_ets_certCRLTimestamp "id-smime-aa-ets-certCRLTimestamp"
#define NID_id_smime_aa_ets_certCRLTimestamp 237
#define OBJ_id_smime_aa_ets_certCRLTimestamp OBJ_id_smime_aa,26L
#define SN_id_smime_aa_ets_archiveTimeStamp "id-smime-aa-ets-archiveTimeStamp"
#define NID_id_smime_aa_ets_archiveTimeStamp 238
#define OBJ_id_smime_aa_ets_archiveTimeStamp OBJ_id_smime_aa,27L
#define SN_id_smime_aa_signatureType "id-smime-aa-signatureType"
#define NID_id_smime_aa_signatureType 239
#define OBJ_id_smime_aa_signatureType OBJ_id_smime_aa,28L
#define SN_id_smime_aa_dvcs_dvc "id-smime-aa-dvcs-dvc"
#define NID_id_smime_aa_dvcs_dvc 240
#define OBJ_id_smime_aa_dvcs_dvc OBJ_id_smime_aa,29L
#define SN_id_smime_aa_signingCertificateV2 "id-smime-aa-signingCertificateV2"
#define NID_id_smime_aa_signingCertificateV2 1086
#define OBJ_id_smime_aa_signingCertificateV2 OBJ_id_smime_aa,47L
#define SN_id_smime_alg_ESDHwith3DES "id-smime-alg-ESDHwith3DES"
#define NID_id_smime_alg_ESDHwith3DES 241
#define OBJ_id_smime_alg_ESDHwith3DES OBJ_id_smime_alg,1L
#define SN_id_smime_alg_ESDHwithRC2 "id-smime-alg-ESDHwithRC2"
#define NID_id_smime_alg_ESDHwithRC2 242
#define OBJ_id_smime_alg_ESDHwithRC2 OBJ_id_smime_alg,2L
#define SN_id_smime_alg_3DESwrap "id-smime-alg-3DESwrap"
#define NID_id_smime_alg_3DESwrap 243
#define OBJ_id_smime_alg_3DESwrap OBJ_id_smime_alg,3L
#define SN_id_smime_alg_RC2wrap "id-smime-alg-RC2wrap"
#define NID_id_smime_alg_RC2wrap 244
#define OBJ_id_smime_alg_RC2wrap OBJ_id_smime_alg,4L
#define SN_id_smime_alg_ESDH "id-smime-alg-ESDH"
#define NID_id_smime_alg_ESDH 245
#define OBJ_id_smime_alg_ESDH OBJ_id_smime_alg,5L
#define SN_id_smime_alg_CMS3DESwrap "id-smime-alg-CMS3DESwrap"
#define NID_id_smime_alg_CMS3DESwrap 246
#define OBJ_id_smime_alg_CMS3DESwrap OBJ_id_smime_alg,6L
#define SN_id_smime_alg_CMSRC2wrap "id-smime-alg-CMSRC2wrap"
#define NID_id_smime_alg_CMSRC2wrap 247
#define OBJ_id_smime_alg_CMSRC2wrap OBJ_id_smime_alg,7L
#define SN_id_alg_PWRI_KEK "id-alg-PWRI-KEK"
#define NID_id_alg_PWRI_KEK 893
#define OBJ_id_alg_PWRI_KEK OBJ_id_smime_alg,9L
#define SN_id_smime_cd_ldap "id-smime-cd-ldap"
#define NID_id_smime_cd_ldap 248
#define OBJ_id_smime_cd_ldap OBJ_id_smime_cd,1L
#define SN_id_smime_spq_ets_sqt_uri "id-smime-spq-ets-sqt-uri"
#define NID_id_smime_spq_ets_sqt_uri 249
#define OBJ_id_smime_spq_ets_sqt_uri OBJ_id_smime_spq,1L
#define SN_id_smime_spq_ets_sqt_unotice "id-smime-spq-ets-sqt-unotice"
#define NID_id_smime_spq_ets_sqt_unotice 250
#define OBJ_id_smime_spq_ets_sqt_unotice OBJ_id_smime_spq,2L
#define SN_id_smime_cti_ets_proofOfOrigin "id-smime-cti-ets-proofOfOrigin"
#define NID_id_smime_cti_ets_proofOfOrigin 251
#define OBJ_id_smime_cti_ets_proofOfOrigin OBJ_id_smime_cti,1L
#define SN_id_smime_cti_ets_proofOfReceipt "id-smime-cti-ets-proofOfReceipt"
#define NID_id_smime_cti_ets_proofOfReceipt 252
#define OBJ_id_smime_cti_ets_proofOfReceipt OBJ_id_smime_cti,2L
#define SN_id_smime_cti_ets_proofOfDelivery "id-smime-cti-ets-proofOfDelivery"
#define NID_id_smime_cti_ets_proofOfDelivery 253
#define OBJ_id_smime_cti_ets_proofOfDelivery OBJ_id_smime_cti,3L
#define SN_id_smime_cti_ets_proofOfSender "id-smime-cti-ets-proofOfSender"
#define NID_id_smime_cti_ets_proofOfSender 254
#define OBJ_id_smime_cti_ets_proofOfSender OBJ_id_smime_cti,4L
#define SN_id_smime_cti_ets_proofOfApproval "id-smime-cti-ets-proofOfApproval"
#define NID_id_smime_cti_ets_proofOfApproval 255
#define OBJ_id_smime_cti_ets_proofOfApproval OBJ_id_smime_cti,5L
#define SN_id_smime_cti_ets_proofOfCreation "id-smime-cti-ets-proofOfCreation"
#define NID_id_smime_cti_ets_proofOfCreation 256
#define OBJ_id_smime_cti_ets_proofOfCreation OBJ_id_smime_cti,6L
#define LN_friendlyName "friendlyName"
#define NID_friendlyName 156
#define OBJ_friendlyName OBJ_pkcs9,20L
#define LN_localKeyID "localKeyID"
#define NID_localKeyID 157
#define OBJ_localKeyID OBJ_pkcs9,21L
#define SN_ms_csp_name "CSPName"
#define LN_ms_csp_name "Microsoft CSP Name"
#define NID_ms_csp_name 417
#define OBJ_ms_csp_name 1L,3L,6L,1L,4L,1L,311L,17L,1L
#define SN_LocalKeySet "LocalKeySet"
#define LN_LocalKeySet "Microsoft Local Key set"
#define NID_LocalKeySet 856
#define OBJ_LocalKeySet 1L,3L,6L,1L,4L,1L,311L,17L,2L
#define OBJ_certTypes OBJ_pkcs9,22L
#define LN_x509Certificate "x509Certificate"
#define NID_x509Certificate 158
#define OBJ_x509Certificate OBJ_certTypes,1L
#define LN_sdsiCertificate "sdsiCertificate"
#define NID_sdsiCertificate 159
#define OBJ_sdsiCertificate OBJ_certTypes,2L
#define OBJ_crlTypes OBJ_pkcs9,23L
#define LN_x509Crl "x509Crl"
#define NID_x509Crl 160
#define OBJ_x509Crl OBJ_crlTypes,1L
#define OBJ_pkcs12 OBJ_pkcs,12L
#define OBJ_pkcs12_pbeids OBJ_pkcs12,1L
#define SN_pbe_WithSHA1And128BitRC4 "PBE-SHA1-RC4-128"
#define LN_pbe_WithSHA1And128BitRC4 "pbeWithSHA1And128BitRC4"
#define NID_pbe_WithSHA1And128BitRC4 144
#define OBJ_pbe_WithSHA1And128BitRC4 OBJ_pkcs12_pbeids,1L
#define SN_pbe_WithSHA1And40BitRC4 "PBE-SHA1-RC4-40"
#define LN_pbe_WithSHA1And40BitRC4 "pbeWithSHA1And40BitRC4"
#define NID_pbe_WithSHA1And40BitRC4 145
#define OBJ_pbe_WithSHA1And40BitRC4 OBJ_pkcs12_pbeids,2L
#define SN_pbe_WithSHA1And3_Key_TripleDES_CBC "PBE-SHA1-3DES"
#define LN_pbe_WithSHA1And3_Key_TripleDES_CBC "pbeWithSHA1And3-KeyTripleDES-CBC"
#define NID_pbe_WithSHA1And3_Key_TripleDES_CBC 146
#define OBJ_pbe_WithSHA1And3_Key_TripleDES_CBC OBJ_pkcs12_pbeids,3L
#define SN_pbe_WithSHA1And2_Key_TripleDES_CBC "PBE-SHA1-2DES"
#define LN_pbe_WithSHA1And2_Key_TripleDES_CBC "pbeWithSHA1And2-KeyTripleDES-CBC"
#define NID_pbe_WithSHA1And2_Key_TripleDES_CBC 147
#define OBJ_pbe_WithSHA1And2_Key_TripleDES_CBC OBJ_pkcs12_pbeids,4L
#define SN_pbe_WithSHA1And128BitRC2_CBC "PBE-SHA1-RC2-128"
#define LN_pbe_WithSHA1And128BitRC2_CBC "pbeWithSHA1And128BitRC2-CBC"
#define NID_pbe_WithSHA1And128BitRC2_CBC 148
#define OBJ_pbe_WithSHA1And128BitRC2_CBC OBJ_pkcs12_pbeids,5L
#define SN_pbe_WithSHA1And40BitRC2_CBC "PBE-SHA1-RC2-40"
#define LN_pbe_WithSHA1And40BitRC2_CBC "pbeWithSHA1And40BitRC2-CBC"
#define NID_pbe_WithSHA1And40BitRC2_CBC 149
#define OBJ_pbe_WithSHA1And40BitRC2_CBC OBJ_pkcs12_pbeids,6L
#define OBJ_pkcs12_Version1 OBJ_pkcs12,10L
#define OBJ_pkcs12_BagIds OBJ_pkcs12_Version1,1L
#define LN_keyBag "keyBag"
#define NID_keyBag 150
#define OBJ_keyBag OBJ_pkcs12_BagIds,1L
#define LN_pkcs8ShroudedKeyBag "pkcs8ShroudedKeyBag"
#define NID_pkcs8ShroudedKeyBag 151
#define OBJ_pkcs8ShroudedKeyBag OBJ_pkcs12_BagIds,2L
#define LN_certBag "certBag"
#define NID_certBag 152
#define OBJ_certBag OBJ_pkcs12_BagIds,3L
#define LN_crlBag "crlBag"
#define NID_crlBag 153
#define OBJ_crlBag OBJ_pkcs12_BagIds,4L
#define LN_secretBag "secretBag"
#define NID_secretBag 154
#define OBJ_secretBag OBJ_pkcs12_BagIds,5L
#define LN_safeContentsBag "safeContentsBag"
#define NID_safeContentsBag 155
#define OBJ_safeContentsBag OBJ_pkcs12_BagIds,6L
#define SN_md2 "MD2"
#define LN_md2 "md2"
#define NID_md2 3
#define OBJ_md2 OBJ_rsadsi,2L,2L
#define SN_md4 "MD4"
#define LN_md4 "md4"
#define NID_md4 257
#define OBJ_md4 OBJ_rsadsi,2L,4L
#define SN_md5 "MD5"
#define LN_md5 "md5"
#define NID_md5 4
#define OBJ_md5 OBJ_rsadsi,2L,5L
#define SN_md5_sha1 "MD5-SHA1"
#define LN_md5_sha1 "md5-sha1"
#define NID_md5_sha1 114
#define LN_hmacWithMD5 "hmacWithMD5"
#define NID_hmacWithMD5 797
#define OBJ_hmacWithMD5 OBJ_rsadsi,2L,6L
#define LN_hmacWithSHA1 "hmacWithSHA1"
#define NID_hmacWithSHA1 163
#define OBJ_hmacWithSHA1 OBJ_rsadsi,2L,7L
#define SN_sm2 "SM2"
#define LN_sm2 "sm2"
#define NID_sm2 1172
#define OBJ_sm2 OBJ_sm_scheme,301L
#define SN_sm3 "SM3"
#define LN_sm3 "sm3"
#define NID_sm3 1143
#define OBJ_sm3 OBJ_sm_scheme,401L
#define SN_sm3WithRSAEncryption "RSA-SM3"
#define LN_sm3WithRSAEncryption "sm3WithRSAEncryption"
#define NID_sm3WithRSAEncryption 1144
#define OBJ_sm3WithRSAEncryption OBJ_sm_scheme,504L
#define LN_hmacWithSHA224 "hmacWithSHA224"
#define NID_hmacWithSHA224 798
#define OBJ_hmacWithSHA224 OBJ_rsadsi,2L,8L
#define LN_hmacWithSHA256 "hmacWithSHA256"
#define NID_hmacWithSHA256 799
#define OBJ_hmacWithSHA256 OBJ_rsadsi,2L,9L
#define LN_hmacWithSHA384 "hmacWithSHA384"
#define NID_hmacWithSHA384 800
#define OBJ_hmacWithSHA384 OBJ_rsadsi,2L,10L
#define LN_hmacWithSHA512 "hmacWithSHA512"
#define NID_hmacWithSHA512 801
#define OBJ_hmacWithSHA512 OBJ_rsadsi,2L,11L
#define LN_hmacWithSHA512_224 "hmacWithSHA512-224"
#define NID_hmacWithSHA512_224 1193
#define OBJ_hmacWithSHA512_224 OBJ_rsadsi,2L,12L
#define LN_hmacWithSHA512_256 "hmacWithSHA512-256"
#define NID_hmacWithSHA512_256 1194
#define OBJ_hmacWithSHA512_256 OBJ_rsadsi,2L,13L
#define SN_rc2_cbc "RC2-CBC"
#define LN_rc2_cbc "rc2-cbc"
#define NID_rc2_cbc 37
#define OBJ_rc2_cbc OBJ_rsadsi,3L,2L
#define SN_rc2_ecb "RC2-ECB"
#define LN_rc2_ecb "rc2-ecb"
#define NID_rc2_ecb 38
#define SN_rc2_cfb64 "RC2-CFB"
#define LN_rc2_cfb64 "rc2-cfb"
#define NID_rc2_cfb64 39
#define SN_rc2_ofb64 "RC2-OFB"
#define LN_rc2_ofb64 "rc2-ofb"
#define NID_rc2_ofb64 40
#define SN_rc2_40_cbc "RC2-40-CBC"
#define LN_rc2_40_cbc "rc2-40-cbc"
#define NID_rc2_40_cbc 98
#define SN_rc2_64_cbc "RC2-64-CBC"
#define LN_rc2_64_cbc "rc2-64-cbc"
#define NID_rc2_64_cbc 166
#define SN_rc4 "RC4"
#define LN_rc4 "rc4"
#define NID_rc4 5
#define OBJ_rc4 OBJ_rsadsi,3L,4L
#define SN_rc4_40 "RC4-40"
#define LN_rc4_40 "rc4-40"
#define NID_rc4_40 97
#define SN_des_ede3_cbc "DES-EDE3-CBC"
#define LN_des_ede3_cbc "des-ede3-cbc"
#define NID_des_ede3_cbc 44
#define OBJ_des_ede3_cbc OBJ_rsadsi,3L,7L
#define SN_rc5_cbc "RC5-CBC"
#define LN_rc5_cbc "rc5-cbc"
#define NID_rc5_cbc 120
#define OBJ_rc5_cbc OBJ_rsadsi,3L,8L
#define SN_rc5_ecb "RC5-ECB"
#define LN_rc5_ecb "rc5-ecb"
#define NID_rc5_ecb 121
#define SN_rc5_cfb64 "RC5-CFB"
#define LN_rc5_cfb64 "rc5-cfb"
#define NID_rc5_cfb64 122
#define SN_rc5_ofb64 "RC5-OFB"
#define LN_rc5_ofb64 "rc5-ofb"
#define NID_rc5_ofb64 123
#define SN_ms_ext_req "msExtReq"
#define LN_ms_ext_req "Microsoft Extension Request"
#define NID_ms_ext_req 171
#define OBJ_ms_ext_req 1L,3L,6L,1L,4L,1L,311L,2L,1L,14L
#define SN_ms_code_ind "msCodeInd"
#define LN_ms_code_ind "Microsoft Individual Code Signing"
#define NID_ms_code_ind 134
#define OBJ_ms_code_ind 1L,3L,6L,1L,4L,1L,311L,2L,1L,21L
#define SN_ms_code_com "msCodeCom"
#define LN_ms_code_com "Microsoft Commercial Code Signing"
#define NID_ms_code_com 135
#define OBJ_ms_code_com 1L,3L,6L,1L,4L,1L,311L,2L,1L,22L
#define SN_ms_ctl_sign "msCTLSign"
#define LN_ms_ctl_sign "Microsoft Trust List Signing"
#define NID_ms_ctl_sign 136
#define OBJ_ms_ctl_sign 1L,3L,6L,1L,4L,1L,311L,10L,3L,1L
#define SN_ms_sgc "msSGC"
#define LN_ms_sgc "Microsoft Server Gated Crypto"
#define NID_ms_sgc 137
#define OBJ_ms_sgc 1L,3L,6L,1L,4L,1L,311L,10L,3L,3L
#define SN_ms_efs "msEFS"
#define LN_ms_efs "Microsoft Encrypted File System"
#define NID_ms_efs 138
#define OBJ_ms_efs 1L,3L,6L,1L,4L,1L,311L,10L,3L,4L
#define SN_ms_smartcard_login "msSmartcardLogin"
#define LN_ms_smartcard_login "Microsoft Smartcardlogin"
#define NID_ms_smartcard_login 648
#define OBJ_ms_smartcard_login 1L,3L,6L,1L,4L,1L,311L,20L,2L,2L
#define SN_ms_upn "msUPN"
#define LN_ms_upn "Microsoft Universal Principal Name"
#define NID_ms_upn 649
#define OBJ_ms_upn 1L,3L,6L,1L,4L,1L,311L,20L,2L,3L
#define SN_idea_cbc "IDEA-CBC"
#define LN_idea_cbc "idea-cbc"
#define NID_idea_cbc 34
#define OBJ_idea_cbc 1L,3L,6L,1L,4L,1L,188L,7L,1L,1L,2L
#define SN_idea_ecb "IDEA-ECB"
#define LN_idea_ecb "idea-ecb"
#define NID_idea_ecb 36
#define SN_idea_cfb64 "IDEA-CFB"
#define LN_idea_cfb64 "idea-cfb"
#define NID_idea_cfb64 35
#define SN_idea_ofb64 "IDEA-OFB"
#define LN_idea_ofb64 "idea-ofb"
#define NID_idea_ofb64 46
#define SN_bf_cbc "BF-CBC"
#define LN_bf_cbc "bf-cbc"
#define NID_bf_cbc 91
#define OBJ_bf_cbc 1L,3L,6L,1L,4L,1L,3029L,1L,2L
#define SN_bf_ecb "BF-ECB"
#define LN_bf_ecb "bf-ecb"
#define NID_bf_ecb 92
#define SN_bf_cfb64 "BF-CFB"
#define LN_bf_cfb64 "bf-cfb"
#define NID_bf_cfb64 93
#define SN_bf_ofb64 "BF-OFB"
#define LN_bf_ofb64 "bf-ofb"
#define NID_bf_ofb64 94
#define SN_id_pkix "PKIX"
#define NID_id_pkix 127
#define OBJ_id_pkix 1L,3L,6L,1L,5L,5L,7L
#define SN_id_pkix_mod "id-pkix-mod"
#define NID_id_pkix_mod 258
#define OBJ_id_pkix_mod OBJ_id_pkix,0L
#define SN_id_pe "id-pe"
#define NID_id_pe 175
#define OBJ_id_pe OBJ_id_pkix,1L
#define SN_id_qt "id-qt"
#define NID_id_qt 259
#define OBJ_id_qt OBJ_id_pkix,2L
#define SN_id_kp "id-kp"
#define NID_id_kp 128
#define OBJ_id_kp OBJ_id_pkix,3L
#define SN_id_it "id-it"
#define NID_id_it 260
#define OBJ_id_it OBJ_id_pkix,4L
#define SN_id_pkip "id-pkip"
#define NID_id_pkip 261
#define OBJ_id_pkip OBJ_id_pkix,5L
#define SN_id_alg "id-alg"
#define NID_id_alg 262
#define OBJ_id_alg OBJ_id_pkix,6L
#define SN_id_cmc "id-cmc"
#define NID_id_cmc 263
#define OBJ_id_cmc OBJ_id_pkix,7L
#define SN_id_on "id-on"
#define NID_id_on 264
#define OBJ_id_on OBJ_id_pkix,8L
#define SN_id_pda "id-pda"
#define NID_id_pda 265
#define OBJ_id_pda OBJ_id_pkix,9L
#define SN_id_aca "id-aca"
#define NID_id_aca 266
#define OBJ_id_aca OBJ_id_pkix,10L
#define SN_id_qcs "id-qcs"
#define NID_id_qcs 267
#define OBJ_id_qcs OBJ_id_pkix,11L
#define SN_id_cct "id-cct"
#define NID_id_cct 268
#define OBJ_id_cct OBJ_id_pkix,12L
#define SN_id_ppl "id-ppl"
#define NID_id_ppl 662
#define OBJ_id_ppl OBJ_id_pkix,21L
#define SN_id_ad "id-ad"
#define NID_id_ad 176
#define OBJ_id_ad OBJ_id_pkix,48L
#define SN_id_pkix1_explicit_88 "id-pkix1-explicit-88"
#define NID_id_pkix1_explicit_88 269
#define OBJ_id_pkix1_explicit_88 OBJ_id_pkix_mod,1L
#define SN_id_pkix1_implicit_88 "id-pkix1-implicit-88"
#define NID_id_pkix1_implicit_88 270
#define OBJ_id_pkix1_implicit_88 OBJ_id_pkix_mod,2L
#define SN_id_pkix1_explicit_93 "id-pkix1-explicit-93"
#define NID_id_pkix1_explicit_93 271
#define OBJ_id_pkix1_explicit_93 OBJ_id_pkix_mod,3L
#define SN_id_pkix1_implicit_93 "id-pkix1-implicit-93"
#define NID_id_pkix1_implicit_93 272
#define OBJ_id_pkix1_implicit_93 OBJ_id_pkix_mod,4L
#define SN_id_mod_crmf "id-mod-crmf"
#define NID_id_mod_crmf 273
#define OBJ_id_mod_crmf OBJ_id_pkix_mod,5L
#define SN_id_mod_cmc "id-mod-cmc"
#define NID_id_mod_cmc 274
#define OBJ_id_mod_cmc OBJ_id_pkix_mod,6L
#define SN_id_mod_kea_profile_88 "id-mod-kea-profile-88"
#define NID_id_mod_kea_profile_88 275
#define OBJ_id_mod_kea_profile_88 OBJ_id_pkix_mod,7L
#define SN_id_mod_kea_profile_93 "id-mod-kea-profile-93"
#define NID_id_mod_kea_profile_93 276
#define OBJ_id_mod_kea_profile_93 OBJ_id_pkix_mod,8L
#define SN_id_mod_cmp "id-mod-cmp"
#define NID_id_mod_cmp 277
#define OBJ_id_mod_cmp OBJ_id_pkix_mod,9L
#define SN_id_mod_qualified_cert_88 "id-mod-qualified-cert-88"
#define NID_id_mod_qualified_cert_88 278
#define OBJ_id_mod_qualified_cert_88 OBJ_id_pkix_mod,10L
#define SN_id_mod_qualified_cert_93 "id-mod-qualified-cert-93"
#define NID_id_mod_qualified_cert_93 279
#define OBJ_id_mod_qualified_cert_93 OBJ_id_pkix_mod,11L
#define SN_id_mod_attribute_cert "id-mod-attribute-cert"
#define NID_id_mod_attribute_cert 280
#define OBJ_id_mod_attribute_cert OBJ_id_pkix_mod,12L
#define SN_id_mod_timestamp_protocol "id-mod-timestamp-protocol"
#define NID_id_mod_timestamp_protocol 281
#define OBJ_id_mod_timestamp_protocol OBJ_id_pkix_mod,13L
#define SN_id_mod_ocsp "id-mod-ocsp"
#define NID_id_mod_ocsp 282
#define OBJ_id_mod_ocsp OBJ_id_pkix_mod,14L
#define SN_id_mod_dvcs "id-mod-dvcs"
#define NID_id_mod_dvcs 283
#define OBJ_id_mod_dvcs OBJ_id_pkix_mod,15L
#define SN_id_mod_cmp2000 "id-mod-cmp2000"
#define NID_id_mod_cmp2000 284
#define OBJ_id_mod_cmp2000 OBJ_id_pkix_mod,16L
#define SN_info_access "authorityInfoAccess"
#define LN_info_access "Authority Information Access"
#define NID_info_access 177
#define OBJ_info_access OBJ_id_pe,1L
#define SN_biometricInfo "biometricInfo"
#define LN_biometricInfo "Biometric Info"
#define NID_biometricInfo 285
#define OBJ_biometricInfo OBJ_id_pe,2L
#define SN_qcStatements "qcStatements"
#define NID_qcStatements 286
#define OBJ_qcStatements OBJ_id_pe,3L
#define SN_ac_auditEntity "ac-auditEntity"
#define NID_ac_auditEntity 287
#define OBJ_ac_auditEntity OBJ_id_pe,4L
#define SN_ac_targeting "ac-targeting"
#define NID_ac_targeting 288
#define OBJ_ac_targeting OBJ_id_pe,5L
#define SN_aaControls "aaControls"
#define NID_aaControls 289
#define OBJ_aaControls OBJ_id_pe,6L
#define SN_sbgp_ipAddrBlock "sbgp-ipAddrBlock"
#define NID_sbgp_ipAddrBlock 290
#define OBJ_sbgp_ipAddrBlock OBJ_id_pe,7L
#define SN_sbgp_autonomousSysNum "sbgp-autonomousSysNum"
#define NID_sbgp_autonomousSysNum 291
#define OBJ_sbgp_autonomousSysNum OBJ_id_pe,8L
#define SN_sbgp_routerIdentifier "sbgp-routerIdentifier"
#define NID_sbgp_routerIdentifier 292
#define OBJ_sbgp_routerIdentifier OBJ_id_pe,9L
#define SN_ac_proxying "ac-proxying"
#define NID_ac_proxying 397
#define OBJ_ac_proxying OBJ_id_pe,10L
#define SN_sinfo_access "subjectInfoAccess"
#define LN_sinfo_access "Subject Information Access"
#define NID_sinfo_access 398
#define OBJ_sinfo_access OBJ_id_pe,11L
#define SN_proxyCertInfo "proxyCertInfo"
#define LN_proxyCertInfo "Proxy Certificate Information"
#define NID_proxyCertInfo 663
#define OBJ_proxyCertInfo OBJ_id_pe,14L
#define SN_tlsfeature "tlsfeature"
#define LN_tlsfeature "TLS Feature"
#define NID_tlsfeature 1020
#define OBJ_tlsfeature OBJ_id_pe,24L
#define SN_id_qt_cps "id-qt-cps"
#define LN_id_qt_cps "Policy Qualifier CPS"
#define NID_id_qt_cps 164
#define OBJ_id_qt_cps OBJ_id_qt,1L
#define SN_id_qt_unotice "id-qt-unotice"
#define LN_id_qt_unotice "Policy Qualifier User Notice"
#define NID_id_qt_unotice 165
#define OBJ_id_qt_unotice OBJ_id_qt,2L
#define SN_textNotice "textNotice"
#define NID_textNotice 293
#define OBJ_textNotice OBJ_id_qt,3L
#define SN_server_auth "serverAuth"
#define LN_server_auth "TLS Web Server Authentication"
#define NID_server_auth 129
#define OBJ_server_auth OBJ_id_kp,1L
#define SN_client_auth "clientAuth"
#define LN_client_auth "TLS Web Client Authentication"
#define NID_client_auth 130
#define OBJ_client_auth OBJ_id_kp,2L
#define SN_code_sign "codeSigning"
#define LN_code_sign "Code Signing"
#define NID_code_sign 131
#define OBJ_code_sign OBJ_id_kp,3L
#define SN_email_protect "emailProtection"
#define LN_email_protect "E-mail Protection"
#define NID_email_protect 132
#define OBJ_email_protect OBJ_id_kp,4L
#define SN_ipsecEndSystem "ipsecEndSystem"
#define LN_ipsecEndSystem "IPSec End System"
#define NID_ipsecEndSystem 294
#define OBJ_ipsecEndSystem OBJ_id_kp,5L
#define SN_ipsecTunnel "ipsecTunnel"
#define LN_ipsecTunnel "IPSec Tunnel"
#define NID_ipsecTunnel 295
#define OBJ_ipsecTunnel OBJ_id_kp,6L
#define SN_ipsecUser "ipsecUser"
#define LN_ipsecUser "IPSec User"
#define NID_ipsecUser 296
#define OBJ_ipsecUser OBJ_id_kp,7L
#define SN_time_stamp "timeStamping"
#define LN_time_stamp "Time Stamping"
#define NID_time_stamp 133
#define OBJ_time_stamp OBJ_id_kp,8L
#define SN_OCSP_sign "OCSPSigning"
#define LN_OCSP_sign "OCSP Signing"
#define NID_OCSP_sign 180
#define OBJ_OCSP_sign OBJ_id_kp,9L
#define SN_dvcs "DVCS"
#define LN_dvcs "dvcs"
#define NID_dvcs 297
#define OBJ_dvcs OBJ_id_kp,10L
#define SN_ipsec_IKE "ipsecIKE"
#define LN_ipsec_IKE "ipsec Internet Key Exchange"
#define NID_ipsec_IKE 1022
#define OBJ_ipsec_IKE OBJ_id_kp,17L
#define SN_capwapAC "capwapAC"
#define LN_capwapAC "Ctrl/provision WAP Access"
#define NID_capwapAC 1023
#define OBJ_capwapAC OBJ_id_kp,18L
#define SN_capwapWTP "capwapWTP"
#define LN_capwapWTP "Ctrl/Provision WAP Termination"
#define NID_capwapWTP 1024
#define OBJ_capwapWTP OBJ_id_kp,19L
#define SN_sshClient "secureShellClient"
#define LN_sshClient "SSH Client"
#define NID_sshClient 1025
#define OBJ_sshClient OBJ_id_kp,21L
#define SN_sshServer "secureShellServer"
#define LN_sshServer "SSH Server"
#define NID_sshServer 1026
#define OBJ_sshServer OBJ_id_kp,22L
#define SN_sendRouter "sendRouter"
#define LN_sendRouter "Send Router"
#define NID_sendRouter 1027
#define OBJ_sendRouter OBJ_id_kp,23L
#define SN_sendProxiedRouter "sendProxiedRouter"
#define LN_sendProxiedRouter "Send Proxied Router"
#define NID_sendProxiedRouter 1028
#define OBJ_sendProxiedRouter OBJ_id_kp,24L
#define SN_sendOwner "sendOwner"
#define LN_sendOwner "Send Owner"
#define NID_sendOwner 1029
#define OBJ_sendOwner OBJ_id_kp,25L
#define SN_sendProxiedOwner "sendProxiedOwner"
#define LN_sendProxiedOwner "Send Proxied Owner"
#define NID_sendProxiedOwner 1030
#define OBJ_sendProxiedOwner OBJ_id_kp,26L
#define SN_cmcCA "cmcCA"
#define LN_cmcCA "CMC Certificate Authority"
#define NID_cmcCA 1131
#define OBJ_cmcCA OBJ_id_kp,27L
#define SN_cmcRA "cmcRA"
#define LN_cmcRA "CMC Registration Authority"
#define NID_cmcRA 1132
#define OBJ_cmcRA OBJ_id_kp,28L
#define SN_id_it_caProtEncCert "id-it-caProtEncCert"
#define NID_id_it_caProtEncCert 298
#define OBJ_id_it_caProtEncCert OBJ_id_it,1L
#define SN_id_it_signKeyPairTypes "id-it-signKeyPairTypes"
#define NID_id_it_signKeyPairTypes 299
#define OBJ_id_it_signKeyPairTypes OBJ_id_it,2L
#define SN_id_it_encKeyPairTypes "id-it-encKeyPairTypes"
#define NID_id_it_encKeyPairTypes 300
#define OBJ_id_it_encKeyPairTypes OBJ_id_it,3L
#define SN_id_it_preferredSymmAlg "id-it-preferredSymmAlg"
#define NID_id_it_preferredSymmAlg 301
#define OBJ_id_it_preferredSymmAlg OBJ_id_it,4L
#define SN_id_it_caKeyUpdateInfo "id-it-caKeyUpdateInfo"
#define NID_id_it_caKeyUpdateInfo 302
#define OBJ_id_it_caKeyUpdateInfo OBJ_id_it,5L
#define SN_id_it_currentCRL "id-it-currentCRL"
#define NID_id_it_currentCRL 303
#define OBJ_id_it_currentCRL OBJ_id_it,6L
#define SN_id_it_unsupportedOIDs "id-it-unsupportedOIDs"
#define NID_id_it_unsupportedOIDs 304
#define OBJ_id_it_unsupportedOIDs OBJ_id_it,7L
#define SN_id_it_subscriptionRequest "id-it-subscriptionRequest"
#define NID_id_it_subscriptionRequest 305
#define OBJ_id_it_subscriptionRequest OBJ_id_it,8L
#define SN_id_it_subscriptionResponse "id-it-subscriptionResponse"
#define NID_id_it_subscriptionResponse 306
#define OBJ_id_it_subscriptionResponse OBJ_id_it,9L
#define SN_id_it_keyPairParamReq "id-it-keyPairParamReq"
#define NID_id_it_keyPairParamReq 307
#define OBJ_id_it_keyPairParamReq OBJ_id_it,10L
#define SN_id_it_keyPairParamRep "id-it-keyPairParamRep"
#define NID_id_it_keyPairParamRep 308
#define OBJ_id_it_keyPairParamRep OBJ_id_it,11L
#define SN_id_it_revPassphrase "id-it-revPassphrase"
#define NID_id_it_revPassphrase 309
#define OBJ_id_it_revPassphrase OBJ_id_it,12L
#define SN_id_it_implicitConfirm "id-it-implicitConfirm"
#define NID_id_it_implicitConfirm 310
#define OBJ_id_it_implicitConfirm OBJ_id_it,13L
#define SN_id_it_confirmWaitTime "id-it-confirmWaitTime"
#define NID_id_it_confirmWaitTime 311
#define OBJ_id_it_confirmWaitTime OBJ_id_it,14L
#define SN_id_it_origPKIMessage "id-it-origPKIMessage"
#define NID_id_it_origPKIMessage 312
#define OBJ_id_it_origPKIMessage OBJ_id_it,15L
#define SN_id_it_suppLangTags "id-it-suppLangTags"
#define NID_id_it_suppLangTags 784
#define OBJ_id_it_suppLangTags OBJ_id_it,16L
#define SN_id_regCtrl "id-regCtrl"
#define NID_id_regCtrl 313
#define OBJ_id_regCtrl OBJ_id_pkip,1L
#define SN_id_regInfo "id-regInfo"
#define NID_id_regInfo 314
#define OBJ_id_regInfo OBJ_id_pkip,2L
#define SN_id_regCtrl_regToken "id-regCtrl-regToken"
#define NID_id_regCtrl_regToken 315
#define OBJ_id_regCtrl_regToken OBJ_id_regCtrl,1L
#define SN_id_regCtrl_authenticator "id-regCtrl-authenticator"
#define NID_id_regCtrl_authenticator 316
#define OBJ_id_regCtrl_authenticator OBJ_id_regCtrl,2L
#define SN_id_regCtrl_pkiPublicationInfo "id-regCtrl-pkiPublicationInfo"
#define NID_id_regCtrl_pkiPublicationInfo 317
#define OBJ_id_regCtrl_pkiPublicationInfo OBJ_id_regCtrl,3L
#define SN_id_regCtrl_pkiArchiveOptions "id-regCtrl-pkiArchiveOptions"
#define NID_id_regCtrl_pkiArchiveOptions 318
#define OBJ_id_regCtrl_pkiArchiveOptions OBJ_id_regCtrl,4L
#define SN_id_regCtrl_oldCertID "id-regCtrl-oldCertID"
#define NID_id_regCtrl_oldCertID 319
#define OBJ_id_regCtrl_oldCertID OBJ_id_regCtrl,5L
#define SN_id_regCtrl_protocolEncrKey "id-regCtrl-protocolEncrKey"
#define NID_id_regCtrl_protocolEncrKey 320
#define OBJ_id_regCtrl_protocolEncrKey OBJ_id_regCtrl,6L
#define SN_id_regInfo_utf8Pairs "id-regInfo-utf8Pairs"
#define NID_id_regInfo_utf8Pairs 321
#define OBJ_id_regInfo_utf8Pairs OBJ_id_regInfo,1L
#define SN_id_regInfo_certReq "id-regInfo-certReq"
#define NID_id_regInfo_certReq 322
#define OBJ_id_regInfo_certReq OBJ_id_regInfo,2L
#define SN_id_alg_des40 "id-alg-des40"
#define NID_id_alg_des40 323
#define OBJ_id_alg_des40 OBJ_id_alg,1L
#define SN_id_alg_noSignature "id-alg-noSignature"
#define NID_id_alg_noSignature 324
#define OBJ_id_alg_noSignature OBJ_id_alg,2L
#define SN_id_alg_dh_sig_hmac_sha1 "id-alg-dh-sig-hmac-sha1"
#define NID_id_alg_dh_sig_hmac_sha1 325
#define OBJ_id_alg_dh_sig_hmac_sha1 OBJ_id_alg,3L
#define SN_id_alg_dh_pop "id-alg-dh-pop"
#define NID_id_alg_dh_pop 326
#define OBJ_id_alg_dh_pop OBJ_id_alg,4L
#define SN_id_cmc_statusInfo "id-cmc-statusInfo"
#define NID_id_cmc_statusInfo 327
#define OBJ_id_cmc_statusInfo OBJ_id_cmc,1L
#define SN_id_cmc_identification "id-cmc-identification"
#define NID_id_cmc_identification 328
#define OBJ_id_cmc_identification OBJ_id_cmc,2L
#define SN_id_cmc_identityProof "id-cmc-identityProof"
#define NID_id_cmc_identityProof 329
#define OBJ_id_cmc_identityProof OBJ_id_cmc,3L
#define SN_id_cmc_dataReturn "id-cmc-dataReturn"
#define NID_id_cmc_dataReturn 330
#define OBJ_id_cmc_dataReturn OBJ_id_cmc,4L
#define SN_id_cmc_transactionId "id-cmc-transactionId"
#define NID_id_cmc_transactionId 331
#define OBJ_id_cmc_transactionId OBJ_id_cmc,5L
#define SN_id_cmc_senderNonce "id-cmc-senderNonce"
#define NID_id_cmc_senderNonce 332
#define OBJ_id_cmc_senderNonce OBJ_id_cmc,6L
#define SN_id_cmc_recipientNonce "id-cmc-recipientNonce"
#define NID_id_cmc_recipientNonce 333
#define OBJ_id_cmc_recipientNonce OBJ_id_cmc,7L
#define SN_id_cmc_addExtensions "id-cmc-addExtensions"
#define NID_id_cmc_addExtensions 334
#define OBJ_id_cmc_addExtensions OBJ_id_cmc,8L
#define SN_id_cmc_encryptedPOP "id-cmc-encryptedPOP"
#define NID_id_cmc_encryptedPOP 335
#define OBJ_id_cmc_encryptedPOP OBJ_id_cmc,9L
#define SN_id_cmc_decryptedPOP "id-cmc-decryptedPOP"
#define NID_id_cmc_decryptedPOP 336
#define OBJ_id_cmc_decryptedPOP OBJ_id_cmc,10L
#define SN_id_cmc_lraPOPWitness "id-cmc-lraPOPWitness"
#define NID_id_cmc_lraPOPWitness 337
#define OBJ_id_cmc_lraPOPWitness OBJ_id_cmc,11L
#define SN_id_cmc_getCert "id-cmc-getCert"
#define NID_id_cmc_getCert 338
#define OBJ_id_cmc_getCert OBJ_id_cmc,15L
#define SN_id_cmc_getCRL "id-cmc-getCRL"
#define NID_id_cmc_getCRL 339
#define OBJ_id_cmc_getCRL OBJ_id_cmc,16L
#define SN_id_cmc_revokeRequest "id-cmc-revokeRequest"
#define NID_id_cmc_revokeRequest 340
#define OBJ_id_cmc_revokeRequest OBJ_id_cmc,17L
#define SN_id_cmc_regInfo "id-cmc-regInfo"
#define NID_id_cmc_regInfo 341
#define OBJ_id_cmc_regInfo OBJ_id_cmc,18L
#define SN_id_cmc_responseInfo "id-cmc-responseInfo"
#define NID_id_cmc_responseInfo 342
#define OBJ_id_cmc_responseInfo OBJ_id_cmc,19L
#define SN_id_cmc_queryPending "id-cmc-queryPending"
#define NID_id_cmc_queryPending 343
#define OBJ_id_cmc_queryPending OBJ_id_cmc,21L
#define SN_id_cmc_popLinkRandom "id-cmc-popLinkRandom"
#define NID_id_cmc_popLinkRandom 344
#define OBJ_id_cmc_popLinkRandom OBJ_id_cmc,22L
#define SN_id_cmc_popLinkWitness "id-cmc-popLinkWitness"
#define NID_id_cmc_popLinkWitness 345
#define OBJ_id_cmc_popLinkWitness OBJ_id_cmc,23L
#define SN_id_cmc_confirmCertAcceptance "id-cmc-confirmCertAcceptance"
#define NID_id_cmc_confirmCertAcceptance 346
#define OBJ_id_cmc_confirmCertAcceptance OBJ_id_cmc,24L
#define SN_id_on_personalData "id-on-personalData"
#define NID_id_on_personalData 347
#define OBJ_id_on_personalData OBJ_id_on,1L
#define SN_id_on_permanentIdentifier "id-on-permanentIdentifier"
#define LN_id_on_permanentIdentifier "Permanent Identifier"
#define NID_id_on_permanentIdentifier 858
#define OBJ_id_on_permanentIdentifier OBJ_id_on,3L
#define SN_id_pda_dateOfBirth "id-pda-dateOfBirth"
#define NID_id_pda_dateOfBirth 348
#define OBJ_id_pda_dateOfBirth OBJ_id_pda,1L
#define SN_id_pda_placeOfBirth "id-pda-placeOfBirth"
#define NID_id_pda_placeOfBirth 349
#define OBJ_id_pda_placeOfBirth OBJ_id_pda,2L
#define SN_id_pda_gender "id-pda-gender"
#define NID_id_pda_gender 351
#define OBJ_id_pda_gender OBJ_id_pda,3L
#define SN_id_pda_countryOfCitizenship "id-pda-countryOfCitizenship"
#define NID_id_pda_countryOfCitizenship 352
#define OBJ_id_pda_countryOfCitizenship OBJ_id_pda,4L
#define SN_id_pda_countryOfResidence "id-pda-countryOfResidence"
#define NID_id_pda_countryOfResidence 353
#define OBJ_id_pda_countryOfResidence OBJ_id_pda,5L
#define SN_id_aca_authenticationInfo "id-aca-authenticationInfo"
#define NID_id_aca_authenticationInfo 354
#define OBJ_id_aca_authenticationInfo OBJ_id_aca,1L
#define SN_id_aca_accessIdentity "id-aca-accessIdentity"
#define NID_id_aca_accessIdentity 355
#define OBJ_id_aca_accessIdentity OBJ_id_aca,2L
#define SN_id_aca_chargingIdentity "id-aca-chargingIdentity"
#define NID_id_aca_chargingIdentity 356
#define OBJ_id_aca_chargingIdentity OBJ_id_aca,3L
#define SN_id_aca_group "id-aca-group"
#define NID_id_aca_group 357
#define OBJ_id_aca_group OBJ_id_aca,4L
#define SN_id_aca_role "id-aca-role"
#define NID_id_aca_role 358
#define OBJ_id_aca_role OBJ_id_aca,5L
#define SN_id_aca_encAttrs "id-aca-encAttrs"
#define NID_id_aca_encAttrs 399
#define OBJ_id_aca_encAttrs OBJ_id_aca,6L
#define SN_id_qcs_pkixQCSyntax_v1 "id-qcs-pkixQCSyntax-v1"
#define NID_id_qcs_pkixQCSyntax_v1 359
#define OBJ_id_qcs_pkixQCSyntax_v1 OBJ_id_qcs,1L
#define SN_id_cct_crs "id-cct-crs"
#define NID_id_cct_crs 360
#define OBJ_id_cct_crs OBJ_id_cct,1L
#define SN_id_cct_PKIData "id-cct-PKIData"
#define NID_id_cct_PKIData 361
#define OBJ_id_cct_PKIData OBJ_id_cct,2L
#define SN_id_cct_PKIResponse "id-cct-PKIResponse"
#define NID_id_cct_PKIResponse 362
#define OBJ_id_cct_PKIResponse OBJ_id_cct,3L
#define SN_id_ppl_anyLanguage "id-ppl-anyLanguage"
#define LN_id_ppl_anyLanguage "Any language"
#define NID_id_ppl_anyLanguage 664
#define OBJ_id_ppl_anyLanguage OBJ_id_ppl,0L
#define SN_id_ppl_inheritAll "id-ppl-inheritAll"
#define LN_id_ppl_inheritAll "Inherit all"
#define NID_id_ppl_inheritAll 665
#define OBJ_id_ppl_inheritAll OBJ_id_ppl,1L
#define SN_Independent "id-ppl-independent"
#define LN_Independent "Independent"
#define NID_Independent 667
#define OBJ_Independent OBJ_id_ppl,2L
#define SN_ad_OCSP "OCSP"
#define LN_ad_OCSP "OCSP"
#define NID_ad_OCSP 178
#define OBJ_ad_OCSP OBJ_id_ad,1L
#define SN_ad_ca_issuers "caIssuers"
#define LN_ad_ca_issuers "CA Issuers"
#define NID_ad_ca_issuers 179
#define OBJ_ad_ca_issuers OBJ_id_ad,2L
#define SN_ad_timeStamping "ad_timestamping"
#define LN_ad_timeStamping "AD Time Stamping"
#define NID_ad_timeStamping 363
#define OBJ_ad_timeStamping OBJ_id_ad,3L
#define SN_ad_dvcs "AD_DVCS"
#define LN_ad_dvcs "ad dvcs"
#define NID_ad_dvcs 364
#define OBJ_ad_dvcs OBJ_id_ad,4L
#define SN_caRepository "caRepository"
#define LN_caRepository "CA Repository"
#define NID_caRepository 785
#define OBJ_caRepository OBJ_id_ad,5L
#define OBJ_id_pkix_OCSP OBJ_ad_OCSP
#define SN_id_pkix_OCSP_basic "basicOCSPResponse"
#define LN_id_pkix_OCSP_basic "Basic OCSP Response"
#define NID_id_pkix_OCSP_basic 365
#define OBJ_id_pkix_OCSP_basic OBJ_id_pkix_OCSP,1L
#define SN_id_pkix_OCSP_Nonce "Nonce"
#define LN_id_pkix_OCSP_Nonce "OCSP Nonce"
#define NID_id_pkix_OCSP_Nonce 366
#define OBJ_id_pkix_OCSP_Nonce OBJ_id_pkix_OCSP,2L
#define SN_id_pkix_OCSP_CrlID "CrlID"
#define LN_id_pkix_OCSP_CrlID "OCSP CRL ID"
#define NID_id_pkix_OCSP_CrlID 367
#define OBJ_id_pkix_OCSP_CrlID OBJ_id_pkix_OCSP,3L
#define SN_id_pkix_OCSP_acceptableResponses "acceptableResponses"
#define LN_id_pkix_OCSP_acceptableResponses "Acceptable OCSP Responses"
#define NID_id_pkix_OCSP_acceptableResponses 368
#define OBJ_id_pkix_OCSP_acceptableResponses OBJ_id_pkix_OCSP,4L
#define SN_id_pkix_OCSP_noCheck "noCheck"
#define LN_id_pkix_OCSP_noCheck "OCSP No Check"
#define NID_id_pkix_OCSP_noCheck 369
#define OBJ_id_pkix_OCSP_noCheck OBJ_id_pkix_OCSP,5L
#define SN_id_pkix_OCSP_archiveCutoff "archiveCutoff"
#define LN_id_pkix_OCSP_archiveCutoff "OCSP Archive Cutoff"
#define NID_id_pkix_OCSP_archiveCutoff 370
#define OBJ_id_pkix_OCSP_archiveCutoff OBJ_id_pkix_OCSP,6L
#define SN_id_pkix_OCSP_serviceLocator "serviceLocator"
#define LN_id_pkix_OCSP_serviceLocator "OCSP Service Locator"
#define NID_id_pkix_OCSP_serviceLocator 371
#define OBJ_id_pkix_OCSP_serviceLocator OBJ_id_pkix_OCSP,7L
#define SN_id_pkix_OCSP_extendedStatus "extendedStatus"
#define LN_id_pkix_OCSP_extendedStatus "Extended OCSP Status"
#define NID_id_pkix_OCSP_extendedStatus 372
#define OBJ_id_pkix_OCSP_extendedStatus OBJ_id_pkix_OCSP,8L
#define SN_id_pkix_OCSP_valid "valid"
#define NID_id_pkix_OCSP_valid 373
#define OBJ_id_pkix_OCSP_valid OBJ_id_pkix_OCSP,9L
#define SN_id_pkix_OCSP_path "path"
#define NID_id_pkix_OCSP_path 374
#define OBJ_id_pkix_OCSP_path OBJ_id_pkix_OCSP,10L
#define SN_id_pkix_OCSP_trustRoot "trustRoot"
#define LN_id_pkix_OCSP_trustRoot "Trust Root"
#define NID_id_pkix_OCSP_trustRoot 375
#define OBJ_id_pkix_OCSP_trustRoot OBJ_id_pkix_OCSP,11L
#define SN_algorithm "algorithm"
#define LN_algorithm "algorithm"
#define NID_algorithm 376
#define OBJ_algorithm 1L,3L,14L,3L,2L
#define SN_md5WithRSA "RSA-NP-MD5"
#define LN_md5WithRSA "md5WithRSA"
#define NID_md5WithRSA 104
#define OBJ_md5WithRSA OBJ_algorithm,3L
#define SN_des_ecb "DES-ECB"
#define LN_des_ecb "des-ecb"
#define NID_des_ecb 29
#define OBJ_des_ecb OBJ_algorithm,6L
#define SN_des_cbc "DES-CBC"
#define LN_des_cbc "des-cbc"
#define NID_des_cbc 31
#define OBJ_des_cbc OBJ_algorithm,7L
#define SN_des_ofb64 "DES-OFB"
#define LN_des_ofb64 "des-ofb"
#define NID_des_ofb64 45
#define OBJ_des_ofb64 OBJ_algorithm,8L
#define SN_des_cfb64 "DES-CFB"
#define LN_des_cfb64 "des-cfb"
#define NID_des_cfb64 30
#define OBJ_des_cfb64 OBJ_algorithm,9L
#define SN_rsaSignature "rsaSignature"
#define NID_rsaSignature 377
#define OBJ_rsaSignature OBJ_algorithm,11L
#define SN_dsa_2 "DSA-old"
#define LN_dsa_2 "dsaEncryption-old"
#define NID_dsa_2 67
#define OBJ_dsa_2 OBJ_algorithm,12L
#define SN_dsaWithSHA "DSA-SHA"
#define LN_dsaWithSHA "dsaWithSHA"
#define NID_dsaWithSHA 66
#define OBJ_dsaWithSHA OBJ_algorithm,13L
#define SN_shaWithRSAEncryption "RSA-SHA"
#define LN_shaWithRSAEncryption "shaWithRSAEncryption"
#define NID_shaWithRSAEncryption 42
#define OBJ_shaWithRSAEncryption OBJ_algorithm,15L
#define SN_des_ede_ecb "DES-EDE"
#define LN_des_ede_ecb "des-ede"
#define NID_des_ede_ecb 32
#define OBJ_des_ede_ecb OBJ_algorithm,17L
#define SN_des_ede3_ecb "DES-EDE3"
#define LN_des_ede3_ecb "des-ede3"
#define NID_des_ede3_ecb 33
#define SN_des_ede_cbc "DES-EDE-CBC"
#define LN_des_ede_cbc "des-ede-cbc"
#define NID_des_ede_cbc 43
#define SN_des_ede_cfb64 "DES-EDE-CFB"
#define LN_des_ede_cfb64 "des-ede-cfb"
#define NID_des_ede_cfb64 60
#define SN_des_ede3_cfb64 "DES-EDE3-CFB"
#define LN_des_ede3_cfb64 "des-ede3-cfb"
#define NID_des_ede3_cfb64 61
#define SN_des_ede_ofb64 "DES-EDE-OFB"
#define LN_des_ede_ofb64 "des-ede-ofb"
#define NID_des_ede_ofb64 62
#define SN_des_ede3_ofb64 "DES-EDE3-OFB"
#define LN_des_ede3_ofb64 "des-ede3-ofb"
#define NID_des_ede3_ofb64 63
#define SN_desx_cbc "DESX-CBC"
#define LN_desx_cbc "desx-cbc"
#define NID_desx_cbc 80
#define SN_sha "SHA"
#define LN_sha "sha"
#define NID_sha 41
#define OBJ_sha OBJ_algorithm,18L
#define SN_sha1 "SHA1"
#define LN_sha1 "sha1"
#define NID_sha1 64
#define OBJ_sha1 OBJ_algorithm,26L
#define SN_dsaWithSHA1_2 "DSA-SHA1-old"
#define LN_dsaWithSHA1_2 "dsaWithSHA1-old"
#define NID_dsaWithSHA1_2 70
#define OBJ_dsaWithSHA1_2 OBJ_algorithm,27L
#define SN_sha1WithRSA "RSA-SHA1-2"
#define LN_sha1WithRSA "sha1WithRSA"
#define NID_sha1WithRSA 115
#define OBJ_sha1WithRSA OBJ_algorithm,29L
#define SN_ripemd160 "RIPEMD160"
#define LN_ripemd160 "ripemd160"
#define NID_ripemd160 117
#define OBJ_ripemd160 1L,3L,36L,3L,2L,1L
#define SN_ripemd160WithRSA "RSA-RIPEMD160"
#define LN_ripemd160WithRSA "ripemd160WithRSA"
#define NID_ripemd160WithRSA 119
#define OBJ_ripemd160WithRSA 1L,3L,36L,3L,3L,1L,2L
#define SN_blake2b512 "BLAKE2b512"
#define LN_blake2b512 "blake2b512"
#define NID_blake2b512 1056
#define OBJ_blake2b512 1L,3L,6L,1L,4L,1L,1722L,12L,2L,1L,16L
#define SN_blake2s256 "BLAKE2s256"
#define LN_blake2s256 "blake2s256"
#define NID_blake2s256 1057
#define OBJ_blake2s256 1L,3L,6L,1L,4L,1L,1722L,12L,2L,2L,8L
#define SN_sxnet "SXNetID"
#define LN_sxnet "Strong Extranet ID"
#define NID_sxnet 143
#define OBJ_sxnet 1L,3L,101L,1L,4L,1L
#define SN_X500 "X500"
#define LN_X500 "directory services (X.500)"
#define NID_X500 11
#define OBJ_X500 2L,5L
#define SN_X509 "X509"
#define NID_X509 12
#define OBJ_X509 OBJ_X500,4L
#define SN_commonName "CN"
#define LN_commonName "commonName"
#define NID_commonName 13
#define OBJ_commonName OBJ_X509,3L
#define SN_surname "SN"
#define LN_surname "surname"
#define NID_surname 100
#define OBJ_surname OBJ_X509,4L
#define LN_serialNumber "serialNumber"
#define NID_serialNumber 105
#define OBJ_serialNumber OBJ_X509,5L
#define SN_countryName "C"
#define LN_countryName "countryName"
#define NID_countryName 14
#define OBJ_countryName OBJ_X509,6L
#define SN_localityName "L"
#define LN_localityName "localityName"
#define NID_localityName 15
#define OBJ_localityName OBJ_X509,7L
#define SN_stateOrProvinceName "ST"
#define LN_stateOrProvinceName "stateOrProvinceName"
#define NID_stateOrProvinceName 16
#define OBJ_stateOrProvinceName OBJ_X509,8L
#define SN_streetAddress "street"
#define LN_streetAddress "streetAddress"
#define NID_streetAddress 660
#define OBJ_streetAddress OBJ_X509,9L
#define SN_organizationName "O"
#define LN_organizationName "organizationName"
#define NID_organizationName 17
#define OBJ_organizationName OBJ_X509,10L
#define SN_organizationalUnitName "OU"
#define LN_organizationalUnitName "organizationalUnitName"
#define NID_organizationalUnitName 18
#define OBJ_organizationalUnitName OBJ_X509,11L
#define SN_title "title"
#define LN_title "title"
#define NID_title 106
#define OBJ_title OBJ_X509,12L
#define LN_description "description"
#define NID_description 107
#define OBJ_description OBJ_X509,13L
#define LN_searchGuide "searchGuide"
#define NID_searchGuide 859
#define OBJ_searchGuide OBJ_X509,14L
#define LN_businessCategory "businessCategory"
#define NID_businessCategory 860
#define OBJ_businessCategory OBJ_X509,15L
#define LN_postalAddress "postalAddress"
#define NID_postalAddress 861
#define OBJ_postalAddress OBJ_X509,16L
#define LN_postalCode "postalCode"
#define NID_postalCode 661
#define OBJ_postalCode OBJ_X509,17L
#define LN_postOfficeBox "postOfficeBox"
#define NID_postOfficeBox 862
#define OBJ_postOfficeBox OBJ_X509,18L
#define LN_physicalDeliveryOfficeName "physicalDeliveryOfficeName"
#define NID_physicalDeliveryOfficeName 863
#define OBJ_physicalDeliveryOfficeName OBJ_X509,19L
#define LN_telephoneNumber "telephoneNumber"
#define NID_telephoneNumber 864
#define OBJ_telephoneNumber OBJ_X509,20L
#define LN_telexNumber "telexNumber"
#define NID_telexNumber 865
#define OBJ_telexNumber OBJ_X509,21L
#define LN_teletexTerminalIdentifier "teletexTerminalIdentifier"
#define NID_teletexTerminalIdentifier 866
#define OBJ_teletexTerminalIdentifier OBJ_X509,22L
#define LN_facsimileTelephoneNumber "facsimileTelephoneNumber"
#define NID_facsimileTelephoneNumber 867
#define OBJ_facsimileTelephoneNumber OBJ_X509,23L
#define LN_x121Address "x121Address"
#define NID_x121Address 868
#define OBJ_x121Address OBJ_X509,24L
#define LN_internationaliSDNNumber "internationaliSDNNumber"
#define NID_internationaliSDNNumber 869
#define OBJ_internationaliSDNNumber OBJ_X509,25L
#define LN_registeredAddress "registeredAddress"
#define NID_registeredAddress 870
#define OBJ_registeredAddress OBJ_X509,26L
#define LN_destinationIndicator "destinationIndicator"
#define NID_destinationIndicator 871
#define OBJ_destinationIndicator OBJ_X509,27L
#define LN_preferredDeliveryMethod "preferredDeliveryMethod"
#define NID_preferredDeliveryMethod 872
#define OBJ_preferredDeliveryMethod OBJ_X509,28L
#define LN_presentationAddress "presentationAddress"
#define NID_presentationAddress 873
#define OBJ_presentationAddress OBJ_X509,29L
#define LN_supportedApplicationContext "supportedApplicationContext"
#define NID_supportedApplicationContext 874
#define OBJ_supportedApplicationContext OBJ_X509,30L
#define SN_member "member"
#define NID_member 875
#define OBJ_member OBJ_X509,31L
#define SN_owner "owner"
#define NID_owner 876
#define OBJ_owner OBJ_X509,32L
#define LN_roleOccupant "roleOccupant"
#define NID_roleOccupant 877
#define OBJ_roleOccupant OBJ_X509,33L
#define SN_seeAlso "seeAlso"
#define NID_seeAlso 878
#define OBJ_seeAlso OBJ_X509,34L
#define LN_userPassword "userPassword"
#define NID_userPassword 879
#define OBJ_userPassword OBJ_X509,35L
#define LN_userCertificate "userCertificate"
#define NID_userCertificate 880
#define OBJ_userCertificate OBJ_X509,36L
#define LN_cACertificate "cACertificate"
#define NID_cACertificate 881
#define OBJ_cACertificate OBJ_X509,37L
#define LN_authorityRevocationList "authorityRevocationList"
#define NID_authorityRevocationList 882
#define OBJ_authorityRevocationList OBJ_X509,38L
#define LN_certificateRevocationList "certificateRevocationList"
#define NID_certificateRevocationList 883
#define OBJ_certificateRevocationList OBJ_X509,39L
#define LN_crossCertificatePair "crossCertificatePair"
#define NID_crossCertificatePair 884
#define OBJ_crossCertificatePair OBJ_X509,40L
#define SN_name "name"
#define LN_name "name"
#define NID_name 173
#define OBJ_name OBJ_X509,41L
#define SN_givenName "GN"
#define LN_givenName "givenName"
#define NID_givenName 99
#define OBJ_givenName OBJ_X509,42L
#define SN_initials "initials"
#define LN_initials "initials"
#define NID_initials 101
#define OBJ_initials OBJ_X509,43L
#define LN_generationQualifier "generationQualifier"
#define NID_generationQualifier 509
#define OBJ_generationQualifier OBJ_X509,44L
#define LN_x500UniqueIdentifier "x500UniqueIdentifier"
#define NID_x500UniqueIdentifier 503
#define OBJ_x500UniqueIdentifier OBJ_X509,45L
#define SN_dnQualifier "dnQualifier"
#define LN_dnQualifier "dnQualifier"
#define NID_dnQualifier 174
#define OBJ_dnQualifier OBJ_X509,46L
#define LN_enhancedSearchGuide "enhancedSearchGuide"
#define NID_enhancedSearchGuide 885
#define OBJ_enhancedSearchGuide OBJ_X509,47L
#define LN_protocolInformation "protocolInformation"
#define NID_protocolInformation 886
#define OBJ_protocolInformation OBJ_X509,48L
#define LN_distinguishedName "distinguishedName"
#define NID_distinguishedName 887
#define OBJ_distinguishedName OBJ_X509,49L
#define LN_uniqueMember "uniqueMember"
#define NID_uniqueMember 888
#define OBJ_uniqueMember OBJ_X509,50L
#define LN_houseIdentifier "houseIdentifier"
#define NID_houseIdentifier 889
#define OBJ_houseIdentifier OBJ_X509,51L
#define LN_supportedAlgorithms "supportedAlgorithms"
#define NID_supportedAlgorithms 890
#define OBJ_supportedAlgorithms OBJ_X509,52L
#define LN_deltaRevocationList "deltaRevocationList"
#define NID_deltaRevocationList 891
#define OBJ_deltaRevocationList OBJ_X509,53L
#define SN_dmdName "dmdName"
#define NID_dmdName 892
#define OBJ_dmdName OBJ_X509,54L
#define LN_pseudonym "pseudonym"
#define NID_pseudonym 510
#define OBJ_pseudonym OBJ_X509,65L
#define SN_role "role"
#define LN_role "role"
#define NID_role 400
#define OBJ_role OBJ_X509,72L
#define LN_organizationIdentifier "organizationIdentifier"
#define NID_organizationIdentifier 1089
#define OBJ_organizationIdentifier OBJ_X509,97L
#define SN_countryCode3c "c3"
#define LN_countryCode3c "countryCode3c"
#define NID_countryCode3c 1090
#define OBJ_countryCode3c OBJ_X509,98L
#define SN_countryCode3n "n3"
#define LN_countryCode3n "countryCode3n"
#define NID_countryCode3n 1091
#define OBJ_countryCode3n OBJ_X509,99L
#define LN_dnsName "dnsName"
#define NID_dnsName 1092
#define OBJ_dnsName OBJ_X509,100L
#define SN_X500algorithms "X500algorithms"
#define LN_X500algorithms "directory services - algorithms"
#define NID_X500algorithms 378
#define OBJ_X500algorithms OBJ_X500,8L
#define SN_rsa "RSA"
#define LN_rsa "rsa"
#define NID_rsa 19
#define OBJ_rsa OBJ_X500algorithms,1L,1L
#define SN_mdc2WithRSA "RSA-MDC2"
#define LN_mdc2WithRSA "mdc2WithRSA"
#define NID_mdc2WithRSA 96
#define OBJ_mdc2WithRSA OBJ_X500algorithms,3L,100L
#define SN_mdc2 "MDC2"
#define LN_mdc2 "mdc2"
#define NID_mdc2 95
#define OBJ_mdc2 OBJ_X500algorithms,3L,101L
#define SN_id_ce "id-ce"
#define NID_id_ce 81
#define OBJ_id_ce OBJ_X500,29L
#define SN_subject_directory_attributes "subjectDirectoryAttributes"
#define LN_subject_directory_attributes "X509v3 Subject Directory Attributes"
#define NID_subject_directory_attributes 769
#define OBJ_subject_directory_attributes OBJ_id_ce,9L
#define SN_subject_key_identifier "subjectKeyIdentifier"
#define LN_subject_key_identifier "X509v3 Subject Key Identifier"
#define NID_subject_key_identifier 82
#define OBJ_subject_key_identifier OBJ_id_ce,14L
#define SN_key_usage "keyUsage"
#define LN_key_usage "X509v3 Key Usage"
#define NID_key_usage 83
#define OBJ_key_usage OBJ_id_ce,15L
#define SN_private_key_usage_period "privateKeyUsagePeriod"
#define LN_private_key_usage_period "X509v3 Private Key Usage Period"
#define NID_private_key_usage_period 84
#define OBJ_private_key_usage_period OBJ_id_ce,16L
#define SN_subject_alt_name "subjectAltName"
#define LN_subject_alt_name "X509v3 Subject Alternative Name"
#define NID_subject_alt_name 85
#define OBJ_subject_alt_name OBJ_id_ce,17L
#define SN_issuer_alt_name "issuerAltName"
#define LN_issuer_alt_name "X509v3 Issuer Alternative Name"
#define NID_issuer_alt_name 86
#define OBJ_issuer_alt_name OBJ_id_ce,18L
#define SN_basic_constraints "basicConstraints"
#define LN_basic_constraints "X509v3 Basic Constraints"
#define NID_basic_constraints 87
#define OBJ_basic_constraints OBJ_id_ce,19L
#define SN_crl_number "crlNumber"
#define LN_crl_number "X509v3 CRL Number"
#define NID_crl_number 88
#define OBJ_crl_number OBJ_id_ce,20L
#define SN_crl_reason "CRLReason"
#define LN_crl_reason "X509v3 CRL Reason Code"
#define NID_crl_reason 141
#define OBJ_crl_reason OBJ_id_ce,21L
#define SN_invalidity_date "invalidityDate"
#define LN_invalidity_date "Invalidity Date"
#define NID_invalidity_date 142
#define OBJ_invalidity_date OBJ_id_ce,24L
#define SN_delta_crl "deltaCRL"
#define LN_delta_crl "X509v3 Delta CRL Indicator"
#define NID_delta_crl 140
#define OBJ_delta_crl OBJ_id_ce,27L
#define SN_issuing_distribution_point "issuingDistributionPoint"
#define LN_issuing_distribution_point "X509v3 Issuing Distribution Point"
#define NID_issuing_distribution_point 770
#define OBJ_issuing_distribution_point OBJ_id_ce,28L
#define SN_certificate_issuer "certificateIssuer"
#define LN_certificate_issuer "X509v3 Certificate Issuer"
#define NID_certificate_issuer 771
#define OBJ_certificate_issuer OBJ_id_ce,29L
#define SN_name_constraints "nameConstraints"
#define LN_name_constraints "X509v3 Name Constraints"
#define NID_name_constraints 666
#define OBJ_name_constraints OBJ_id_ce,30L
#define SN_crl_distribution_points "crlDistributionPoints"
#define LN_crl_distribution_points "X509v3 CRL Distribution Points"
#define NID_crl_distribution_points 103
#define OBJ_crl_distribution_points OBJ_id_ce,31L
#define SN_certificate_policies "certificatePolicies"
#define LN_certificate_policies "X509v3 Certificate Policies"
#define NID_certificate_policies 89
#define OBJ_certificate_policies OBJ_id_ce,32L
#define SN_any_policy "anyPolicy"
#define LN_any_policy "X509v3 Any Policy"
#define NID_any_policy 746
#define OBJ_any_policy OBJ_certificate_policies,0L
#define SN_policy_mappings "policyMappings"
#define LN_policy_mappings "X509v3 Policy Mappings"
#define NID_policy_mappings 747
#define OBJ_policy_mappings OBJ_id_ce,33L
#define SN_authority_key_identifier "authorityKeyIdentifier"
#define LN_authority_key_identifier "X509v3 Authority Key Identifier"
#define NID_authority_key_identifier 90
#define OBJ_authority_key_identifier OBJ_id_ce,35L
#define SN_policy_constraints "policyConstraints"
#define LN_policy_constraints "X509v3 Policy Constraints"
#define NID_policy_constraints 401
#define OBJ_policy_constraints OBJ_id_ce,36L
#define SN_ext_key_usage "extendedKeyUsage"
#define LN_ext_key_usage "X509v3 Extended Key Usage"
#define NID_ext_key_usage 126
#define OBJ_ext_key_usage OBJ_id_ce,37L
#define SN_freshest_crl "freshestCRL"
#define LN_freshest_crl "X509v3 Freshest CRL"
#define NID_freshest_crl 857
#define OBJ_freshest_crl OBJ_id_ce,46L
#define SN_inhibit_any_policy "inhibitAnyPolicy"
#define LN_inhibit_any_policy "X509v3 Inhibit Any Policy"
#define NID_inhibit_any_policy 748
#define OBJ_inhibit_any_policy OBJ_id_ce,54L
#define SN_target_information "targetInformation"
#define LN_target_information "X509v3 AC Targeting"
#define NID_target_information 402
#define OBJ_target_information OBJ_id_ce,55L
#define SN_no_rev_avail "noRevAvail"
#define LN_no_rev_avail "X509v3 No Revocation Available"
#define NID_no_rev_avail 403
#define OBJ_no_rev_avail OBJ_id_ce,56L
#define SN_anyExtendedKeyUsage "anyExtendedKeyUsage"
#define LN_anyExtendedKeyUsage "Any Extended Key Usage"
#define NID_anyExtendedKeyUsage 910
#define OBJ_anyExtendedKeyUsage OBJ_ext_key_usage,0L
#define SN_netscape "Netscape"
#define LN_netscape "Netscape Communications Corp."
#define NID_netscape 57
#define OBJ_netscape 2L,16L,840L,1L,113730L
#define SN_netscape_cert_extension "nsCertExt"
#define LN_netscape_cert_extension "Netscape Certificate Extension"
#define NID_netscape_cert_extension 58
#define OBJ_netscape_cert_extension OBJ_netscape,1L
#define SN_netscape_data_type "nsDataType"
#define LN_netscape_data_type "Netscape Data Type"
#define NID_netscape_data_type 59
#define OBJ_netscape_data_type OBJ_netscape,2L
#define SN_netscape_cert_type "nsCertType"
#define LN_netscape_cert_type "Netscape Cert Type"
#define NID_netscape_cert_type 71
#define OBJ_netscape_cert_type OBJ_netscape_cert_extension,1L
#define SN_netscape_base_url "nsBaseUrl"
#define LN_netscape_base_url "Netscape Base Url"
#define NID_netscape_base_url 72
#define OBJ_netscape_base_url OBJ_netscape_cert_extension,2L
#define SN_netscape_revocation_url "nsRevocationUrl"
#define LN_netscape_revocation_url "Netscape Revocation Url"
#define NID_netscape_revocation_url 73
#define OBJ_netscape_revocation_url OBJ_netscape_cert_extension,3L
#define SN_netscape_ca_revocation_url "nsCaRevocationUrl"
#define LN_netscape_ca_revocation_url "Netscape CA Revocation Url"
#define NID_netscape_ca_revocation_url 74
#define OBJ_netscape_ca_revocation_url OBJ_netscape_cert_extension,4L
#define SN_netscape_renewal_url "nsRenewalUrl"
#define LN_netscape_renewal_url "Netscape Renewal Url"
#define NID_netscape_renewal_url 75
#define OBJ_netscape_renewal_url OBJ_netscape_cert_extension,7L
#define SN_netscape_ca_policy_url "nsCaPolicyUrl"
#define LN_netscape_ca_policy_url "Netscape CA Policy Url"
#define NID_netscape_ca_policy_url 76
#define OBJ_netscape_ca_policy_url OBJ_netscape_cert_extension,8L
#define SN_netscape_ssl_server_name "nsSslServerName"
#define LN_netscape_ssl_server_name "Netscape SSL Server Name"
#define NID_netscape_ssl_server_name 77
#define OBJ_netscape_ssl_server_name OBJ_netscape_cert_extension,12L
#define SN_netscape_comment "nsComment"
#define LN_netscape_comment "Netscape Comment"
#define NID_netscape_comment 78
#define OBJ_netscape_comment OBJ_netscape_cert_extension,13L
#define SN_netscape_cert_sequence "nsCertSequence"
#define LN_netscape_cert_sequence "Netscape Certificate Sequence"
#define NID_netscape_cert_sequence 79
#define OBJ_netscape_cert_sequence OBJ_netscape_data_type,5L
#define SN_ns_sgc "nsSGC"
#define LN_ns_sgc "Netscape Server Gated Crypto"
#define NID_ns_sgc 139
#define OBJ_ns_sgc OBJ_netscape,4L,1L
#define SN_org "ORG"
#define LN_org "org"
#define NID_org 379
#define OBJ_org OBJ_iso,3L
#define SN_dod "DOD"
#define LN_dod "dod"
#define NID_dod 380
#define OBJ_dod OBJ_org,6L
#define SN_iana "IANA"
#define LN_iana "iana"
#define NID_iana 381
#define OBJ_iana OBJ_dod,1L
#define OBJ_internet OBJ_iana
#define SN_Directory "directory"
#define LN_Directory "Directory"
#define NID_Directory 382
#define OBJ_Directory OBJ_internet,1L
#define SN_Management "mgmt"
#define LN_Management "Management"
#define NID_Management 383
#define OBJ_Management OBJ_internet,2L
#define SN_Experimental "experimental"
#define LN_Experimental "Experimental"
#define NID_Experimental 384
#define OBJ_Experimental OBJ_internet,3L
#define SN_Private "private"
#define LN_Private "Private"
#define NID_Private 385
#define OBJ_Private OBJ_internet,4L
#define SN_Security "security"
#define LN_Security "Security"
#define NID_Security 386
#define OBJ_Security OBJ_internet,5L
#define SN_SNMPv2 "snmpv2"
#define LN_SNMPv2 "SNMPv2"
#define NID_SNMPv2 387
#define OBJ_SNMPv2 OBJ_internet,6L
#define LN_Mail "Mail"
#define NID_Mail 388
#define OBJ_Mail OBJ_internet,7L
#define SN_Enterprises "enterprises"
#define LN_Enterprises "Enterprises"
#define NID_Enterprises 389
#define OBJ_Enterprises OBJ_Private,1L
#define SN_dcObject "dcobject"
#define LN_dcObject "dcObject"
#define NID_dcObject 390
#define OBJ_dcObject OBJ_Enterprises,1466L,344L
#define SN_mime_mhs "mime-mhs"
#define LN_mime_mhs "MIME MHS"
#define NID_mime_mhs 504
#define OBJ_mime_mhs OBJ_Mail,1L
#define SN_mime_mhs_headings "mime-mhs-headings"
#define LN_mime_mhs_headings "mime-mhs-headings"
#define NID_mime_mhs_headings 505
#define OBJ_mime_mhs_headings OBJ_mime_mhs,1L
#define SN_mime_mhs_bodies "mime-mhs-bodies"
#define LN_mime_mhs_bodies "mime-mhs-bodies"
#define NID_mime_mhs_bodies 506
#define OBJ_mime_mhs_bodies OBJ_mime_mhs,2L
#define SN_id_hex_partial_message "id-hex-partial-message"
#define LN_id_hex_partial_message "id-hex-partial-message"
#define NID_id_hex_partial_message 507
#define OBJ_id_hex_partial_message OBJ_mime_mhs_headings,1L
#define SN_id_hex_multipart_message "id-hex-multipart-message"
#define LN_id_hex_multipart_message "id-hex-multipart-message"
#define NID_id_hex_multipart_message 508
#define OBJ_id_hex_multipart_message OBJ_mime_mhs_headings,2L
#define SN_zlib_compression "ZLIB"
#define LN_zlib_compression "zlib compression"
#define NID_zlib_compression 125
#define OBJ_zlib_compression OBJ_id_smime_alg,8L
#define OBJ_csor 2L,16L,840L,1L,101L,3L
#define OBJ_nistAlgorithms OBJ_csor,4L
#define OBJ_aes OBJ_nistAlgorithms,1L
#define SN_aes_128_ecb "AES-128-ECB"
#define LN_aes_128_ecb "aes-128-ecb"
#define NID_aes_128_ecb 418
#define OBJ_aes_128_ecb OBJ_aes,1L
#define SN_aes_128_cbc "AES-128-CBC"
#define LN_aes_128_cbc "aes-128-cbc"
#define NID_aes_128_cbc 419
#define OBJ_aes_128_cbc OBJ_aes,2L
#define SN_aes_128_ofb128 "AES-128-OFB"
#define LN_aes_128_ofb128 "aes-128-ofb"
#define NID_aes_128_ofb128 420
#define OBJ_aes_128_ofb128 OBJ_aes,3L
#define SN_aes_128_cfb128 "AES-128-CFB"
#define LN_aes_128_cfb128 "aes-128-cfb"
#define NID_aes_128_cfb128 421
#define OBJ_aes_128_cfb128 OBJ_aes,4L
#define SN_id_aes128_wrap "id-aes128-wrap"
#define NID_id_aes128_wrap 788
#define OBJ_id_aes128_wrap OBJ_aes,5L
#define SN_aes_128_gcm "id-aes128-GCM"
#define LN_aes_128_gcm "aes-128-gcm"
#define NID_aes_128_gcm 895
#define OBJ_aes_128_gcm OBJ_aes,6L
#define SN_aes_128_ccm "id-aes128-CCM"
#define LN_aes_128_ccm "aes-128-ccm"
#define NID_aes_128_ccm 896
#define OBJ_aes_128_ccm OBJ_aes,7L
#define SN_id_aes128_wrap_pad "id-aes128-wrap-pad"
#define NID_id_aes128_wrap_pad 897
#define OBJ_id_aes128_wrap_pad OBJ_aes,8L
#define SN_aes_192_ecb "AES-192-ECB"
#define LN_aes_192_ecb "aes-192-ecb"
#define NID_aes_192_ecb 422
#define OBJ_aes_192_ecb OBJ_aes,21L
#define SN_aes_192_cbc "AES-192-CBC"
#define LN_aes_192_cbc "aes-192-cbc"
#define NID_aes_192_cbc 423
#define OBJ_aes_192_cbc OBJ_aes,22L
#define SN_aes_192_ofb128 "AES-192-OFB"
#define LN_aes_192_ofb128 "aes-192-ofb"
#define NID_aes_192_ofb128 424
#define OBJ_aes_192_ofb128 OBJ_aes,23L
#define SN_aes_192_cfb128 "AES-192-CFB"
#define LN_aes_192_cfb128 "aes-192-cfb"
#define NID_aes_192_cfb128 425
#define OBJ_aes_192_cfb128 OBJ_aes,24L
#define SN_id_aes192_wrap "id-aes192-wrap"
#define NID_id_aes192_wrap 789
#define OBJ_id_aes192_wrap OBJ_aes,25L
#define SN_aes_192_gcm "id-aes192-GCM"
#define LN_aes_192_gcm "aes-192-gcm"
#define NID_aes_192_gcm 898
#define OBJ_aes_192_gcm OBJ_aes,26L
#define SN_aes_192_ccm "id-aes192-CCM"
#define LN_aes_192_ccm "aes-192-ccm"
#define NID_aes_192_ccm 899
#define OBJ_aes_192_ccm OBJ_aes,27L
#define SN_id_aes192_wrap_pad "id-aes192-wrap-pad"
#define NID_id_aes192_wrap_pad 900
#define OBJ_id_aes192_wrap_pad OBJ_aes,28L
#define SN_aes_256_ecb "AES-256-ECB"
#define LN_aes_256_ecb "aes-256-ecb"
#define NID_aes_256_ecb 426
#define OBJ_aes_256_ecb OBJ_aes,41L
#define SN_aes_256_cbc "AES-256-CBC"
#define LN_aes_256_cbc "aes-256-cbc"
#define NID_aes_256_cbc 427
#define OBJ_aes_256_cbc OBJ_aes,42L
#define SN_aes_256_ofb128 "AES-256-OFB"
#define LN_aes_256_ofb128 "aes-256-ofb"
#define NID_aes_256_ofb128 428
#define OBJ_aes_256_ofb128 OBJ_aes,43L
#define SN_aes_256_cfb128 "AES-256-CFB"
#define LN_aes_256_cfb128 "aes-256-cfb"
#define NID_aes_256_cfb128 429
#define OBJ_aes_256_cfb128 OBJ_aes,44L
#define SN_id_aes256_wrap "id-aes256-wrap"
#define NID_id_aes256_wrap 790
#define OBJ_id_aes256_wrap OBJ_aes,45L
#define SN_aes_256_gcm "id-aes256-GCM"
#define LN_aes_256_gcm "aes-256-gcm"
#define NID_aes_256_gcm 901
#define OBJ_aes_256_gcm OBJ_aes,46L
#define SN_aes_256_ccm "id-aes256-CCM"
#define LN_aes_256_ccm "aes-256-ccm"
#define NID_aes_256_ccm 902
#define OBJ_aes_256_ccm OBJ_aes,47L
#define SN_id_aes256_wrap_pad "id-aes256-wrap-pad"
#define NID_id_aes256_wrap_pad 903
#define OBJ_id_aes256_wrap_pad OBJ_aes,48L
#define SN_aes_128_xts "AES-128-XTS"
#define LN_aes_128_xts "aes-128-xts"
#define NID_aes_128_xts 913
#define OBJ_aes_128_xts OBJ_ieee_siswg,0L,1L,1L
#define SN_aes_256_xts "AES-256-XTS"
#define LN_aes_256_xts "aes-256-xts"
#define NID_aes_256_xts 914
#define OBJ_aes_256_xts OBJ_ieee_siswg,0L,1L,2L
#define SN_aes_128_cfb1 "AES-128-CFB1"
#define LN_aes_128_cfb1 "aes-128-cfb1"
#define NID_aes_128_cfb1 650
#define SN_aes_192_cfb1 "AES-192-CFB1"
#define LN_aes_192_cfb1 "aes-192-cfb1"
#define NID_aes_192_cfb1 651
#define SN_aes_256_cfb1 "AES-256-CFB1"
#define LN_aes_256_cfb1 "aes-256-cfb1"
#define NID_aes_256_cfb1 652
#define SN_aes_128_cfb8 "AES-128-CFB8"
#define LN_aes_128_cfb8 "aes-128-cfb8"
#define NID_aes_128_cfb8 653
#define SN_aes_192_cfb8 "AES-192-CFB8"
#define LN_aes_192_cfb8 "aes-192-cfb8"
#define NID_aes_192_cfb8 654
#define SN_aes_256_cfb8 "AES-256-CFB8"
#define LN_aes_256_cfb8 "aes-256-cfb8"
#define NID_aes_256_cfb8 655
#define SN_aes_128_ctr "AES-128-CTR"
#define LN_aes_128_ctr "aes-128-ctr"
#define NID_aes_128_ctr 904
#define SN_aes_192_ctr "AES-192-CTR"
#define LN_aes_192_ctr "aes-192-ctr"
#define NID_aes_192_ctr 905
#define SN_aes_256_ctr "AES-256-CTR"
#define LN_aes_256_ctr "aes-256-ctr"
#define NID_aes_256_ctr 906
#define SN_aes_128_ocb "AES-128-OCB"
#define LN_aes_128_ocb "aes-128-ocb"
#define NID_aes_128_ocb 958
#define SN_aes_192_ocb "AES-192-OCB"
#define LN_aes_192_ocb "aes-192-ocb"
#define NID_aes_192_ocb 959
#define SN_aes_256_ocb "AES-256-OCB"
#define LN_aes_256_ocb "aes-256-ocb"
#define NID_aes_256_ocb 960
#define SN_des_cfb1 "DES-CFB1"
#define LN_des_cfb1 "des-cfb1"
#define NID_des_cfb1 656
#define SN_des_cfb8 "DES-CFB8"
#define LN_des_cfb8 "des-cfb8"
#define NID_des_cfb8 657
#define SN_des_ede3_cfb1 "DES-EDE3-CFB1"
#define LN_des_ede3_cfb1 "des-ede3-cfb1"
#define NID_des_ede3_cfb1 658
#define SN_des_ede3_cfb8 "DES-EDE3-CFB8"
#define LN_des_ede3_cfb8 "des-ede3-cfb8"
#define NID_des_ede3_cfb8 659
#define OBJ_nist_hashalgs OBJ_nistAlgorithms,2L
#define SN_sha256 "SHA256"
#define LN_sha256 "sha256"
#define NID_sha256 672
#define OBJ_sha256 OBJ_nist_hashalgs,1L
#define SN_sha384 "SHA384"
#define LN_sha384 "sha384"
#define NID_sha384 673
#define OBJ_sha384 OBJ_nist_hashalgs,2L
#define SN_sha512 "SHA512"
#define LN_sha512 "sha512"
#define NID_sha512 674
#define OBJ_sha512 OBJ_nist_hashalgs,3L
#define SN_sha224 "SHA224"
#define LN_sha224 "sha224"
#define NID_sha224 675
#define OBJ_sha224 OBJ_nist_hashalgs,4L
#define SN_sha512_224 "SHA512-224"
#define LN_sha512_224 "sha512-224"
#define NID_sha512_224 1094
#define OBJ_sha512_224 OBJ_nist_hashalgs,5L
#define SN_sha512_256 "SHA512-256"
#define LN_sha512_256 "sha512-256"
#define NID_sha512_256 1095
#define OBJ_sha512_256 OBJ_nist_hashalgs,6L
#define SN_sha3_224 "SHA3-224"
#define LN_sha3_224 "sha3-224"
#define NID_sha3_224 1096
#define OBJ_sha3_224 OBJ_nist_hashalgs,7L
#define SN_sha3_256 "SHA3-256"
#define LN_sha3_256 "sha3-256"
#define NID_sha3_256 1097
#define OBJ_sha3_256 OBJ_nist_hashalgs,8L
#define SN_sha3_384 "SHA3-384"
#define LN_sha3_384 "sha3-384"
#define NID_sha3_384 1098
#define OBJ_sha3_384 OBJ_nist_hashalgs,9L
#define SN_sha3_512 "SHA3-512"
#define LN_sha3_512 "sha3-512"
#define NID_sha3_512 1099
#define OBJ_sha3_512 OBJ_nist_hashalgs,10L
#define SN_shake128 "SHAKE128"
#define LN_shake128 "shake128"
#define NID_shake128 1100
#define OBJ_shake128 OBJ_nist_hashalgs,11L
#define SN_shake256 "SHAKE256"
#define LN_shake256 "shake256"
#define NID_shake256 1101
#define OBJ_shake256 OBJ_nist_hashalgs,12L
#define SN_hmac_sha3_224 "id-hmacWithSHA3-224"
#define LN_hmac_sha3_224 "hmac-sha3-224"
#define NID_hmac_sha3_224 1102
#define OBJ_hmac_sha3_224 OBJ_nist_hashalgs,13L
#define SN_hmac_sha3_256 "id-hmacWithSHA3-256"
#define LN_hmac_sha3_256 "hmac-sha3-256"
#define NID_hmac_sha3_256 1103
#define OBJ_hmac_sha3_256 OBJ_nist_hashalgs,14L
#define SN_hmac_sha3_384 "id-hmacWithSHA3-384"
#define LN_hmac_sha3_384 "hmac-sha3-384"
#define NID_hmac_sha3_384 1104
#define OBJ_hmac_sha3_384 OBJ_nist_hashalgs,15L
#define SN_hmac_sha3_512 "id-hmacWithSHA3-512"
#define LN_hmac_sha3_512 "hmac-sha3-512"
#define NID_hmac_sha3_512 1105
#define OBJ_hmac_sha3_512 OBJ_nist_hashalgs,16L
#define OBJ_dsa_with_sha2 OBJ_nistAlgorithms,3L
#define SN_dsa_with_SHA224 "dsa_with_SHA224"
#define NID_dsa_with_SHA224 802
#define OBJ_dsa_with_SHA224 OBJ_dsa_with_sha2,1L
#define SN_dsa_with_SHA256 "dsa_with_SHA256"
#define NID_dsa_with_SHA256 803
#define OBJ_dsa_with_SHA256 OBJ_dsa_with_sha2,2L
#define OBJ_sigAlgs OBJ_nistAlgorithms,3L
#define SN_dsa_with_SHA384 "id-dsa-with-sha384"
#define LN_dsa_with_SHA384 "dsa_with_SHA384"
#define NID_dsa_with_SHA384 1106
#define OBJ_dsa_with_SHA384 OBJ_sigAlgs,3L
#define SN_dsa_with_SHA512 "id-dsa-with-sha512"
#define LN_dsa_with_SHA512 "dsa_with_SHA512"
#define NID_dsa_with_SHA512 1107
#define OBJ_dsa_with_SHA512 OBJ_sigAlgs,4L
#define SN_dsa_with_SHA3_224 "id-dsa-with-sha3-224"
#define LN_dsa_with_SHA3_224 "dsa_with_SHA3-224"
#define NID_dsa_with_SHA3_224 1108
#define OBJ_dsa_with_SHA3_224 OBJ_sigAlgs,5L
#define SN_dsa_with_SHA3_256 "id-dsa-with-sha3-256"
#define LN_dsa_with_SHA3_256 "dsa_with_SHA3-256"
#define NID_dsa_with_SHA3_256 1109
#define OBJ_dsa_with_SHA3_256 OBJ_sigAlgs,6L
#define SN_dsa_with_SHA3_384 "id-dsa-with-sha3-384"
#define LN_dsa_with_SHA3_384 "dsa_with_SHA3-384"
#define NID_dsa_with_SHA3_384 1110
#define OBJ_dsa_with_SHA3_384 OBJ_sigAlgs,7L
#define SN_dsa_with_SHA3_512 "id-dsa-with-sha3-512"
#define LN_dsa_with_SHA3_512 "dsa_with_SHA3-512"
#define NID_dsa_with_SHA3_512 1111
#define OBJ_dsa_with_SHA3_512 OBJ_sigAlgs,8L
#define SN_ecdsa_with_SHA3_224 "id-ecdsa-with-sha3-224"
#define LN_ecdsa_with_SHA3_224 "ecdsa_with_SHA3-224"
#define NID_ecdsa_with_SHA3_224 1112
#define OBJ_ecdsa_with_SHA3_224 OBJ_sigAlgs,9L
#define SN_ecdsa_with_SHA3_256 "id-ecdsa-with-sha3-256"
#define LN_ecdsa_with_SHA3_256 "ecdsa_with_SHA3-256"
#define NID_ecdsa_with_SHA3_256 1113
#define OBJ_ecdsa_with_SHA3_256 OBJ_sigAlgs,10L
#define SN_ecdsa_with_SHA3_384 "id-ecdsa-with-sha3-384"
#define LN_ecdsa_with_SHA3_384 "ecdsa_with_SHA3-384"
#define NID_ecdsa_with_SHA3_384 1114
#define OBJ_ecdsa_with_SHA3_384 OBJ_sigAlgs,11L
#define SN_ecdsa_with_SHA3_512 "id-ecdsa-with-sha3-512"
#define LN_ecdsa_with_SHA3_512 "ecdsa_with_SHA3-512"
#define NID_ecdsa_with_SHA3_512 1115
#define OBJ_ecdsa_with_SHA3_512 OBJ_sigAlgs,12L
#define SN_RSA_SHA3_224 "id-rsassa-pkcs1-v1_5-with-sha3-224"
#define LN_RSA_SHA3_224 "RSA-SHA3-224"
#define NID_RSA_SHA3_224 1116
#define OBJ_RSA_SHA3_224 OBJ_sigAlgs,13L
#define SN_RSA_SHA3_256 "id-rsassa-pkcs1-v1_5-with-sha3-256"
#define LN_RSA_SHA3_256 "RSA-SHA3-256"
#define NID_RSA_SHA3_256 1117
#define OBJ_RSA_SHA3_256 OBJ_sigAlgs,14L
#define SN_RSA_SHA3_384 "id-rsassa-pkcs1-v1_5-with-sha3-384"
#define LN_RSA_SHA3_384 "RSA-SHA3-384"
#define NID_RSA_SHA3_384 1118
#define OBJ_RSA_SHA3_384 OBJ_sigAlgs,15L
#define SN_RSA_SHA3_512 "id-rsassa-pkcs1-v1_5-with-sha3-512"
#define LN_RSA_SHA3_512 "RSA-SHA3-512"
#define NID_RSA_SHA3_512 1119
#define OBJ_RSA_SHA3_512 OBJ_sigAlgs,16L
#define SN_hold_instruction_code "holdInstructionCode"
#define LN_hold_instruction_code "Hold Instruction Code"
#define NID_hold_instruction_code 430
#define OBJ_hold_instruction_code OBJ_id_ce,23L
#define OBJ_holdInstruction OBJ_X9_57,2L
#define SN_hold_instruction_none "holdInstructionNone"
#define LN_hold_instruction_none "Hold Instruction None"
#define NID_hold_instruction_none 431
#define OBJ_hold_instruction_none OBJ_holdInstruction,1L
#define SN_hold_instruction_call_issuer "holdInstructionCallIssuer"
#define LN_hold_instruction_call_issuer "Hold Instruction Call Issuer"
#define NID_hold_instruction_call_issuer 432
#define OBJ_hold_instruction_call_issuer OBJ_holdInstruction,2L
#define SN_hold_instruction_reject "holdInstructionReject"
#define LN_hold_instruction_reject "Hold Instruction Reject"
#define NID_hold_instruction_reject 433
#define OBJ_hold_instruction_reject OBJ_holdInstruction,3L
#define SN_data "data"
#define NID_data 434
#define OBJ_data OBJ_itu_t,9L
#define SN_pss "pss"
#define NID_pss 435
#define OBJ_pss OBJ_data,2342L
#define SN_ucl "ucl"
#define NID_ucl 436
#define OBJ_ucl OBJ_pss,19200300L
#define SN_pilot "pilot"
#define NID_pilot 437
#define OBJ_pilot OBJ_ucl,100L
#define LN_pilotAttributeType "pilotAttributeType"
#define NID_pilotAttributeType 438
#define OBJ_pilotAttributeType OBJ_pilot,1L
#define LN_pilotAttributeSyntax "pilotAttributeSyntax"
#define NID_pilotAttributeSyntax 439
#define OBJ_pilotAttributeSyntax OBJ_pilot,3L
#define LN_pilotObjectClass "pilotObjectClass"
#define NID_pilotObjectClass 440
#define OBJ_pilotObjectClass OBJ_pilot,4L
#define LN_pilotGroups "pilotGroups"
#define NID_pilotGroups 441
#define OBJ_pilotGroups OBJ_pilot,10L
#define LN_iA5StringSyntax "iA5StringSyntax"
#define NID_iA5StringSyntax 442
#define OBJ_iA5StringSyntax OBJ_pilotAttributeSyntax,4L
#define LN_caseIgnoreIA5StringSyntax "caseIgnoreIA5StringSyntax"
#define NID_caseIgnoreIA5StringSyntax 443
#define OBJ_caseIgnoreIA5StringSyntax OBJ_pilotAttributeSyntax,5L
#define LN_pilotObject "pilotObject"
#define NID_pilotObject 444
#define OBJ_pilotObject OBJ_pilotObjectClass,3L
#define LN_pilotPerson "pilotPerson"
#define NID_pilotPerson 445
#define OBJ_pilotPerson OBJ_pilotObjectClass,4L
#define SN_account "account"
#define NID_account 446
#define OBJ_account OBJ_pilotObjectClass,5L
#define SN_document "document"
#define NID_document 447
#define OBJ_document OBJ_pilotObjectClass,6L
#define SN_room "room"
#define NID_room 448
#define OBJ_room OBJ_pilotObjectClass,7L
#define LN_documentSeries "documentSeries"
#define NID_documentSeries 449
#define OBJ_documentSeries OBJ_pilotObjectClass,9L
#define SN_Domain "domain"
#define LN_Domain "Domain"
#define NID_Domain 392
#define OBJ_Domain OBJ_pilotObjectClass,13L
#define LN_rFC822localPart "rFC822localPart"
#define NID_rFC822localPart 450
#define OBJ_rFC822localPart OBJ_pilotObjectClass,14L
#define LN_dNSDomain "dNSDomain"
#define NID_dNSDomain 451
#define OBJ_dNSDomain OBJ_pilotObjectClass,15L
#define LN_domainRelatedObject "domainRelatedObject"
#define NID_domainRelatedObject 452
#define OBJ_domainRelatedObject OBJ_pilotObjectClass,17L
#define LN_friendlyCountry "friendlyCountry"
#define NID_friendlyCountry 453
#define OBJ_friendlyCountry OBJ_pilotObjectClass,18L
#define LN_simpleSecurityObject "simpleSecurityObject"
#define NID_simpleSecurityObject 454
#define OBJ_simpleSecurityObject OBJ_pilotObjectClass,19L
#define LN_pilotOrganization "pilotOrganization"
#define NID_pilotOrganization 455
#define OBJ_pilotOrganization OBJ_pilotObjectClass,20L
#define LN_pilotDSA "pilotDSA"
#define NID_pilotDSA 456
#define OBJ_pilotDSA OBJ_pilotObjectClass,21L
#define LN_qualityLabelledData "qualityLabelledData"
#define NID_qualityLabelledData 457
#define OBJ_qualityLabelledData OBJ_pilotObjectClass,22L
#define SN_userId "UID"
#define LN_userId "userId"
#define NID_userId 458
#define OBJ_userId OBJ_pilotAttributeType,1L
#define LN_textEncodedORAddress "textEncodedORAddress"
#define NID_textEncodedORAddress 459
#define OBJ_textEncodedORAddress OBJ_pilotAttributeType,2L
#define SN_rfc822Mailbox "mail"
#define LN_rfc822Mailbox "rfc822Mailbox"
#define NID_rfc822Mailbox 460
#define OBJ_rfc822Mailbox OBJ_pilotAttributeType,3L
#define SN_info "info"
#define NID_info 461
#define OBJ_info OBJ_pilotAttributeType,4L
#define LN_favouriteDrink "favouriteDrink"
#define NID_favouriteDrink 462
#define OBJ_favouriteDrink OBJ_pilotAttributeType,5L
#define LN_roomNumber "roomNumber"
#define NID_roomNumber 463
#define OBJ_roomNumber OBJ_pilotAttributeType,6L
#define SN_photo "photo"
#define NID_photo 464
#define OBJ_photo OBJ_pilotAttributeType,7L
#define LN_userClass "userClass"
#define NID_userClass 465
#define OBJ_userClass OBJ_pilotAttributeType,8L
#define SN_host "host"
#define NID_host 466
#define OBJ_host OBJ_pilotAttributeType,9L
#define SN_manager "manager"
#define NID_manager 467
#define OBJ_manager OBJ_pilotAttributeType,10L
#define LN_documentIdentifier "documentIdentifier"
#define NID_documentIdentifier 468
#define OBJ_documentIdentifier OBJ_pilotAttributeType,11L
#define LN_documentTitle "documentTitle"
#define NID_documentTitle 469
#define OBJ_documentTitle OBJ_pilotAttributeType,12L
#define LN_documentVersion "documentVersion"
#define NID_documentVersion 470
#define OBJ_documentVersion OBJ_pilotAttributeType,13L
#define LN_documentAuthor "documentAuthor"
#define NID_documentAuthor 471
#define OBJ_documentAuthor OBJ_pilotAttributeType,14L
#define LN_documentLocation "documentLocation"
#define NID_documentLocation 472
#define OBJ_documentLocation OBJ_pilotAttributeType,15L
#define LN_homeTelephoneNumber "homeTelephoneNumber"
#define NID_homeTelephoneNumber 473
#define OBJ_homeTelephoneNumber OBJ_pilotAttributeType,20L
#define SN_secretary "secretary"
#define NID_secretary 474
#define OBJ_secretary OBJ_pilotAttributeType,21L
#define LN_otherMailbox "otherMailbox"
#define NID_otherMailbox 475
#define OBJ_otherMailbox OBJ_pilotAttributeType,22L
#define LN_lastModifiedTime "lastModifiedTime"
#define NID_lastModifiedTime 476
#define OBJ_lastModifiedTime OBJ_pilotAttributeType,23L
#define LN_lastModifiedBy "lastModifiedBy"
#define NID_lastModifiedBy 477
#define OBJ_lastModifiedBy OBJ_pilotAttributeType,24L
#define SN_domainComponent "DC"
#define LN_domainComponent "domainComponent"
#define NID_domainComponent 391
#define OBJ_domainComponent OBJ_pilotAttributeType,25L
#define LN_aRecord "aRecord"
#define NID_aRecord 478
#define OBJ_aRecord OBJ_pilotAttributeType,26L
#define LN_pilotAttributeType27 "pilotAttributeType27"
#define NID_pilotAttributeType27 479
#define OBJ_pilotAttributeType27 OBJ_pilotAttributeType,27L
#define LN_mXRecord "mXRecord"
#define NID_mXRecord 480
#define OBJ_mXRecord OBJ_pilotAttributeType,28L
#define LN_nSRecord "nSRecord"
#define NID_nSRecord 481
#define OBJ_nSRecord OBJ_pilotAttributeType,29L
#define LN_sOARecord "sOARecord"
#define NID_sOARecord 482
#define OBJ_sOARecord OBJ_pilotAttributeType,30L
#define LN_cNAMERecord "cNAMERecord"
#define NID_cNAMERecord 483
#define OBJ_cNAMERecord OBJ_pilotAttributeType,31L
#define LN_associatedDomain "associatedDomain"
#define NID_associatedDomain 484
#define OBJ_associatedDomain OBJ_pilotAttributeType,37L
#define LN_associatedName "associatedName"
#define NID_associatedName 485
#define OBJ_associatedName OBJ_pilotAttributeType,38L
#define LN_homePostalAddress "homePostalAddress"
#define NID_homePostalAddress 486
#define OBJ_homePostalAddress OBJ_pilotAttributeType,39L
#define LN_personalTitle "personalTitle"
#define NID_personalTitle 487
#define OBJ_personalTitle OBJ_pilotAttributeType,40L
#define LN_mobileTelephoneNumber "mobileTelephoneNumber"
#define NID_mobileTelephoneNumber 488
#define OBJ_mobileTelephoneNumber OBJ_pilotAttributeType,41L
#define LN_pagerTelephoneNumber "pagerTelephoneNumber"
#define NID_pagerTelephoneNumber 489
#define OBJ_pagerTelephoneNumber OBJ_pilotAttributeType,42L
#define LN_friendlyCountryName "friendlyCountryName"
#define NID_friendlyCountryName 490
#define OBJ_friendlyCountryName OBJ_pilotAttributeType,43L
#define SN_uniqueIdentifier "uid"
#define LN_uniqueIdentifier "uniqueIdentifier"
#define NID_uniqueIdentifier 102
#define OBJ_uniqueIdentifier OBJ_pilotAttributeType,44L
#define LN_organizationalStatus "organizationalStatus"
#define NID_organizationalStatus 491
#define OBJ_organizationalStatus OBJ_pilotAttributeType,45L
#define LN_janetMailbox "janetMailbox"
#define NID_janetMailbox 492
#define OBJ_janetMailbox OBJ_pilotAttributeType,46L
#define LN_mailPreferenceOption "mailPreferenceOption"
#define NID_mailPreferenceOption 493
#define OBJ_mailPreferenceOption OBJ_pilotAttributeType,47L
#define LN_buildingName "buildingName"
#define NID_buildingName 494
#define OBJ_buildingName OBJ_pilotAttributeType,48L
#define LN_dSAQuality "dSAQuality"
#define NID_dSAQuality 495
#define OBJ_dSAQuality OBJ_pilotAttributeType,49L
#define LN_singleLevelQuality "singleLevelQuality"
#define NID_singleLevelQuality 496
#define OBJ_singleLevelQuality OBJ_pilotAttributeType,50L
#define LN_subtreeMinimumQuality "subtreeMinimumQuality"
#define NID_subtreeMinimumQuality 497
#define OBJ_subtreeMinimumQuality OBJ_pilotAttributeType,51L
#define LN_subtreeMaximumQuality "subtreeMaximumQuality"
#define NID_subtreeMaximumQuality 498
#define OBJ_subtreeMaximumQuality OBJ_pilotAttributeType,52L
#define LN_personalSignature "personalSignature"
#define NID_personalSignature 499
#define OBJ_personalSignature OBJ_pilotAttributeType,53L
#define LN_dITRedirect "dITRedirect"
#define NID_dITRedirect 500
#define OBJ_dITRedirect OBJ_pilotAttributeType,54L
#define SN_audio "audio"
#define NID_audio 501
#define OBJ_audio OBJ_pilotAttributeType,55L
#define LN_documentPublisher "documentPublisher"
#define NID_documentPublisher 502
#define OBJ_documentPublisher OBJ_pilotAttributeType,56L
#define SN_id_set "id-set"
#define LN_id_set "Secure Electronic Transactions"
#define NID_id_set 512
#define OBJ_id_set OBJ_international_organizations,42L
#define SN_set_ctype "set-ctype"
#define LN_set_ctype "content types"
#define NID_set_ctype 513
#define OBJ_set_ctype OBJ_id_set,0L
#define SN_set_msgExt "set-msgExt"
#define LN_set_msgExt "message extensions"
#define NID_set_msgExt 514
#define OBJ_set_msgExt OBJ_id_set,1L
#define SN_set_attr "set-attr"
#define NID_set_attr 515
#define OBJ_set_attr OBJ_id_set,3L
#define SN_set_policy "set-policy"
#define NID_set_policy 516
#define OBJ_set_policy OBJ_id_set,5L
#define SN_set_certExt "set-certExt"
#define LN_set_certExt "certificate extensions"
#define NID_set_certExt 517
#define OBJ_set_certExt OBJ_id_set,7L
#define SN_set_brand "set-brand"
#define NID_set_brand 518
#define OBJ_set_brand OBJ_id_set,8L
#define SN_setct_PANData "setct-PANData"
#define NID_setct_PANData 519
#define OBJ_setct_PANData OBJ_set_ctype,0L
#define SN_setct_PANToken "setct-PANToken"
#define NID_setct_PANToken 520
#define OBJ_setct_PANToken OBJ_set_ctype,1L
#define SN_setct_PANOnly "setct-PANOnly"
#define NID_setct_PANOnly 521
#define OBJ_setct_PANOnly OBJ_set_ctype,2L
#define SN_setct_OIData "setct-OIData"
#define NID_setct_OIData 522
#define OBJ_setct_OIData OBJ_set_ctype,3L
#define SN_setct_PI "setct-PI"
#define NID_setct_PI 523
#define OBJ_setct_PI OBJ_set_ctype,4L
#define SN_setct_PIData "setct-PIData"
#define NID_setct_PIData 524
#define OBJ_setct_PIData OBJ_set_ctype,5L
#define SN_setct_PIDataUnsigned "setct-PIDataUnsigned"
#define NID_setct_PIDataUnsigned 525
#define OBJ_setct_PIDataUnsigned OBJ_set_ctype,6L
#define SN_setct_HODInput "setct-HODInput"
#define NID_setct_HODInput 526
#define OBJ_setct_HODInput OBJ_set_ctype,7L
#define SN_setct_AuthResBaggage "setct-AuthResBaggage"
#define NID_setct_AuthResBaggage 527
#define OBJ_setct_AuthResBaggage OBJ_set_ctype,8L
#define SN_setct_AuthRevReqBaggage "setct-AuthRevReqBaggage"
#define NID_setct_AuthRevReqBaggage 528
#define OBJ_setct_AuthRevReqBaggage OBJ_set_ctype,9L
#define SN_setct_AuthRevResBaggage "setct-AuthRevResBaggage"
#define NID_setct_AuthRevResBaggage 529
#define OBJ_setct_AuthRevResBaggage OBJ_set_ctype,10L
#define SN_setct_CapTokenSeq "setct-CapTokenSeq"
#define NID_setct_CapTokenSeq 530
#define OBJ_setct_CapTokenSeq OBJ_set_ctype,11L
#define SN_setct_PInitResData "setct-PInitResData"
#define NID_setct_PInitResData 531
#define OBJ_setct_PInitResData OBJ_set_ctype,12L
#define SN_setct_PI_TBS "setct-PI-TBS"
#define NID_setct_PI_TBS 532
#define OBJ_setct_PI_TBS OBJ_set_ctype,13L
#define SN_setct_PResData "setct-PResData"
#define NID_setct_PResData 533
#define OBJ_setct_PResData OBJ_set_ctype,14L
#define SN_setct_AuthReqTBS "setct-AuthReqTBS"
#define NID_setct_AuthReqTBS 534
#define OBJ_setct_AuthReqTBS OBJ_set_ctype,16L
#define SN_setct_AuthResTBS "setct-AuthResTBS"
#define NID_setct_AuthResTBS 535
#define OBJ_setct_AuthResTBS OBJ_set_ctype,17L
#define SN_setct_AuthResTBSX "setct-AuthResTBSX"
#define NID_setct_AuthResTBSX 536
#define OBJ_setct_AuthResTBSX OBJ_set_ctype,18L
#define SN_setct_AuthTokenTBS "setct-AuthTokenTBS"
#define NID_setct_AuthTokenTBS 537
#define OBJ_setct_AuthTokenTBS OBJ_set_ctype,19L
#define SN_setct_CapTokenData "setct-CapTokenData"
#define NID_setct_CapTokenData 538
#define OBJ_setct_CapTokenData OBJ_set_ctype,20L
#define SN_setct_CapTokenTBS "setct-CapTokenTBS"
#define NID_setct_CapTokenTBS 539
#define OBJ_setct_CapTokenTBS OBJ_set_ctype,21L
#define SN_setct_AcqCardCodeMsg "setct-AcqCardCodeMsg"
#define NID_setct_AcqCardCodeMsg 540
#define OBJ_setct_AcqCardCodeMsg OBJ_set_ctype,22L
#define SN_setct_AuthRevReqTBS "setct-AuthRevReqTBS"
#define NID_setct_AuthRevReqTBS 541
#define OBJ_setct_AuthRevReqTBS OBJ_set_ctype,23L
#define SN_setct_AuthRevResData "setct-AuthRevResData"
#define NID_setct_AuthRevResData 542
#define OBJ_setct_AuthRevResData OBJ_set_ctype,24L
#define SN_setct_AuthRevResTBS "setct-AuthRevResTBS"
#define NID_setct_AuthRevResTBS 543
#define OBJ_setct_AuthRevResTBS OBJ_set_ctype,25L
#define SN_setct_CapReqTBS "setct-CapReqTBS"
#define NID_setct_CapReqTBS 544
#define OBJ_setct_CapReqTBS OBJ_set_ctype,26L
#define SN_setct_CapReqTBSX "setct-CapReqTBSX"
#define NID_setct_CapReqTBSX 545
#define OBJ_setct_CapReqTBSX OBJ_set_ctype,27L
#define SN_setct_CapResData "setct-CapResData"
#define NID_setct_CapResData 546
#define OBJ_setct_CapResData OBJ_set_ctype,28L
#define SN_setct_CapRevReqTBS "setct-CapRevReqTBS"
#define NID_setct_CapRevReqTBS 547
#define OBJ_setct_CapRevReqTBS OBJ_set_ctype,29L
#define SN_setct_CapRevReqTBSX "setct-CapRevReqTBSX"
#define NID_setct_CapRevReqTBSX 548
#define OBJ_setct_CapRevReqTBSX OBJ_set_ctype,30L
#define SN_setct_CapRevResData "setct-CapRevResData"
#define NID_setct_CapRevResData 549
#define OBJ_setct_CapRevResData OBJ_set_ctype,31L
#define SN_setct_CredReqTBS "setct-CredReqTBS"
#define NID_setct_CredReqTBS 550
#define OBJ_setct_CredReqTBS OBJ_set_ctype,32L
#define SN_setct_CredReqTBSX "setct-CredReqTBSX"
#define NID_setct_CredReqTBSX 551
#define OBJ_setct_CredReqTBSX OBJ_set_ctype,33L
#define SN_setct_CredResData "setct-CredResData"
#define NID_setct_CredResData 552
#define OBJ_setct_CredResData OBJ_set_ctype,34L
#define SN_setct_CredRevReqTBS "setct-CredRevReqTBS"
#define NID_setct_CredRevReqTBS 553
#define OBJ_setct_CredRevReqTBS OBJ_set_ctype,35L
#define SN_setct_CredRevReqTBSX "setct-CredRevReqTBSX"
#define NID_setct_CredRevReqTBSX 554
#define OBJ_setct_CredRevReqTBSX OBJ_set_ctype,36L
#define SN_setct_CredRevResData "setct-CredRevResData"
#define NID_setct_CredRevResData 555
#define OBJ_setct_CredRevResData OBJ_set_ctype,37L
#define SN_setct_PCertReqData "setct-PCertReqData"
#define NID_setct_PCertReqData 556
#define OBJ_setct_PCertReqData OBJ_set_ctype,38L
#define SN_setct_PCertResTBS "setct-PCertResTBS"
#define NID_setct_PCertResTBS 557
#define OBJ_setct_PCertResTBS OBJ_set_ctype,39L
#define SN_setct_BatchAdminReqData "setct-BatchAdminReqData"
#define NID_setct_BatchAdminReqData 558
#define OBJ_setct_BatchAdminReqData OBJ_set_ctype,40L
#define SN_setct_BatchAdminResData "setct-BatchAdminResData"
#define NID_setct_BatchAdminResData 559
#define OBJ_setct_BatchAdminResData OBJ_set_ctype,41L
#define SN_setct_CardCInitResTBS "setct-CardCInitResTBS"
#define NID_setct_CardCInitResTBS 560
#define OBJ_setct_CardCInitResTBS OBJ_set_ctype,42L
#define SN_setct_MeAqCInitResTBS "setct-MeAqCInitResTBS"
#define NID_setct_MeAqCInitResTBS 561
#define OBJ_setct_MeAqCInitResTBS OBJ_set_ctype,43L
#define SN_setct_RegFormResTBS "setct-RegFormResTBS"
#define NID_setct_RegFormResTBS 562
#define OBJ_setct_RegFormResTBS OBJ_set_ctype,44L
#define SN_setct_CertReqData "setct-CertReqData"
#define NID_setct_CertReqData 563
#define OBJ_setct_CertReqData OBJ_set_ctype,45L
#define SN_setct_CertReqTBS "setct-CertReqTBS"
#define NID_setct_CertReqTBS 564
#define OBJ_setct_CertReqTBS OBJ_set_ctype,46L
#define SN_setct_CertResData "setct-CertResData"
#define NID_setct_CertResData 565
#define OBJ_setct_CertResData OBJ_set_ctype,47L
#define SN_setct_CertInqReqTBS "setct-CertInqReqTBS"
#define NID_setct_CertInqReqTBS 566
#define OBJ_setct_CertInqReqTBS OBJ_set_ctype,48L
#define SN_setct_ErrorTBS "setct-ErrorTBS"
#define NID_setct_ErrorTBS 567
#define OBJ_setct_ErrorTBS OBJ_set_ctype,49L
#define SN_setct_PIDualSignedTBE "setct-PIDualSignedTBE"
#define NID_setct_PIDualSignedTBE 568
#define OBJ_setct_PIDualSignedTBE OBJ_set_ctype,50L
#define SN_setct_PIUnsignedTBE "setct-PIUnsignedTBE"
#define NID_setct_PIUnsignedTBE 569
#define OBJ_setct_PIUnsignedTBE OBJ_set_ctype,51L
#define SN_setct_AuthReqTBE "setct-AuthReqTBE"
#define NID_setct_AuthReqTBE 570
#define OBJ_setct_AuthReqTBE OBJ_set_ctype,52L
#define SN_setct_AuthResTBE "setct-AuthResTBE"
#define NID_setct_AuthResTBE 571
#define OBJ_setct_AuthResTBE OBJ_set_ctype,53L
#define SN_setct_AuthResTBEX "setct-AuthResTBEX"
#define NID_setct_AuthResTBEX 572
#define OBJ_setct_AuthResTBEX OBJ_set_ctype,54L
#define SN_setct_AuthTokenTBE "setct-AuthTokenTBE"
#define NID_setct_AuthTokenTBE 573
#define OBJ_setct_AuthTokenTBE OBJ_set_ctype,55L
#define SN_setct_CapTokenTBE "setct-CapTokenTBE"
#define NID_setct_CapTokenTBE 574
#define OBJ_setct_CapTokenTBE OBJ_set_ctype,56L
#define SN_setct_CapTokenTBEX "setct-CapTokenTBEX"
#define NID_setct_CapTokenTBEX 575
#define OBJ_setct_CapTokenTBEX OBJ_set_ctype,57L
#define SN_setct_AcqCardCodeMsgTBE "setct-AcqCardCodeMsgTBE"
#define NID_setct_AcqCardCodeMsgTBE 576
#define OBJ_setct_AcqCardCodeMsgTBE OBJ_set_ctype,58L
#define SN_setct_AuthRevReqTBE "setct-AuthRevReqTBE"
#define NID_setct_AuthRevReqTBE 577
#define OBJ_setct_AuthRevReqTBE OBJ_set_ctype,59L
#define SN_setct_AuthRevResTBE "setct-AuthRevResTBE"
#define NID_setct_AuthRevResTBE 578
#define OBJ_setct_AuthRevResTBE OBJ_set_ctype,60L
#define SN_setct_AuthRevResTBEB "setct-AuthRevResTBEB"
#define NID_setct_AuthRevResTBEB 579
#define OBJ_setct_AuthRevResTBEB OBJ_set_ctype,61L
#define SN_setct_CapReqTBE "setct-CapReqTBE"
#define NID_setct_CapReqTBE 580
#define OBJ_setct_CapReqTBE OBJ_set_ctype,62L
#define SN_setct_CapReqTBEX "setct-CapReqTBEX"
#define NID_setct_CapReqTBEX 581
#define OBJ_setct_CapReqTBEX OBJ_set_ctype,63L
#define SN_setct_CapResTBE "setct-CapResTBE"
#define NID_setct_CapResTBE 582
#define OBJ_setct_CapResTBE OBJ_set_ctype,64L
#define SN_setct_CapRevReqTBE "setct-CapRevReqTBE"
#define NID_setct_CapRevReqTBE 583
#define OBJ_setct_CapRevReqTBE OBJ_set_ctype,65L
#define SN_setct_CapRevReqTBEX "setct-CapRevReqTBEX"
#define NID_setct_CapRevReqTBEX 584
#define OBJ_setct_CapRevReqTBEX OBJ_set_ctype,66L
#define SN_setct_CapRevResTBE "setct-CapRevResTBE"
#define NID_setct_CapRevResTBE 585
#define OBJ_setct_CapRevResTBE OBJ_set_ctype,67L
#define SN_setct_CredReqTBE "setct-CredReqTBE"
#define NID_setct_CredReqTBE 586
#define OBJ_setct_CredReqTBE OBJ_set_ctype,68L
#define SN_setct_CredReqTBEX "setct-CredReqTBEX"
#define NID_setct_CredReqTBEX 587
#define OBJ_setct_CredReqTBEX OBJ_set_ctype,69L
#define SN_setct_CredResTBE "setct-CredResTBE"
#define NID_setct_CredResTBE 588
#define OBJ_setct_CredResTBE OBJ_set_ctype,70L
#define SN_setct_CredRevReqTBE "setct-CredRevReqTBE"
#define NID_setct_CredRevReqTBE 589
#define OBJ_setct_CredRevReqTBE OBJ_set_ctype,71L
#define SN_setct_CredRevReqTBEX "setct-CredRevReqTBEX"
#define NID_setct_CredRevReqTBEX 590
#define OBJ_setct_CredRevReqTBEX OBJ_set_ctype,72L
#define SN_setct_CredRevResTBE "setct-CredRevResTBE"
#define NID_setct_CredRevResTBE 591
#define OBJ_setct_CredRevResTBE OBJ_set_ctype,73L
#define SN_setct_BatchAdminReqTBE "setct-BatchAdminReqTBE"
#define NID_setct_BatchAdminReqTBE 592
#define OBJ_setct_BatchAdminReqTBE OBJ_set_ctype,74L
#define SN_setct_BatchAdminResTBE "setct-BatchAdminResTBE"
#define NID_setct_BatchAdminResTBE 593
#define OBJ_setct_BatchAdminResTBE OBJ_set_ctype,75L
#define SN_setct_RegFormReqTBE "setct-RegFormReqTBE"
#define NID_setct_RegFormReqTBE 594
#define OBJ_setct_RegFormReqTBE OBJ_set_ctype,76L
#define SN_setct_CertReqTBE "setct-CertReqTBE"
#define NID_setct_CertReqTBE 595
#define OBJ_setct_CertReqTBE OBJ_set_ctype,77L
#define SN_setct_CertReqTBEX "setct-CertReqTBEX"
#define NID_setct_CertReqTBEX 596
#define OBJ_setct_CertReqTBEX OBJ_set_ctype,78L
#define SN_setct_CertResTBE "setct-CertResTBE"
#define NID_setct_CertResTBE 597
#define OBJ_setct_CertResTBE OBJ_set_ctype,79L
#define SN_setct_CRLNotificationTBS "setct-CRLNotificationTBS"
#define NID_setct_CRLNotificationTBS 598
#define OBJ_setct_CRLNotificationTBS OBJ_set_ctype,80L
#define SN_setct_CRLNotificationResTBS "setct-CRLNotificationResTBS"
#define NID_setct_CRLNotificationResTBS 599
#define OBJ_setct_CRLNotificationResTBS OBJ_set_ctype,81L
#define SN_setct_BCIDistributionTBS "setct-BCIDistributionTBS"
#define NID_setct_BCIDistributionTBS 600
#define OBJ_setct_BCIDistributionTBS OBJ_set_ctype,82L
#define SN_setext_genCrypt "setext-genCrypt"
#define LN_setext_genCrypt "generic cryptogram"
#define NID_setext_genCrypt 601
#define OBJ_setext_genCrypt OBJ_set_msgExt,1L
#define SN_setext_miAuth "setext-miAuth"
#define LN_setext_miAuth "merchant initiated auth"
#define NID_setext_miAuth 602
#define OBJ_setext_miAuth OBJ_set_msgExt,3L
#define SN_setext_pinSecure "setext-pinSecure"
#define NID_setext_pinSecure 603
#define OBJ_setext_pinSecure OBJ_set_msgExt,4L
#define SN_setext_pinAny "setext-pinAny"
#define NID_setext_pinAny 604
#define OBJ_setext_pinAny OBJ_set_msgExt,5L
#define SN_setext_track2 "setext-track2"
#define NID_setext_track2 605
#define OBJ_setext_track2 OBJ_set_msgExt,7L
#define SN_setext_cv "setext-cv"
#define LN_setext_cv "additional verification"
#define NID_setext_cv 606
#define OBJ_setext_cv OBJ_set_msgExt,8L
#define SN_set_policy_root "set-policy-root"
#define NID_set_policy_root 607
#define OBJ_set_policy_root OBJ_set_policy,0L
#define SN_setCext_hashedRoot "setCext-hashedRoot"
#define NID_setCext_hashedRoot 608
#define OBJ_setCext_hashedRoot OBJ_set_certExt,0L
#define SN_setCext_certType "setCext-certType"
#define NID_setCext_certType 609
#define OBJ_setCext_certType OBJ_set_certExt,1L
#define SN_setCext_merchData "setCext-merchData"
#define NID_setCext_merchData 610
#define OBJ_setCext_merchData OBJ_set_certExt,2L
#define SN_setCext_cCertRequired "setCext-cCertRequired"
#define NID_setCext_cCertRequired 611
#define OBJ_setCext_cCertRequired OBJ_set_certExt,3L
#define SN_setCext_tunneling "setCext-tunneling"
#define NID_setCext_tunneling 612
#define OBJ_setCext_tunneling OBJ_set_certExt,4L
#define SN_setCext_setExt "setCext-setExt"
#define NID_setCext_setExt 613
#define OBJ_setCext_setExt OBJ_set_certExt,5L
#define SN_setCext_setQualf "setCext-setQualf"
#define NID_setCext_setQualf 614
#define OBJ_setCext_setQualf OBJ_set_certExt,6L
#define SN_setCext_PGWYcapabilities "setCext-PGWYcapabilities"
#define NID_setCext_PGWYcapabilities 615
#define OBJ_setCext_PGWYcapabilities OBJ_set_certExt,7L
#define SN_setCext_TokenIdentifier "setCext-TokenIdentifier"
#define NID_setCext_TokenIdentifier 616
#define OBJ_setCext_TokenIdentifier OBJ_set_certExt,8L
#define SN_setCext_Track2Data "setCext-Track2Data"
#define NID_setCext_Track2Data 617
#define OBJ_setCext_Track2Data OBJ_set_certExt,9L
#define SN_setCext_TokenType "setCext-TokenType"
#define NID_setCext_TokenType 618
#define OBJ_setCext_TokenType OBJ_set_certExt,10L
#define SN_setCext_IssuerCapabilities "setCext-IssuerCapabilities"
#define NID_setCext_IssuerCapabilities 619
#define OBJ_setCext_IssuerCapabilities OBJ_set_certExt,11L
#define SN_setAttr_Cert "setAttr-Cert"
#define NID_setAttr_Cert 620
#define OBJ_setAttr_Cert OBJ_set_attr,0L
#define SN_setAttr_PGWYcap "setAttr-PGWYcap"
#define LN_setAttr_PGWYcap "payment gateway capabilities"
#define NID_setAttr_PGWYcap 621
#define OBJ_setAttr_PGWYcap OBJ_set_attr,1L
#define SN_setAttr_TokenType "setAttr-TokenType"
#define NID_setAttr_TokenType 622
#define OBJ_setAttr_TokenType OBJ_set_attr,2L
#define SN_setAttr_IssCap "setAttr-IssCap"
#define LN_setAttr_IssCap "issuer capabilities"
#define NID_setAttr_IssCap 623
#define OBJ_setAttr_IssCap OBJ_set_attr,3L
#define SN_set_rootKeyThumb "set-rootKeyThumb"
#define NID_set_rootKeyThumb 624
#define OBJ_set_rootKeyThumb OBJ_setAttr_Cert,0L
#define SN_set_addPolicy "set-addPolicy"
#define NID_set_addPolicy 625
#define OBJ_set_addPolicy OBJ_setAttr_Cert,1L
#define SN_setAttr_Token_EMV "setAttr-Token-EMV"
#define NID_setAttr_Token_EMV 626
#define OBJ_setAttr_Token_EMV OBJ_setAttr_TokenType,1L
#define SN_setAttr_Token_B0Prime "setAttr-Token-B0Prime"
#define NID_setAttr_Token_B0Prime 627
#define OBJ_setAttr_Token_B0Prime OBJ_setAttr_TokenType,2L
#define SN_setAttr_IssCap_CVM "setAttr-IssCap-CVM"
#define NID_setAttr_IssCap_CVM 628
#define OBJ_setAttr_IssCap_CVM OBJ_setAttr_IssCap,3L
#define SN_setAttr_IssCap_T2 "setAttr-IssCap-T2"
#define NID_setAttr_IssCap_T2 629
#define OBJ_setAttr_IssCap_T2 OBJ_setAttr_IssCap,4L
#define SN_setAttr_IssCap_Sig "setAttr-IssCap-Sig"
#define NID_setAttr_IssCap_Sig 630
#define OBJ_setAttr_IssCap_Sig OBJ_setAttr_IssCap,5L
#define SN_setAttr_GenCryptgrm "setAttr-GenCryptgrm"
#define LN_setAttr_GenCryptgrm "generate cryptogram"
#define NID_setAttr_GenCryptgrm 631
#define OBJ_setAttr_GenCryptgrm OBJ_setAttr_IssCap_CVM,1L
#define SN_setAttr_T2Enc "setAttr-T2Enc"
#define LN_setAttr_T2Enc "encrypted track 2"
#define NID_setAttr_T2Enc 632
#define OBJ_setAttr_T2Enc OBJ_setAttr_IssCap_T2,1L
#define SN_setAttr_T2cleartxt "setAttr-T2cleartxt"
#define LN_setAttr_T2cleartxt "cleartext track 2"
#define NID_setAttr_T2cleartxt 633
#define OBJ_setAttr_T2cleartxt OBJ_setAttr_IssCap_T2,2L
#define SN_setAttr_TokICCsig "setAttr-TokICCsig"
#define LN_setAttr_TokICCsig "ICC or token signature"
#define NID_setAttr_TokICCsig 634
#define OBJ_setAttr_TokICCsig OBJ_setAttr_IssCap_Sig,1L
#define SN_setAttr_SecDevSig "setAttr-SecDevSig"
#define LN_setAttr_SecDevSig "secure device signature"
#define NID_setAttr_SecDevSig 635
#define OBJ_setAttr_SecDevSig OBJ_setAttr_IssCap_Sig,2L
#define SN_set_brand_IATA_ATA "set-brand-IATA-ATA"
#define NID_set_brand_IATA_ATA 636
#define OBJ_set_brand_IATA_ATA OBJ_set_brand,1L
#define SN_set_brand_Diners "set-brand-Diners"
#define NID_set_brand_Diners 637
#define OBJ_set_brand_Diners OBJ_set_brand,30L
#define SN_set_brand_AmericanExpress "set-brand-AmericanExpress"
#define NID_set_brand_AmericanExpress 638
#define OBJ_set_brand_AmericanExpress OBJ_set_brand,34L
#define SN_set_brand_JCB "set-brand-JCB"
#define NID_set_brand_JCB 639
#define OBJ_set_brand_JCB OBJ_set_brand,35L
#define SN_set_brand_Visa "set-brand-Visa"
#define NID_set_brand_Visa 640
#define OBJ_set_brand_Visa OBJ_set_brand,4L
#define SN_set_brand_MasterCard "set-brand-MasterCard"
#define NID_set_brand_MasterCard 641
#define OBJ_set_brand_MasterCard OBJ_set_brand,5L
#define SN_set_brand_Novus "set-brand-Novus"
#define NID_set_brand_Novus 642
#define OBJ_set_brand_Novus OBJ_set_brand,6011L
#define SN_des_cdmf "DES-CDMF"
#define LN_des_cdmf "des-cdmf"
#define NID_des_cdmf 643
#define OBJ_des_cdmf OBJ_rsadsi,3L,10L
#define SN_rsaOAEPEncryptionSET "rsaOAEPEncryptionSET"
#define NID_rsaOAEPEncryptionSET 644
#define OBJ_rsaOAEPEncryptionSET OBJ_rsadsi,1L,1L,6L
#define SN_ipsec3 "Oakley-EC2N-3"
#define LN_ipsec3 "ipsec3"
#define NID_ipsec3 749
#define SN_ipsec4 "Oakley-EC2N-4"
#define LN_ipsec4 "ipsec4"
#define NID_ipsec4 750
#define SN_whirlpool "whirlpool"
#define NID_whirlpool 804
#define OBJ_whirlpool OBJ_iso,0L,10118L,3L,0L,55L
#define SN_cryptopro "cryptopro"
#define NID_cryptopro 805
#define OBJ_cryptopro OBJ_member_body,643L,2L,2L
#define SN_cryptocom "cryptocom"
#define NID_cryptocom 806
#define OBJ_cryptocom OBJ_member_body,643L,2L,9L
#define SN_id_tc26 "id-tc26"
#define NID_id_tc26 974
#define OBJ_id_tc26 OBJ_member_body,643L,7L,1L
#define SN_id_GostR3411_94_with_GostR3410_2001 "id-GostR3411-94-with-GostR3410-2001"
#define LN_id_GostR3411_94_with_GostR3410_2001 "GOST R 34.11-94 with GOST R 34.10-2001"
#define NID_id_GostR3411_94_with_GostR3410_2001 807
#define OBJ_id_GostR3411_94_with_GostR3410_2001 OBJ_cryptopro,3L
#define SN_id_GostR3411_94_with_GostR3410_94 "id-GostR3411-94-with-GostR3410-94"
#define LN_id_GostR3411_94_with_GostR3410_94 "GOST R 34.11-94 with GOST R 34.10-94"
#define NID_id_GostR3411_94_with_GostR3410_94 808
#define OBJ_id_GostR3411_94_with_GostR3410_94 OBJ_cryptopro,4L
#define SN_id_GostR3411_94 "md_gost94"
#define LN_id_GostR3411_94 "GOST R 34.11-94"
#define NID_id_GostR3411_94 809
#define OBJ_id_GostR3411_94 OBJ_cryptopro,9L
#define SN_id_HMACGostR3411_94 "id-HMACGostR3411-94"
#define LN_id_HMACGostR3411_94 "HMAC GOST 34.11-94"
#define NID_id_HMACGostR3411_94 810
#define OBJ_id_HMACGostR3411_94 OBJ_cryptopro,10L
#define SN_id_GostR3410_2001 "gost2001"
#define LN_id_GostR3410_2001 "GOST R 34.10-2001"
#define NID_id_GostR3410_2001 811
#define OBJ_id_GostR3410_2001 OBJ_cryptopro,19L
#define SN_id_GostR3410_94 "gost94"
#define LN_id_GostR3410_94 "GOST R 34.10-94"
#define NID_id_GostR3410_94 812
#define OBJ_id_GostR3410_94 OBJ_cryptopro,20L
#define SN_id_Gost28147_89 "gost89"
#define LN_id_Gost28147_89 "GOST 28147-89"
#define NID_id_Gost28147_89 813
#define OBJ_id_Gost28147_89 OBJ_cryptopro,21L
#define SN_gost89_cnt "gost89-cnt"
#define NID_gost89_cnt 814
#define SN_gost89_cnt_12 "gost89-cnt-12"
#define NID_gost89_cnt_12 975
#define SN_gost89_cbc "gost89-cbc"
#define NID_gost89_cbc 1009
#define SN_gost89_ecb "gost89-ecb"
#define NID_gost89_ecb 1010
#define SN_gost89_ctr "gost89-ctr"
#define NID_gost89_ctr 1011
#define SN_id_Gost28147_89_MAC "gost-mac"
#define LN_id_Gost28147_89_MAC "GOST 28147-89 MAC"
#define NID_id_Gost28147_89_MAC 815
#define OBJ_id_Gost28147_89_MAC OBJ_cryptopro,22L
#define SN_gost_mac_12 "gost-mac-12"
#define NID_gost_mac_12 976
#define SN_id_GostR3411_94_prf "prf-gostr3411-94"
#define LN_id_GostR3411_94_prf "GOST R 34.11-94 PRF"
#define NID_id_GostR3411_94_prf 816
#define OBJ_id_GostR3411_94_prf OBJ_cryptopro,23L
#define SN_id_GostR3410_2001DH "id-GostR3410-2001DH"
#define LN_id_GostR3410_2001DH "GOST R 34.10-2001 DH"
#define NID_id_GostR3410_2001DH 817
#define OBJ_id_GostR3410_2001DH OBJ_cryptopro,98L
#define SN_id_GostR3410_94DH "id-GostR3410-94DH"
#define LN_id_GostR3410_94DH "GOST R 34.10-94 DH"
#define NID_id_GostR3410_94DH 818
#define OBJ_id_GostR3410_94DH OBJ_cryptopro,99L
#define SN_id_Gost28147_89_CryptoPro_KeyMeshing "id-Gost28147-89-CryptoPro-KeyMeshing"
#define NID_id_Gost28147_89_CryptoPro_KeyMeshing 819
#define OBJ_id_Gost28147_89_CryptoPro_KeyMeshing OBJ_cryptopro,14L,1L
#define SN_id_Gost28147_89_None_KeyMeshing "id-Gost28147-89-None-KeyMeshing"
#define NID_id_Gost28147_89_None_KeyMeshing 820
#define OBJ_id_Gost28147_89_None_KeyMeshing OBJ_cryptopro,14L,0L
#define SN_id_GostR3411_94_TestParamSet "id-GostR3411-94-TestParamSet"
#define NID_id_GostR3411_94_TestParamSet 821
#define OBJ_id_GostR3411_94_TestParamSet OBJ_cryptopro,30L,0L
#define SN_id_GostR3411_94_CryptoProParamSet "id-GostR3411-94-CryptoProParamSet"
#define NID_id_GostR3411_94_CryptoProParamSet 822
#define OBJ_id_GostR3411_94_CryptoProParamSet OBJ_cryptopro,30L,1L
#define SN_id_Gost28147_89_TestParamSet "id-Gost28147-89-TestParamSet"
#define NID_id_Gost28147_89_TestParamSet 823
#define OBJ_id_Gost28147_89_TestParamSet OBJ_cryptopro,31L,0L
#define SN_id_Gost28147_89_CryptoPro_A_ParamSet "id-Gost28147-89-CryptoPro-A-ParamSet"
#define NID_id_Gost28147_89_CryptoPro_A_ParamSet 824
#define OBJ_id_Gost28147_89_CryptoPro_A_ParamSet OBJ_cryptopro,31L,1L
#define SN_id_Gost28147_89_CryptoPro_B_ParamSet "id-Gost28147-89-CryptoPro-B-ParamSet"
#define NID_id_Gost28147_89_CryptoPro_B_ParamSet 825
#define OBJ_id_Gost28147_89_CryptoPro_B_ParamSet OBJ_cryptopro,31L,2L
#define SN_id_Gost28147_89_CryptoPro_C_ParamSet "id-Gost28147-89-CryptoPro-C-ParamSet"
#define NID_id_Gost28147_89_CryptoPro_C_ParamSet 826
#define OBJ_id_Gost28147_89_CryptoPro_C_ParamSet OBJ_cryptopro,31L,3L
#define SN_id_Gost28147_89_CryptoPro_D_ParamSet "id-Gost28147-89-CryptoPro-D-ParamSet"
#define NID_id_Gost28147_89_CryptoPro_D_ParamSet 827
#define OBJ_id_Gost28147_89_CryptoPro_D_ParamSet OBJ_cryptopro,31L,4L
#define SN_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-1-ParamSet"
#define NID_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet 828
#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_1_ParamSet OBJ_cryptopro,31L,5L
#define SN_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet "id-Gost28147-89-CryptoPro-Oscar-1-0-ParamSet"
#define NID_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet 829
#define OBJ_id_Gost28147_89_CryptoPro_Oscar_1_0_ParamSet OBJ_cryptopro,31L,6L
#define SN_id_Gost28147_89_CryptoPro_RIC_1_ParamSet "id-Gost28147-89-CryptoPro-RIC-1-ParamSet"
#define NID_id_Gost28147_89_CryptoPro_RIC_1_ParamSet 830
#define OBJ_id_Gost28147_89_CryptoPro_RIC_1_ParamSet OBJ_cryptopro,31L,7L
#define SN_id_GostR3410_94_TestParamSet "id-GostR3410-94-TestParamSet"
#define NID_id_GostR3410_94_TestParamSet 831
#define OBJ_id_GostR3410_94_TestParamSet OBJ_cryptopro,32L,0L
#define SN_id_GostR3410_94_CryptoPro_A_ParamSet "id-GostR3410-94-CryptoPro-A-ParamSet"
#define NID_id_GostR3410_94_CryptoPro_A_ParamSet 832
#define OBJ_id_GostR3410_94_CryptoPro_A_ParamSet OBJ_cryptopro,32L,2L
#define SN_id_GostR3410_94_CryptoPro_B_ParamSet "id-GostR3410-94-CryptoPro-B-ParamSet"
#define NID_id_GostR3410_94_CryptoPro_B_ParamSet 833
#define OBJ_id_GostR3410_94_CryptoPro_B_ParamSet OBJ_cryptopro,32L,3L
#define SN_id_GostR3410_94_CryptoPro_C_ParamSet "id-GostR3410-94-CryptoPro-C-ParamSet"
#define NID_id_GostR3410_94_CryptoPro_C_ParamSet 834
#define OBJ_id_GostR3410_94_CryptoPro_C_ParamSet OBJ_cryptopro,32L,4L
#define SN_id_GostR3410_94_CryptoPro_D_ParamSet "id-GostR3410-94-CryptoPro-D-ParamSet"
#define NID_id_GostR3410_94_CryptoPro_D_ParamSet 835
#define OBJ_id_GostR3410_94_CryptoPro_D_ParamSet OBJ_cryptopro,32L,5L
#define SN_id_GostR3410_94_CryptoPro_XchA_ParamSet "id-GostR3410-94-CryptoPro-XchA-ParamSet"
#define NID_id_GostR3410_94_CryptoPro_XchA_ParamSet 836
#define OBJ_id_GostR3410_94_CryptoPro_XchA_ParamSet OBJ_cryptopro,33L,1L
#define SN_id_GostR3410_94_CryptoPro_XchB_ParamSet "id-GostR3410-94-CryptoPro-XchB-ParamSet"
#define NID_id_GostR3410_94_CryptoPro_XchB_ParamSet 837
#define OBJ_id_GostR3410_94_CryptoPro_XchB_ParamSet OBJ_cryptopro,33L,2L
#define SN_id_GostR3410_94_CryptoPro_XchC_ParamSet "id-GostR3410-94-CryptoPro-XchC-ParamSet"
#define NID_id_GostR3410_94_CryptoPro_XchC_ParamSet 838
#define OBJ_id_GostR3410_94_CryptoPro_XchC_ParamSet OBJ_cryptopro,33L,3L
#define SN_id_GostR3410_2001_TestParamSet "id-GostR3410-2001-TestParamSet"
#define NID_id_GostR3410_2001_TestParamSet 839
#define OBJ_id_GostR3410_2001_TestParamSet OBJ_cryptopro,35L,0L
#define SN_id_GostR3410_2001_CryptoPro_A_ParamSet "id-GostR3410-2001-CryptoPro-A-ParamSet"
#define NID_id_GostR3410_2001_CryptoPro_A_ParamSet 840
#define OBJ_id_GostR3410_2001_CryptoPro_A_ParamSet OBJ_cryptopro,35L,1L
#define SN_id_GostR3410_2001_CryptoPro_B_ParamSet "id-GostR3410-2001-CryptoPro-B-ParamSet"
#define NID_id_GostR3410_2001_CryptoPro_B_ParamSet 841
#define OBJ_id_GostR3410_2001_CryptoPro_B_ParamSet OBJ_cryptopro,35L,2L
#define SN_id_GostR3410_2001_CryptoPro_C_ParamSet "id-GostR3410-2001-CryptoPro-C-ParamSet"
#define NID_id_GostR3410_2001_CryptoPro_C_ParamSet 842
#define OBJ_id_GostR3410_2001_CryptoPro_C_ParamSet OBJ_cryptopro,35L,3L
#define SN_id_GostR3410_2001_CryptoPro_XchA_ParamSet "id-GostR3410-2001-CryptoPro-XchA-ParamSet"
#define NID_id_GostR3410_2001_CryptoPro_XchA_ParamSet 843
#define OBJ_id_GostR3410_2001_CryptoPro_XchA_ParamSet OBJ_cryptopro,36L,0L
#define SN_id_GostR3410_2001_CryptoPro_XchB_ParamSet "id-GostR3410-2001-CryptoPro-XchB-ParamSet"
#define NID_id_GostR3410_2001_CryptoPro_XchB_ParamSet 844
#define OBJ_id_GostR3410_2001_CryptoPro_XchB_ParamSet OBJ_cryptopro,36L,1L
#define SN_id_GostR3410_94_a "id-GostR3410-94-a"
#define NID_id_GostR3410_94_a 845
#define OBJ_id_GostR3410_94_a OBJ_id_GostR3410_94,1L
#define SN_id_GostR3410_94_aBis "id-GostR3410-94-aBis"
#define NID_id_GostR3410_94_aBis 846
#define OBJ_id_GostR3410_94_aBis OBJ_id_GostR3410_94,2L
#define SN_id_GostR3410_94_b "id-GostR3410-94-b"
#define NID_id_GostR3410_94_b 847
#define OBJ_id_GostR3410_94_b OBJ_id_GostR3410_94,3L
#define SN_id_GostR3410_94_bBis "id-GostR3410-94-bBis"
#define NID_id_GostR3410_94_bBis 848
#define OBJ_id_GostR3410_94_bBis OBJ_id_GostR3410_94,4L
#define SN_id_Gost28147_89_cc "id-Gost28147-89-cc"
#define LN_id_Gost28147_89_cc "GOST 28147-89 Cryptocom ParamSet"
#define NID_id_Gost28147_89_cc 849
#define OBJ_id_Gost28147_89_cc OBJ_cryptocom,1L,6L,1L
#define SN_id_GostR3410_94_cc "gost94cc"
#define LN_id_GostR3410_94_cc "GOST 34.10-94 Cryptocom"
#define NID_id_GostR3410_94_cc 850
#define OBJ_id_GostR3410_94_cc OBJ_cryptocom,1L,5L,3L
#define SN_id_GostR3410_2001_cc "gost2001cc"
#define LN_id_GostR3410_2001_cc "GOST 34.10-2001 Cryptocom"
#define NID_id_GostR3410_2001_cc 851
#define OBJ_id_GostR3410_2001_cc OBJ_cryptocom,1L,5L,4L
#define SN_id_GostR3411_94_with_GostR3410_94_cc "id-GostR3411-94-with-GostR3410-94-cc"
#define LN_id_GostR3411_94_with_GostR3410_94_cc "GOST R 34.11-94 with GOST R 34.10-94 Cryptocom"
#define NID_id_GostR3411_94_with_GostR3410_94_cc 852
#define OBJ_id_GostR3411_94_with_GostR3410_94_cc OBJ_cryptocom,1L,3L,3L
#define SN_id_GostR3411_94_with_GostR3410_2001_cc "id-GostR3411-94-with-GostR3410-2001-cc"
#define LN_id_GostR3411_94_with_GostR3410_2001_cc "GOST R 34.11-94 with GOST R 34.10-2001 Cryptocom"
#define NID_id_GostR3411_94_with_GostR3410_2001_cc 853
#define OBJ_id_GostR3411_94_with_GostR3410_2001_cc OBJ_cryptocom,1L,3L,4L
#define SN_id_GostR3410_2001_ParamSet_cc "id-GostR3410-2001-ParamSet-cc"
#define LN_id_GostR3410_2001_ParamSet_cc "GOST R 3410-2001 Parameter Set Cryptocom"
#define NID_id_GostR3410_2001_ParamSet_cc 854
#define OBJ_id_GostR3410_2001_ParamSet_cc OBJ_cryptocom,1L,8L,1L
#define SN_id_tc26_algorithms "id-tc26-algorithms"
#define NID_id_tc26_algorithms 977
#define OBJ_id_tc26_algorithms OBJ_id_tc26,1L
#define SN_id_tc26_sign "id-tc26-sign"
#define NID_id_tc26_sign 978
#define OBJ_id_tc26_sign OBJ_id_tc26_algorithms,1L
#define SN_id_GostR3410_2012_256 "gost2012_256"
#define LN_id_GostR3410_2012_256 "GOST R 34.10-2012 with 256 bit modulus"
#define NID_id_GostR3410_2012_256 979
#define OBJ_id_GostR3410_2012_256 OBJ_id_tc26_sign,1L
#define SN_id_GostR3410_2012_512 "gost2012_512"
#define LN_id_GostR3410_2012_512 "GOST R 34.10-2012 with 512 bit modulus"
#define NID_id_GostR3410_2012_512 980
#define OBJ_id_GostR3410_2012_512 OBJ_id_tc26_sign,2L
#define SN_id_tc26_digest "id-tc26-digest"
#define NID_id_tc26_digest 981
#define OBJ_id_tc26_digest OBJ_id_tc26_algorithms,2L
#define SN_id_GostR3411_2012_256 "md_gost12_256"
#define LN_id_GostR3411_2012_256 "GOST R 34.11-2012 with 256 bit hash"
#define NID_id_GostR3411_2012_256 982
#define OBJ_id_GostR3411_2012_256 OBJ_id_tc26_digest,2L
#define SN_id_GostR3411_2012_512 "md_gost12_512"
#define LN_id_GostR3411_2012_512 "GOST R 34.11-2012 with 512 bit hash"
#define NID_id_GostR3411_2012_512 983
#define OBJ_id_GostR3411_2012_512 OBJ_id_tc26_digest,3L
#define SN_id_tc26_signwithdigest "id-tc26-signwithdigest"
#define NID_id_tc26_signwithdigest 984
#define OBJ_id_tc26_signwithdigest OBJ_id_tc26_algorithms,3L
#define SN_id_tc26_signwithdigest_gost3410_2012_256 "id-tc26-signwithdigest-gost3410-2012-256"
#define LN_id_tc26_signwithdigest_gost3410_2012_256 "GOST R 34.10-2012 with GOST R 34.11-2012 (256 bit)"
#define NID_id_tc26_signwithdigest_gost3410_2012_256 985
#define OBJ_id_tc26_signwithdigest_gost3410_2012_256 OBJ_id_tc26_signwithdigest,2L
#define SN_id_tc26_signwithdigest_gost3410_2012_512 "id-tc26-signwithdigest-gost3410-2012-512"
#define LN_id_tc26_signwithdigest_gost3410_2012_512 "GOST R 34.10-2012 with GOST R 34.11-2012 (512 bit)"
#define NID_id_tc26_signwithdigest_gost3410_2012_512 986
#define OBJ_id_tc26_signwithdigest_gost3410_2012_512 OBJ_id_tc26_signwithdigest,3L
#define SN_id_tc26_mac "id-tc26-mac"
#define NID_id_tc26_mac 987
#define OBJ_id_tc26_mac OBJ_id_tc26_algorithms,4L
#define SN_id_tc26_hmac_gost_3411_2012_256 "id-tc26-hmac-gost-3411-2012-256"
#define LN_id_tc26_hmac_gost_3411_2012_256 "HMAC GOST 34.11-2012 256 bit"
#define NID_id_tc26_hmac_gost_3411_2012_256 988
#define OBJ_id_tc26_hmac_gost_3411_2012_256 OBJ_id_tc26_mac,1L
#define SN_id_tc26_hmac_gost_3411_2012_512 "id-tc26-hmac-gost-3411-2012-512"
#define LN_id_tc26_hmac_gost_3411_2012_512 "HMAC GOST 34.11-2012 512 bit"
#define NID_id_tc26_hmac_gost_3411_2012_512 989
#define OBJ_id_tc26_hmac_gost_3411_2012_512 OBJ_id_tc26_mac,2L
#define SN_id_tc26_cipher "id-tc26-cipher"
#define NID_id_tc26_cipher 990
#define OBJ_id_tc26_cipher OBJ_id_tc26_algorithms,5L
#define SN_id_tc26_cipher_gostr3412_2015_magma "id-tc26-cipher-gostr3412-2015-magma"
#define NID_id_tc26_cipher_gostr3412_2015_magma 1173
#define OBJ_id_tc26_cipher_gostr3412_2015_magma OBJ_id_tc26_cipher,1L
#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm "id-tc26-cipher-gostr3412-2015-magma-ctracpkm"
#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm 1174
#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_magma,1L
#define SN_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-magma-ctracpkm-omac"
#define NID_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac 1175
#define OBJ_id_tc26_cipher_gostr3412_2015_magma_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_magma,2L
#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik "id-tc26-cipher-gostr3412-2015-kuznyechik"
#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik 1176
#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik OBJ_id_tc26_cipher,2L
#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm"
#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm 1177
#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,1L
#define SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac "id-tc26-cipher-gostr3412-2015-kuznyechik-ctracpkm-omac"
#define NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac 1178
#define OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac OBJ_id_tc26_cipher_gostr3412_2015_kuznyechik,2L
#define SN_id_tc26_agreement "id-tc26-agreement"
#define NID_id_tc26_agreement 991
#define OBJ_id_tc26_agreement OBJ_id_tc26_algorithms,6L
#define SN_id_tc26_agreement_gost_3410_2012_256 "id-tc26-agreement-gost-3410-2012-256"
#define NID_id_tc26_agreement_gost_3410_2012_256 992
#define OBJ_id_tc26_agreement_gost_3410_2012_256 OBJ_id_tc26_agreement,1L
#define SN_id_tc26_agreement_gost_3410_2012_512 "id-tc26-agreement-gost-3410-2012-512"
#define NID_id_tc26_agreement_gost_3410_2012_512 993
#define OBJ_id_tc26_agreement_gost_3410_2012_512 OBJ_id_tc26_agreement,2L
#define SN_id_tc26_wrap "id-tc26-wrap"
#define NID_id_tc26_wrap 1179
#define OBJ_id_tc26_wrap OBJ_id_tc26_algorithms,7L
#define SN_id_tc26_wrap_gostr3412_2015_magma "id-tc26-wrap-gostr3412-2015-magma"
#define NID_id_tc26_wrap_gostr3412_2015_magma 1180
#define OBJ_id_tc26_wrap_gostr3412_2015_magma OBJ_id_tc26_wrap,1L
#define SN_id_tc26_wrap_gostr3412_2015_magma_kexp15 "id-tc26-wrap-gostr3412-2015-magma-kexp15"
#define NID_id_tc26_wrap_gostr3412_2015_magma_kexp15 1181
#define OBJ_id_tc26_wrap_gostr3412_2015_magma_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L
#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik "id-tc26-wrap-gostr3412-2015-kuznyechik"
#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik 1182
#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik OBJ_id_tc26_wrap,2L
#define SN_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 "id-tc26-wrap-gostr3412-2015-kuznyechik-kexp15"
#define NID_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 1183
-#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_magma,1L
+#define OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik_kexp15 OBJ_id_tc26_wrap_gostr3412_2015_kuznyechik,1L
#define SN_id_tc26_constants "id-tc26-constants"
#define NID_id_tc26_constants 994
#define OBJ_id_tc26_constants OBJ_id_tc26,2L
#define SN_id_tc26_sign_constants "id-tc26-sign-constants"
#define NID_id_tc26_sign_constants 995
#define OBJ_id_tc26_sign_constants OBJ_id_tc26_constants,1L
#define SN_id_tc26_gost_3410_2012_256_constants "id-tc26-gost-3410-2012-256-constants"
#define NID_id_tc26_gost_3410_2012_256_constants 1147
#define OBJ_id_tc26_gost_3410_2012_256_constants OBJ_id_tc26_sign_constants,1L
#define SN_id_tc26_gost_3410_2012_256_paramSetA "id-tc26-gost-3410-2012-256-paramSetA"
#define LN_id_tc26_gost_3410_2012_256_paramSetA "GOST R 34.10-2012 (256 bit) ParamSet A"
#define NID_id_tc26_gost_3410_2012_256_paramSetA 1148
#define OBJ_id_tc26_gost_3410_2012_256_paramSetA OBJ_id_tc26_gost_3410_2012_256_constants,1L
#define SN_id_tc26_gost_3410_2012_256_paramSetB "id-tc26-gost-3410-2012-256-paramSetB"
#define LN_id_tc26_gost_3410_2012_256_paramSetB "GOST R 34.10-2012 (256 bit) ParamSet B"
#define NID_id_tc26_gost_3410_2012_256_paramSetB 1184
#define OBJ_id_tc26_gost_3410_2012_256_paramSetB OBJ_id_tc26_gost_3410_2012_256_constants,2L
#define SN_id_tc26_gost_3410_2012_256_paramSetC "id-tc26-gost-3410-2012-256-paramSetC"
#define LN_id_tc26_gost_3410_2012_256_paramSetC "GOST R 34.10-2012 (256 bit) ParamSet C"
#define NID_id_tc26_gost_3410_2012_256_paramSetC 1185
#define OBJ_id_tc26_gost_3410_2012_256_paramSetC OBJ_id_tc26_gost_3410_2012_256_constants,3L
#define SN_id_tc26_gost_3410_2012_256_paramSetD "id-tc26-gost-3410-2012-256-paramSetD"
#define LN_id_tc26_gost_3410_2012_256_paramSetD "GOST R 34.10-2012 (256 bit) ParamSet D"
#define NID_id_tc26_gost_3410_2012_256_paramSetD 1186
#define OBJ_id_tc26_gost_3410_2012_256_paramSetD OBJ_id_tc26_gost_3410_2012_256_constants,4L
#define SN_id_tc26_gost_3410_2012_512_constants "id-tc26-gost-3410-2012-512-constants"
#define NID_id_tc26_gost_3410_2012_512_constants 996
#define OBJ_id_tc26_gost_3410_2012_512_constants OBJ_id_tc26_sign_constants,2L
#define SN_id_tc26_gost_3410_2012_512_paramSetTest "id-tc26-gost-3410-2012-512-paramSetTest"
#define LN_id_tc26_gost_3410_2012_512_paramSetTest "GOST R 34.10-2012 (512 bit) testing parameter set"
#define NID_id_tc26_gost_3410_2012_512_paramSetTest 997
#define OBJ_id_tc26_gost_3410_2012_512_paramSetTest OBJ_id_tc26_gost_3410_2012_512_constants,0L
#define SN_id_tc26_gost_3410_2012_512_paramSetA "id-tc26-gost-3410-2012-512-paramSetA"
#define LN_id_tc26_gost_3410_2012_512_paramSetA "GOST R 34.10-2012 (512 bit) ParamSet A"
#define NID_id_tc26_gost_3410_2012_512_paramSetA 998
#define OBJ_id_tc26_gost_3410_2012_512_paramSetA OBJ_id_tc26_gost_3410_2012_512_constants,1L
#define SN_id_tc26_gost_3410_2012_512_paramSetB "id-tc26-gost-3410-2012-512-paramSetB"
#define LN_id_tc26_gost_3410_2012_512_paramSetB "GOST R 34.10-2012 (512 bit) ParamSet B"
#define NID_id_tc26_gost_3410_2012_512_paramSetB 999
#define OBJ_id_tc26_gost_3410_2012_512_paramSetB OBJ_id_tc26_gost_3410_2012_512_constants,2L
#define SN_id_tc26_gost_3410_2012_512_paramSetC "id-tc26-gost-3410-2012-512-paramSetC"
#define LN_id_tc26_gost_3410_2012_512_paramSetC "GOST R 34.10-2012 (512 bit) ParamSet C"
#define NID_id_tc26_gost_3410_2012_512_paramSetC 1149
#define OBJ_id_tc26_gost_3410_2012_512_paramSetC OBJ_id_tc26_gost_3410_2012_512_constants,3L
#define SN_id_tc26_digest_constants "id-tc26-digest-constants"
#define NID_id_tc26_digest_constants 1000
#define OBJ_id_tc26_digest_constants OBJ_id_tc26_constants,2L
#define SN_id_tc26_cipher_constants "id-tc26-cipher-constants"
#define NID_id_tc26_cipher_constants 1001
#define OBJ_id_tc26_cipher_constants OBJ_id_tc26_constants,5L
#define SN_id_tc26_gost_28147_constants "id-tc26-gost-28147-constants"
#define NID_id_tc26_gost_28147_constants 1002
#define OBJ_id_tc26_gost_28147_constants OBJ_id_tc26_cipher_constants,1L
#define SN_id_tc26_gost_28147_param_Z "id-tc26-gost-28147-param-Z"
#define LN_id_tc26_gost_28147_param_Z "GOST 28147-89 TC26 parameter set"
#define NID_id_tc26_gost_28147_param_Z 1003
#define OBJ_id_tc26_gost_28147_param_Z OBJ_id_tc26_gost_28147_constants,1L
#define SN_INN "INN"
#define LN_INN "INN"
#define NID_INN 1004
#define OBJ_INN OBJ_member_body,643L,3L,131L,1L,1L
#define SN_OGRN "OGRN"
#define LN_OGRN "OGRN"
#define NID_OGRN 1005
#define OBJ_OGRN OBJ_member_body,643L,100L,1L
#define SN_SNILS "SNILS"
#define LN_SNILS "SNILS"
#define NID_SNILS 1006
#define OBJ_SNILS OBJ_member_body,643L,100L,3L
#define SN_subjectSignTool "subjectSignTool"
#define LN_subjectSignTool "Signing Tool of Subject"
#define NID_subjectSignTool 1007
#define OBJ_subjectSignTool OBJ_member_body,643L,100L,111L
#define SN_issuerSignTool "issuerSignTool"
#define LN_issuerSignTool "Signing Tool of Issuer"
#define NID_issuerSignTool 1008
#define OBJ_issuerSignTool OBJ_member_body,643L,100L,112L
#define SN_grasshopper_ecb "grasshopper-ecb"
#define NID_grasshopper_ecb 1012
#define SN_grasshopper_ctr "grasshopper-ctr"
#define NID_grasshopper_ctr 1013
#define SN_grasshopper_ofb "grasshopper-ofb"
#define NID_grasshopper_ofb 1014
#define SN_grasshopper_cbc "grasshopper-cbc"
#define NID_grasshopper_cbc 1015
#define SN_grasshopper_cfb "grasshopper-cfb"
#define NID_grasshopper_cfb 1016
#define SN_grasshopper_mac "grasshopper-mac"
#define NID_grasshopper_mac 1017
#define SN_magma_ecb "magma-ecb"
#define NID_magma_ecb 1187
#define SN_magma_ctr "magma-ctr"
#define NID_magma_ctr 1188
#define SN_magma_ofb "magma-ofb"
#define NID_magma_ofb 1189
#define SN_magma_cbc "magma-cbc"
#define NID_magma_cbc 1190
#define SN_magma_cfb "magma-cfb"
#define NID_magma_cfb 1191
#define SN_magma_mac "magma-mac"
#define NID_magma_mac 1192
#define SN_camellia_128_cbc "CAMELLIA-128-CBC"
#define LN_camellia_128_cbc "camellia-128-cbc"
#define NID_camellia_128_cbc 751
#define OBJ_camellia_128_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,2L
#define SN_camellia_192_cbc "CAMELLIA-192-CBC"
#define LN_camellia_192_cbc "camellia-192-cbc"
#define NID_camellia_192_cbc 752
#define OBJ_camellia_192_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,3L
#define SN_camellia_256_cbc "CAMELLIA-256-CBC"
#define LN_camellia_256_cbc "camellia-256-cbc"
#define NID_camellia_256_cbc 753
#define OBJ_camellia_256_cbc 1L,2L,392L,200011L,61L,1L,1L,1L,4L
#define SN_id_camellia128_wrap "id-camellia128-wrap"
#define NID_id_camellia128_wrap 907
#define OBJ_id_camellia128_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,2L
#define SN_id_camellia192_wrap "id-camellia192-wrap"
#define NID_id_camellia192_wrap 908
#define OBJ_id_camellia192_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,3L
#define SN_id_camellia256_wrap "id-camellia256-wrap"
#define NID_id_camellia256_wrap 909
#define OBJ_id_camellia256_wrap 1L,2L,392L,200011L,61L,1L,1L,3L,4L
#define OBJ_ntt_ds 0L,3L,4401L,5L
#define OBJ_camellia OBJ_ntt_ds,3L,1L,9L
#define SN_camellia_128_ecb "CAMELLIA-128-ECB"
#define LN_camellia_128_ecb "camellia-128-ecb"
#define NID_camellia_128_ecb 754
#define OBJ_camellia_128_ecb OBJ_camellia,1L
#define SN_camellia_128_ofb128 "CAMELLIA-128-OFB"
#define LN_camellia_128_ofb128 "camellia-128-ofb"
#define NID_camellia_128_ofb128 766
#define OBJ_camellia_128_ofb128 OBJ_camellia,3L
#define SN_camellia_128_cfb128 "CAMELLIA-128-CFB"
#define LN_camellia_128_cfb128 "camellia-128-cfb"
#define NID_camellia_128_cfb128 757
#define OBJ_camellia_128_cfb128 OBJ_camellia,4L
#define SN_camellia_128_gcm "CAMELLIA-128-GCM"
#define LN_camellia_128_gcm "camellia-128-gcm"
#define NID_camellia_128_gcm 961
#define OBJ_camellia_128_gcm OBJ_camellia,6L
#define SN_camellia_128_ccm "CAMELLIA-128-CCM"
#define LN_camellia_128_ccm "camellia-128-ccm"
#define NID_camellia_128_ccm 962
#define OBJ_camellia_128_ccm OBJ_camellia,7L
#define SN_camellia_128_ctr "CAMELLIA-128-CTR"
#define LN_camellia_128_ctr "camellia-128-ctr"
#define NID_camellia_128_ctr 963
#define OBJ_camellia_128_ctr OBJ_camellia,9L
#define SN_camellia_128_cmac "CAMELLIA-128-CMAC"
#define LN_camellia_128_cmac "camellia-128-cmac"
#define NID_camellia_128_cmac 964
#define OBJ_camellia_128_cmac OBJ_camellia,10L
#define SN_camellia_192_ecb "CAMELLIA-192-ECB"
#define LN_camellia_192_ecb "camellia-192-ecb"
#define NID_camellia_192_ecb 755
#define OBJ_camellia_192_ecb OBJ_camellia,21L
#define SN_camellia_192_ofb128 "CAMELLIA-192-OFB"
#define LN_camellia_192_ofb128 "camellia-192-ofb"
#define NID_camellia_192_ofb128 767
#define OBJ_camellia_192_ofb128 OBJ_camellia,23L
#define SN_camellia_192_cfb128 "CAMELLIA-192-CFB"
#define LN_camellia_192_cfb128 "camellia-192-cfb"
#define NID_camellia_192_cfb128 758
#define OBJ_camellia_192_cfb128 OBJ_camellia,24L
#define SN_camellia_192_gcm "CAMELLIA-192-GCM"
#define LN_camellia_192_gcm "camellia-192-gcm"
#define NID_camellia_192_gcm 965
#define OBJ_camellia_192_gcm OBJ_camellia,26L
#define SN_camellia_192_ccm "CAMELLIA-192-CCM"
#define LN_camellia_192_ccm "camellia-192-ccm"
#define NID_camellia_192_ccm 966
#define OBJ_camellia_192_ccm OBJ_camellia,27L
#define SN_camellia_192_ctr "CAMELLIA-192-CTR"
#define LN_camellia_192_ctr "camellia-192-ctr"
#define NID_camellia_192_ctr 967
#define OBJ_camellia_192_ctr OBJ_camellia,29L
#define SN_camellia_192_cmac "CAMELLIA-192-CMAC"
#define LN_camellia_192_cmac "camellia-192-cmac"
#define NID_camellia_192_cmac 968
#define OBJ_camellia_192_cmac OBJ_camellia,30L
#define SN_camellia_256_ecb "CAMELLIA-256-ECB"
#define LN_camellia_256_ecb "camellia-256-ecb"
#define NID_camellia_256_ecb 756
#define OBJ_camellia_256_ecb OBJ_camellia,41L
#define SN_camellia_256_ofb128 "CAMELLIA-256-OFB"
#define LN_camellia_256_ofb128 "camellia-256-ofb"
#define NID_camellia_256_ofb128 768
#define OBJ_camellia_256_ofb128 OBJ_camellia,43L
#define SN_camellia_256_cfb128 "CAMELLIA-256-CFB"
#define LN_camellia_256_cfb128 "camellia-256-cfb"
#define NID_camellia_256_cfb128 759
#define OBJ_camellia_256_cfb128 OBJ_camellia,44L
#define SN_camellia_256_gcm "CAMELLIA-256-GCM"
#define LN_camellia_256_gcm "camellia-256-gcm"
#define NID_camellia_256_gcm 969
#define OBJ_camellia_256_gcm OBJ_camellia,46L
#define SN_camellia_256_ccm "CAMELLIA-256-CCM"
#define LN_camellia_256_ccm "camellia-256-ccm"
#define NID_camellia_256_ccm 970
#define OBJ_camellia_256_ccm OBJ_camellia,47L
#define SN_camellia_256_ctr "CAMELLIA-256-CTR"
#define LN_camellia_256_ctr "camellia-256-ctr"
#define NID_camellia_256_ctr 971
#define OBJ_camellia_256_ctr OBJ_camellia,49L
#define SN_camellia_256_cmac "CAMELLIA-256-CMAC"
#define LN_camellia_256_cmac "camellia-256-cmac"
#define NID_camellia_256_cmac 972
#define OBJ_camellia_256_cmac OBJ_camellia,50L
#define SN_camellia_128_cfb1 "CAMELLIA-128-CFB1"
#define LN_camellia_128_cfb1 "camellia-128-cfb1"
#define NID_camellia_128_cfb1 760
#define SN_camellia_192_cfb1 "CAMELLIA-192-CFB1"
#define LN_camellia_192_cfb1 "camellia-192-cfb1"
#define NID_camellia_192_cfb1 761
#define SN_camellia_256_cfb1 "CAMELLIA-256-CFB1"
#define LN_camellia_256_cfb1 "camellia-256-cfb1"
#define NID_camellia_256_cfb1 762
#define SN_camellia_128_cfb8 "CAMELLIA-128-CFB8"
#define LN_camellia_128_cfb8 "camellia-128-cfb8"
#define NID_camellia_128_cfb8 763
#define SN_camellia_192_cfb8 "CAMELLIA-192-CFB8"
#define LN_camellia_192_cfb8 "camellia-192-cfb8"
#define NID_camellia_192_cfb8 764
#define SN_camellia_256_cfb8 "CAMELLIA-256-CFB8"
#define LN_camellia_256_cfb8 "camellia-256-cfb8"
#define NID_camellia_256_cfb8 765
#define OBJ_aria 1L,2L,410L,200046L,1L,1L
#define SN_aria_128_ecb "ARIA-128-ECB"
#define LN_aria_128_ecb "aria-128-ecb"
#define NID_aria_128_ecb 1065
#define OBJ_aria_128_ecb OBJ_aria,1L
#define SN_aria_128_cbc "ARIA-128-CBC"
#define LN_aria_128_cbc "aria-128-cbc"
#define NID_aria_128_cbc 1066
#define OBJ_aria_128_cbc OBJ_aria,2L
#define SN_aria_128_cfb128 "ARIA-128-CFB"
#define LN_aria_128_cfb128 "aria-128-cfb"
#define NID_aria_128_cfb128 1067
#define OBJ_aria_128_cfb128 OBJ_aria,3L
#define SN_aria_128_ofb128 "ARIA-128-OFB"
#define LN_aria_128_ofb128 "aria-128-ofb"
#define NID_aria_128_ofb128 1068
#define OBJ_aria_128_ofb128 OBJ_aria,4L
#define SN_aria_128_ctr "ARIA-128-CTR"
#define LN_aria_128_ctr "aria-128-ctr"
#define NID_aria_128_ctr 1069
#define OBJ_aria_128_ctr OBJ_aria,5L
#define SN_aria_192_ecb "ARIA-192-ECB"
#define LN_aria_192_ecb "aria-192-ecb"
#define NID_aria_192_ecb 1070
#define OBJ_aria_192_ecb OBJ_aria,6L
#define SN_aria_192_cbc "ARIA-192-CBC"
#define LN_aria_192_cbc "aria-192-cbc"
#define NID_aria_192_cbc 1071
#define OBJ_aria_192_cbc OBJ_aria,7L
#define SN_aria_192_cfb128 "ARIA-192-CFB"
#define LN_aria_192_cfb128 "aria-192-cfb"
#define NID_aria_192_cfb128 1072
#define OBJ_aria_192_cfb128 OBJ_aria,8L
#define SN_aria_192_ofb128 "ARIA-192-OFB"
#define LN_aria_192_ofb128 "aria-192-ofb"
#define NID_aria_192_ofb128 1073
#define OBJ_aria_192_ofb128 OBJ_aria,9L
#define SN_aria_192_ctr "ARIA-192-CTR"
#define LN_aria_192_ctr "aria-192-ctr"
#define NID_aria_192_ctr 1074
#define OBJ_aria_192_ctr OBJ_aria,10L
#define SN_aria_256_ecb "ARIA-256-ECB"
#define LN_aria_256_ecb "aria-256-ecb"
#define NID_aria_256_ecb 1075
#define OBJ_aria_256_ecb OBJ_aria,11L
#define SN_aria_256_cbc "ARIA-256-CBC"
#define LN_aria_256_cbc "aria-256-cbc"
#define NID_aria_256_cbc 1076
#define OBJ_aria_256_cbc OBJ_aria,12L
#define SN_aria_256_cfb128 "ARIA-256-CFB"
#define LN_aria_256_cfb128 "aria-256-cfb"
#define NID_aria_256_cfb128 1077
#define OBJ_aria_256_cfb128 OBJ_aria,13L
#define SN_aria_256_ofb128 "ARIA-256-OFB"
#define LN_aria_256_ofb128 "aria-256-ofb"
#define NID_aria_256_ofb128 1078
#define OBJ_aria_256_ofb128 OBJ_aria,14L
#define SN_aria_256_ctr "ARIA-256-CTR"
#define LN_aria_256_ctr "aria-256-ctr"
#define NID_aria_256_ctr 1079
#define OBJ_aria_256_ctr OBJ_aria,15L
#define SN_aria_128_cfb1 "ARIA-128-CFB1"
#define LN_aria_128_cfb1 "aria-128-cfb1"
#define NID_aria_128_cfb1 1080
#define SN_aria_192_cfb1 "ARIA-192-CFB1"
#define LN_aria_192_cfb1 "aria-192-cfb1"
#define NID_aria_192_cfb1 1081
#define SN_aria_256_cfb1 "ARIA-256-CFB1"
#define LN_aria_256_cfb1 "aria-256-cfb1"
#define NID_aria_256_cfb1 1082
#define SN_aria_128_cfb8 "ARIA-128-CFB8"
#define LN_aria_128_cfb8 "aria-128-cfb8"
#define NID_aria_128_cfb8 1083
#define SN_aria_192_cfb8 "ARIA-192-CFB8"
#define LN_aria_192_cfb8 "aria-192-cfb8"
#define NID_aria_192_cfb8 1084
#define SN_aria_256_cfb8 "ARIA-256-CFB8"
#define LN_aria_256_cfb8 "aria-256-cfb8"
#define NID_aria_256_cfb8 1085
#define SN_aria_128_ccm "ARIA-128-CCM"
#define LN_aria_128_ccm "aria-128-ccm"
#define NID_aria_128_ccm 1120
#define OBJ_aria_128_ccm OBJ_aria,37L
#define SN_aria_192_ccm "ARIA-192-CCM"
#define LN_aria_192_ccm "aria-192-ccm"
#define NID_aria_192_ccm 1121
#define OBJ_aria_192_ccm OBJ_aria,38L
#define SN_aria_256_ccm "ARIA-256-CCM"
#define LN_aria_256_ccm "aria-256-ccm"
#define NID_aria_256_ccm 1122
#define OBJ_aria_256_ccm OBJ_aria,39L
#define SN_aria_128_gcm "ARIA-128-GCM"
#define LN_aria_128_gcm "aria-128-gcm"
#define NID_aria_128_gcm 1123
#define OBJ_aria_128_gcm OBJ_aria,34L
#define SN_aria_192_gcm "ARIA-192-GCM"
#define LN_aria_192_gcm "aria-192-gcm"
#define NID_aria_192_gcm 1124
#define OBJ_aria_192_gcm OBJ_aria,35L
#define SN_aria_256_gcm "ARIA-256-GCM"
#define LN_aria_256_gcm "aria-256-gcm"
#define NID_aria_256_gcm 1125
#define OBJ_aria_256_gcm OBJ_aria,36L
#define SN_kisa "KISA"
#define LN_kisa "kisa"
#define NID_kisa 773
#define OBJ_kisa OBJ_member_body,410L,200004L
#define SN_seed_ecb "SEED-ECB"
#define LN_seed_ecb "seed-ecb"
#define NID_seed_ecb 776
#define OBJ_seed_ecb OBJ_kisa,1L,3L
#define SN_seed_cbc "SEED-CBC"
#define LN_seed_cbc "seed-cbc"
#define NID_seed_cbc 777
#define OBJ_seed_cbc OBJ_kisa,1L,4L
#define SN_seed_cfb128 "SEED-CFB"
#define LN_seed_cfb128 "seed-cfb"
#define NID_seed_cfb128 779
#define OBJ_seed_cfb128 OBJ_kisa,1L,5L
#define SN_seed_ofb128 "SEED-OFB"
#define LN_seed_ofb128 "seed-ofb"
#define NID_seed_ofb128 778
#define OBJ_seed_ofb128 OBJ_kisa,1L,6L
#define SN_sm4_ecb "SM4-ECB"
#define LN_sm4_ecb "sm4-ecb"
#define NID_sm4_ecb 1133
#define OBJ_sm4_ecb OBJ_sm_scheme,104L,1L
#define SN_sm4_cbc "SM4-CBC"
#define LN_sm4_cbc "sm4-cbc"
#define NID_sm4_cbc 1134
#define OBJ_sm4_cbc OBJ_sm_scheme,104L,2L
#define SN_sm4_ofb128 "SM4-OFB"
#define LN_sm4_ofb128 "sm4-ofb"
#define NID_sm4_ofb128 1135
#define OBJ_sm4_ofb128 OBJ_sm_scheme,104L,3L
#define SN_sm4_cfb128 "SM4-CFB"
#define LN_sm4_cfb128 "sm4-cfb"
#define NID_sm4_cfb128 1137
#define OBJ_sm4_cfb128 OBJ_sm_scheme,104L,4L
#define SN_sm4_cfb1 "SM4-CFB1"
#define LN_sm4_cfb1 "sm4-cfb1"
#define NID_sm4_cfb1 1136
#define OBJ_sm4_cfb1 OBJ_sm_scheme,104L,5L
#define SN_sm4_cfb8 "SM4-CFB8"
#define LN_sm4_cfb8 "sm4-cfb8"
#define NID_sm4_cfb8 1138
#define OBJ_sm4_cfb8 OBJ_sm_scheme,104L,6L
#define SN_sm4_ctr "SM4-CTR"
#define LN_sm4_ctr "sm4-ctr"
#define NID_sm4_ctr 1139
#define OBJ_sm4_ctr OBJ_sm_scheme,104L,7L
#define SN_hmac "HMAC"
#define LN_hmac "hmac"
#define NID_hmac 855
#define SN_cmac "CMAC"
#define LN_cmac "cmac"
#define NID_cmac 894
#define SN_rc4_hmac_md5 "RC4-HMAC-MD5"
#define LN_rc4_hmac_md5 "rc4-hmac-md5"
#define NID_rc4_hmac_md5 915
#define SN_aes_128_cbc_hmac_sha1 "AES-128-CBC-HMAC-SHA1"
#define LN_aes_128_cbc_hmac_sha1 "aes-128-cbc-hmac-sha1"
#define NID_aes_128_cbc_hmac_sha1 916
#define SN_aes_192_cbc_hmac_sha1 "AES-192-CBC-HMAC-SHA1"
#define LN_aes_192_cbc_hmac_sha1 "aes-192-cbc-hmac-sha1"
#define NID_aes_192_cbc_hmac_sha1 917
#define SN_aes_256_cbc_hmac_sha1 "AES-256-CBC-HMAC-SHA1"
#define LN_aes_256_cbc_hmac_sha1 "aes-256-cbc-hmac-sha1"
#define NID_aes_256_cbc_hmac_sha1 918
#define SN_aes_128_cbc_hmac_sha256 "AES-128-CBC-HMAC-SHA256"
#define LN_aes_128_cbc_hmac_sha256 "aes-128-cbc-hmac-sha256"
#define NID_aes_128_cbc_hmac_sha256 948
#define SN_aes_192_cbc_hmac_sha256 "AES-192-CBC-HMAC-SHA256"
#define LN_aes_192_cbc_hmac_sha256 "aes-192-cbc-hmac-sha256"
#define NID_aes_192_cbc_hmac_sha256 949
#define SN_aes_256_cbc_hmac_sha256 "AES-256-CBC-HMAC-SHA256"
#define LN_aes_256_cbc_hmac_sha256 "aes-256-cbc-hmac-sha256"
#define NID_aes_256_cbc_hmac_sha256 950
#define SN_chacha20_poly1305 "ChaCha20-Poly1305"
#define LN_chacha20_poly1305 "chacha20-poly1305"
#define NID_chacha20_poly1305 1018
#define SN_chacha20 "ChaCha20"
#define LN_chacha20 "chacha20"
#define NID_chacha20 1019
#define SN_dhpublicnumber "dhpublicnumber"
#define LN_dhpublicnumber "X9.42 DH"
#define NID_dhpublicnumber 920
#define OBJ_dhpublicnumber OBJ_ISO_US,10046L,2L,1L
#define SN_brainpoolP160r1 "brainpoolP160r1"
#define NID_brainpoolP160r1 921
#define OBJ_brainpoolP160r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,1L
#define SN_brainpoolP160t1 "brainpoolP160t1"
#define NID_brainpoolP160t1 922
#define OBJ_brainpoolP160t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,2L
#define SN_brainpoolP192r1 "brainpoolP192r1"
#define NID_brainpoolP192r1 923
#define OBJ_brainpoolP192r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,3L
#define SN_brainpoolP192t1 "brainpoolP192t1"
#define NID_brainpoolP192t1 924
#define OBJ_brainpoolP192t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,4L
#define SN_brainpoolP224r1 "brainpoolP224r1"
#define NID_brainpoolP224r1 925
#define OBJ_brainpoolP224r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,5L
#define SN_brainpoolP224t1 "brainpoolP224t1"
#define NID_brainpoolP224t1 926
#define OBJ_brainpoolP224t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,6L
#define SN_brainpoolP256r1 "brainpoolP256r1"
#define NID_brainpoolP256r1 927
#define OBJ_brainpoolP256r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,7L
#define SN_brainpoolP256t1 "brainpoolP256t1"
#define NID_brainpoolP256t1 928
#define OBJ_brainpoolP256t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,8L
#define SN_brainpoolP320r1 "brainpoolP320r1"
#define NID_brainpoolP320r1 929
#define OBJ_brainpoolP320r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,9L
#define SN_brainpoolP320t1 "brainpoolP320t1"
#define NID_brainpoolP320t1 930
#define OBJ_brainpoolP320t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,10L
#define SN_brainpoolP384r1 "brainpoolP384r1"
#define NID_brainpoolP384r1 931
#define OBJ_brainpoolP384r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,11L
#define SN_brainpoolP384t1 "brainpoolP384t1"
#define NID_brainpoolP384t1 932
#define OBJ_brainpoolP384t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,12L
#define SN_brainpoolP512r1 "brainpoolP512r1"
#define NID_brainpoolP512r1 933
#define OBJ_brainpoolP512r1 1L,3L,36L,3L,3L,2L,8L,1L,1L,13L
#define SN_brainpoolP512t1 "brainpoolP512t1"
#define NID_brainpoolP512t1 934
#define OBJ_brainpoolP512t1 1L,3L,36L,3L,3L,2L,8L,1L,1L,14L
#define OBJ_x9_63_scheme 1L,3L,133L,16L,840L,63L,0L
#define OBJ_secg_scheme OBJ_certicom_arc,1L
#define SN_dhSinglePass_stdDH_sha1kdf_scheme "dhSinglePass-stdDH-sha1kdf-scheme"
#define NID_dhSinglePass_stdDH_sha1kdf_scheme 936
#define OBJ_dhSinglePass_stdDH_sha1kdf_scheme OBJ_x9_63_scheme,2L
#define SN_dhSinglePass_stdDH_sha224kdf_scheme "dhSinglePass-stdDH-sha224kdf-scheme"
#define NID_dhSinglePass_stdDH_sha224kdf_scheme 937
#define OBJ_dhSinglePass_stdDH_sha224kdf_scheme OBJ_secg_scheme,11L,0L
#define SN_dhSinglePass_stdDH_sha256kdf_scheme "dhSinglePass-stdDH-sha256kdf-scheme"
#define NID_dhSinglePass_stdDH_sha256kdf_scheme 938
#define OBJ_dhSinglePass_stdDH_sha256kdf_scheme OBJ_secg_scheme,11L,1L
#define SN_dhSinglePass_stdDH_sha384kdf_scheme "dhSinglePass-stdDH-sha384kdf-scheme"
#define NID_dhSinglePass_stdDH_sha384kdf_scheme 939
#define OBJ_dhSinglePass_stdDH_sha384kdf_scheme OBJ_secg_scheme,11L,2L
#define SN_dhSinglePass_stdDH_sha512kdf_scheme "dhSinglePass-stdDH-sha512kdf-scheme"
#define NID_dhSinglePass_stdDH_sha512kdf_scheme 940
#define OBJ_dhSinglePass_stdDH_sha512kdf_scheme OBJ_secg_scheme,11L,3L
#define SN_dhSinglePass_cofactorDH_sha1kdf_scheme "dhSinglePass-cofactorDH-sha1kdf-scheme"
#define NID_dhSinglePass_cofactorDH_sha1kdf_scheme 941
#define OBJ_dhSinglePass_cofactorDH_sha1kdf_scheme OBJ_x9_63_scheme,3L
#define SN_dhSinglePass_cofactorDH_sha224kdf_scheme "dhSinglePass-cofactorDH-sha224kdf-scheme"
#define NID_dhSinglePass_cofactorDH_sha224kdf_scheme 942
#define OBJ_dhSinglePass_cofactorDH_sha224kdf_scheme OBJ_secg_scheme,14L,0L
#define SN_dhSinglePass_cofactorDH_sha256kdf_scheme "dhSinglePass-cofactorDH-sha256kdf-scheme"
#define NID_dhSinglePass_cofactorDH_sha256kdf_scheme 943
#define OBJ_dhSinglePass_cofactorDH_sha256kdf_scheme OBJ_secg_scheme,14L,1L
#define SN_dhSinglePass_cofactorDH_sha384kdf_scheme "dhSinglePass-cofactorDH-sha384kdf-scheme"
#define NID_dhSinglePass_cofactorDH_sha384kdf_scheme 944
#define OBJ_dhSinglePass_cofactorDH_sha384kdf_scheme OBJ_secg_scheme,14L,2L
#define SN_dhSinglePass_cofactorDH_sha512kdf_scheme "dhSinglePass-cofactorDH-sha512kdf-scheme"
#define NID_dhSinglePass_cofactorDH_sha512kdf_scheme 945
#define OBJ_dhSinglePass_cofactorDH_sha512kdf_scheme OBJ_secg_scheme,14L,3L
#define SN_dh_std_kdf "dh-std-kdf"
#define NID_dh_std_kdf 946
#define SN_dh_cofactor_kdf "dh-cofactor-kdf"
#define NID_dh_cofactor_kdf 947
#define SN_ct_precert_scts "ct_precert_scts"
#define LN_ct_precert_scts "CT Precertificate SCTs"
#define NID_ct_precert_scts 951
#define OBJ_ct_precert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,2L
#define SN_ct_precert_poison "ct_precert_poison"
#define LN_ct_precert_poison "CT Precertificate Poison"
#define NID_ct_precert_poison 952
#define OBJ_ct_precert_poison 1L,3L,6L,1L,4L,1L,11129L,2L,4L,3L
#define SN_ct_precert_signer "ct_precert_signer"
#define LN_ct_precert_signer "CT Precertificate Signer"
#define NID_ct_precert_signer 953
#define OBJ_ct_precert_signer 1L,3L,6L,1L,4L,1L,11129L,2L,4L,4L
#define SN_ct_cert_scts "ct_cert_scts"
#define LN_ct_cert_scts "CT Certificate SCTs"
#define NID_ct_cert_scts 954
#define OBJ_ct_cert_scts 1L,3L,6L,1L,4L,1L,11129L,2L,4L,5L
#define SN_jurisdictionLocalityName "jurisdictionL"
#define LN_jurisdictionLocalityName "jurisdictionLocalityName"
#define NID_jurisdictionLocalityName 955
#define OBJ_jurisdictionLocalityName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,1L
#define SN_jurisdictionStateOrProvinceName "jurisdictionST"
#define LN_jurisdictionStateOrProvinceName "jurisdictionStateOrProvinceName"
#define NID_jurisdictionStateOrProvinceName 956
#define OBJ_jurisdictionStateOrProvinceName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,2L
#define SN_jurisdictionCountryName "jurisdictionC"
#define LN_jurisdictionCountryName "jurisdictionCountryName"
#define NID_jurisdictionCountryName 957
#define OBJ_jurisdictionCountryName 1L,3L,6L,1L,4L,1L,311L,60L,2L,1L,3L
#define SN_id_scrypt "id-scrypt"
#define LN_id_scrypt "scrypt"
#define NID_id_scrypt 973
#define OBJ_id_scrypt 1L,3L,6L,1L,4L,1L,11591L,4L,11L
#define SN_tls1_prf "TLS1-PRF"
#define LN_tls1_prf "tls1-prf"
#define NID_tls1_prf 1021
#define SN_hkdf "HKDF"
#define LN_hkdf "hkdf"
#define NID_hkdf 1036
#define SN_id_pkinit "id-pkinit"
#define NID_id_pkinit 1031
#define OBJ_id_pkinit 1L,3L,6L,1L,5L,2L,3L
#define SN_pkInitClientAuth "pkInitClientAuth"
#define LN_pkInitClientAuth "PKINIT Client Auth"
#define NID_pkInitClientAuth 1032
#define OBJ_pkInitClientAuth OBJ_id_pkinit,4L
#define SN_pkInitKDC "pkInitKDC"
#define LN_pkInitKDC "Signing KDC Response"
#define NID_pkInitKDC 1033
#define OBJ_pkInitKDC OBJ_id_pkinit,5L
#define SN_X25519 "X25519"
#define NID_X25519 1034
#define OBJ_X25519 1L,3L,101L,110L
#define SN_X448 "X448"
#define NID_X448 1035
#define OBJ_X448 1L,3L,101L,111L
#define SN_ED25519 "ED25519"
#define NID_ED25519 1087
#define OBJ_ED25519 1L,3L,101L,112L
#define SN_ED448 "ED448"
#define NID_ED448 1088
#define OBJ_ED448 1L,3L,101L,113L
#define SN_kx_rsa "KxRSA"
#define LN_kx_rsa "kx-rsa"
#define NID_kx_rsa 1037
#define SN_kx_ecdhe "KxECDHE"
#define LN_kx_ecdhe "kx-ecdhe"
#define NID_kx_ecdhe 1038
#define SN_kx_dhe "KxDHE"
#define LN_kx_dhe "kx-dhe"
#define NID_kx_dhe 1039
#define SN_kx_ecdhe_psk "KxECDHE-PSK"
#define LN_kx_ecdhe_psk "kx-ecdhe-psk"
#define NID_kx_ecdhe_psk 1040
#define SN_kx_dhe_psk "KxDHE-PSK"
#define LN_kx_dhe_psk "kx-dhe-psk"
#define NID_kx_dhe_psk 1041
#define SN_kx_rsa_psk "KxRSA_PSK"
#define LN_kx_rsa_psk "kx-rsa-psk"
#define NID_kx_rsa_psk 1042
#define SN_kx_psk "KxPSK"
#define LN_kx_psk "kx-psk"
#define NID_kx_psk 1043
#define SN_kx_srp "KxSRP"
#define LN_kx_srp "kx-srp"
#define NID_kx_srp 1044
#define SN_kx_gost "KxGOST"
#define LN_kx_gost "kx-gost"
#define NID_kx_gost 1045
#define SN_kx_any "KxANY"
#define LN_kx_any "kx-any"
#define NID_kx_any 1063
#define SN_auth_rsa "AuthRSA"
#define LN_auth_rsa "auth-rsa"
#define NID_auth_rsa 1046
#define SN_auth_ecdsa "AuthECDSA"
#define LN_auth_ecdsa "auth-ecdsa"
#define NID_auth_ecdsa 1047
#define SN_auth_psk "AuthPSK"
#define LN_auth_psk "auth-psk"
#define NID_auth_psk 1048
#define SN_auth_dss "AuthDSS"
#define LN_auth_dss "auth-dss"
#define NID_auth_dss 1049
#define SN_auth_gost01 "AuthGOST01"
#define LN_auth_gost01 "auth-gost01"
#define NID_auth_gost01 1050
#define SN_auth_gost12 "AuthGOST12"
#define LN_auth_gost12 "auth-gost12"
#define NID_auth_gost12 1051
#define SN_auth_srp "AuthSRP"
#define LN_auth_srp "auth-srp"
#define NID_auth_srp 1052
#define SN_auth_null "AuthNULL"
#define LN_auth_null "auth-null"
#define NID_auth_null 1053
#define SN_auth_any "AuthANY"
#define LN_auth_any "auth-any"
#define NID_auth_any 1064
#define SN_poly1305 "Poly1305"
#define LN_poly1305 "poly1305"
#define NID_poly1305 1061
#define SN_siphash "SipHash"
#define LN_siphash "siphash"
#define NID_siphash 1062
#define SN_ffdhe2048 "ffdhe2048"
#define NID_ffdhe2048 1126
#define SN_ffdhe3072 "ffdhe3072"
#define NID_ffdhe3072 1127
#define SN_ffdhe4096 "ffdhe4096"
#define NID_ffdhe4096 1128
#define SN_ffdhe6144 "ffdhe6144"
#define NID_ffdhe6144 1129
#define SN_ffdhe8192 "ffdhe8192"
#define NID_ffdhe8192 1130
#define SN_ISO_UA "ISO-UA"
#define NID_ISO_UA 1150
#define OBJ_ISO_UA OBJ_member_body,804L
#define SN_ua_pki "ua-pki"
#define NID_ua_pki 1151
#define OBJ_ua_pki OBJ_ISO_UA,2L,1L,1L,1L
#define SN_dstu28147 "dstu28147"
#define LN_dstu28147 "DSTU Gost 28147-2009"
#define NID_dstu28147 1152
#define OBJ_dstu28147 OBJ_ua_pki,1L,1L,1L
#define SN_dstu28147_ofb "dstu28147-ofb"
#define LN_dstu28147_ofb "DSTU Gost 28147-2009 OFB mode"
#define NID_dstu28147_ofb 1153
#define OBJ_dstu28147_ofb OBJ_dstu28147,2L
#define SN_dstu28147_cfb "dstu28147-cfb"
#define LN_dstu28147_cfb "DSTU Gost 28147-2009 CFB mode"
#define NID_dstu28147_cfb 1154
#define OBJ_dstu28147_cfb OBJ_dstu28147,3L
#define SN_dstu28147_wrap "dstu28147-wrap"
#define LN_dstu28147_wrap "DSTU Gost 28147-2009 key wrap"
#define NID_dstu28147_wrap 1155
#define OBJ_dstu28147_wrap OBJ_dstu28147,5L
#define SN_hmacWithDstu34311 "hmacWithDstu34311"
#define LN_hmacWithDstu34311 "HMAC DSTU Gost 34311-95"
#define NID_hmacWithDstu34311 1156
#define OBJ_hmacWithDstu34311 OBJ_ua_pki,1L,1L,2L
#define SN_dstu34311 "dstu34311"
#define LN_dstu34311 "DSTU Gost 34311-95"
#define NID_dstu34311 1157
#define OBJ_dstu34311 OBJ_ua_pki,1L,2L,1L
#define SN_dstu4145le "dstu4145le"
#define LN_dstu4145le "DSTU 4145-2002 little endian"
#define NID_dstu4145le 1158
#define OBJ_dstu4145le OBJ_ua_pki,1L,3L,1L,1L
#define SN_dstu4145be "dstu4145be"
#define LN_dstu4145be "DSTU 4145-2002 big endian"
#define NID_dstu4145be 1159
#define OBJ_dstu4145be OBJ_dstu4145le,1L,1L
#define SN_uacurve0 "uacurve0"
#define LN_uacurve0 "DSTU curve 0"
#define NID_uacurve0 1160
#define OBJ_uacurve0 OBJ_dstu4145le,2L,0L
#define SN_uacurve1 "uacurve1"
#define LN_uacurve1 "DSTU curve 1"
#define NID_uacurve1 1161
#define OBJ_uacurve1 OBJ_dstu4145le,2L,1L
#define SN_uacurve2 "uacurve2"
#define LN_uacurve2 "DSTU curve 2"
#define NID_uacurve2 1162
#define OBJ_uacurve2 OBJ_dstu4145le,2L,2L
#define SN_uacurve3 "uacurve3"
#define LN_uacurve3 "DSTU curve 3"
#define NID_uacurve3 1163
#define OBJ_uacurve3 OBJ_dstu4145le,2L,3L
#define SN_uacurve4 "uacurve4"
#define LN_uacurve4 "DSTU curve 4"
#define NID_uacurve4 1164
#define OBJ_uacurve4 OBJ_dstu4145le,2L,4L
#define SN_uacurve5 "uacurve5"
#define LN_uacurve5 "DSTU curve 5"
#define NID_uacurve5 1165
#define OBJ_uacurve5 OBJ_dstu4145le,2L,5L
#define SN_uacurve6 "uacurve6"
#define LN_uacurve6 "DSTU curve 6"
#define NID_uacurve6 1166
#define OBJ_uacurve6 OBJ_dstu4145le,2L,6L
#define SN_uacurve7 "uacurve7"
#define LN_uacurve7 "DSTU curve 7"
#define NID_uacurve7 1167
#define OBJ_uacurve7 OBJ_dstu4145le,2L,7L
#define SN_uacurve8 "uacurve8"
#define LN_uacurve8 "DSTU curve 8"
#define NID_uacurve8 1168
#define OBJ_uacurve8 OBJ_dstu4145le,2L,8L
#define SN_uacurve9 "uacurve9"
#define LN_uacurve9 "DSTU curve 9"
#define NID_uacurve9 1169
#define OBJ_uacurve9 OBJ_dstu4145le,2L,9L
diff --git a/include/openssl/ocsp.h b/include/openssl/ocsp.h
index 0a17166b5bf6..8582fe1ee1a4 100644
--- a/include/openssl/ocsp.h
+++ b/include/openssl/ocsp.h
@@ -1,352 +1,352 @@
/*
- * Copyright 2000-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2000-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_OCSP_H
# define HEADER_OCSP_H
#include <openssl/opensslconf.h>
/*
* These definitions are outside the OPENSSL_NO_OCSP guard because although for
* historical reasons they have OCSP_* names, they can actually be used
* independently of OCSP. E.g. see RFC5280
*/
/*-
* CRLReason ::= ENUMERATED {
* unspecified (0),
* keyCompromise (1),
* cACompromise (2),
* affiliationChanged (3),
* superseded (4),
* cessationOfOperation (5),
* certificateHold (6),
* removeFromCRL (8) }
*/
# define OCSP_REVOKED_STATUS_NOSTATUS -1
# define OCSP_REVOKED_STATUS_UNSPECIFIED 0
# define OCSP_REVOKED_STATUS_KEYCOMPROMISE 1
# define OCSP_REVOKED_STATUS_CACOMPROMISE 2
# define OCSP_REVOKED_STATUS_AFFILIATIONCHANGED 3
# define OCSP_REVOKED_STATUS_SUPERSEDED 4
# define OCSP_REVOKED_STATUS_CESSATIONOFOPERATION 5
# define OCSP_REVOKED_STATUS_CERTIFICATEHOLD 6
# define OCSP_REVOKED_STATUS_REMOVEFROMCRL 8
# ifndef OPENSSL_NO_OCSP
# include <openssl/ossl_typ.h>
# include <openssl/x509.h>
# include <openssl/x509v3.h>
# include <openssl/safestack.h>
# include <openssl/ocsperr.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Various flags and values */
# define OCSP_DEFAULT_NONCE_LENGTH 16
# define OCSP_NOCERTS 0x1
# define OCSP_NOINTERN 0x2
# define OCSP_NOSIGS 0x4
# define OCSP_NOCHAIN 0x8
# define OCSP_NOVERIFY 0x10
# define OCSP_NOEXPLICIT 0x20
# define OCSP_NOCASIGN 0x40
# define OCSP_NODELEGATED 0x80
# define OCSP_NOCHECKS 0x100
# define OCSP_TRUSTOTHER 0x200
# define OCSP_RESPID_KEY 0x400
# define OCSP_NOTIME 0x800
typedef struct ocsp_cert_id_st OCSP_CERTID;
DEFINE_STACK_OF(OCSP_CERTID)
typedef struct ocsp_one_request_st OCSP_ONEREQ;
DEFINE_STACK_OF(OCSP_ONEREQ)
typedef struct ocsp_req_info_st OCSP_REQINFO;
typedef struct ocsp_signature_st OCSP_SIGNATURE;
typedef struct ocsp_request_st OCSP_REQUEST;
# define OCSP_RESPONSE_STATUS_SUCCESSFUL 0
# define OCSP_RESPONSE_STATUS_MALFORMEDREQUEST 1
# define OCSP_RESPONSE_STATUS_INTERNALERROR 2
# define OCSP_RESPONSE_STATUS_TRYLATER 3
# define OCSP_RESPONSE_STATUS_SIGREQUIRED 5
# define OCSP_RESPONSE_STATUS_UNAUTHORIZED 6
typedef struct ocsp_resp_bytes_st OCSP_RESPBYTES;
# define V_OCSP_RESPID_NAME 0
# define V_OCSP_RESPID_KEY 1
DEFINE_STACK_OF(OCSP_RESPID)
typedef struct ocsp_revoked_info_st OCSP_REVOKEDINFO;
# define V_OCSP_CERTSTATUS_GOOD 0
# define V_OCSP_CERTSTATUS_REVOKED 1
# define V_OCSP_CERTSTATUS_UNKNOWN 2
typedef struct ocsp_cert_status_st OCSP_CERTSTATUS;
typedef struct ocsp_single_response_st OCSP_SINGLERESP;
DEFINE_STACK_OF(OCSP_SINGLERESP)
typedef struct ocsp_response_data_st OCSP_RESPDATA;
typedef struct ocsp_basic_response_st OCSP_BASICRESP;
typedef struct ocsp_crl_id_st OCSP_CRLID;
typedef struct ocsp_service_locator_st OCSP_SERVICELOC;
# define PEM_STRING_OCSP_REQUEST "OCSP REQUEST"
# define PEM_STRING_OCSP_RESPONSE "OCSP RESPONSE"
# define d2i_OCSP_REQUEST_bio(bp,p) ASN1_d2i_bio_of(OCSP_REQUEST,OCSP_REQUEST_new,d2i_OCSP_REQUEST,bp,p)
# define d2i_OCSP_RESPONSE_bio(bp,p) ASN1_d2i_bio_of(OCSP_RESPONSE,OCSP_RESPONSE_new,d2i_OCSP_RESPONSE,bp,p)
# define PEM_read_bio_OCSP_REQUEST(bp,x,cb) (OCSP_REQUEST *)PEM_ASN1_read_bio( \
(char *(*)())d2i_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST, \
bp,(char **)(x),cb,NULL)
# define PEM_read_bio_OCSP_RESPONSE(bp,x,cb)(OCSP_RESPONSE *)PEM_ASN1_read_bio(\
(char *(*)())d2i_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE, \
bp,(char **)(x),cb,NULL)
# define PEM_write_bio_OCSP_REQUEST(bp,o) \
PEM_ASN1_write_bio((int (*)())i2d_OCSP_REQUEST,PEM_STRING_OCSP_REQUEST,\
bp,(char *)(o), NULL,NULL,0,NULL,NULL)
# define PEM_write_bio_OCSP_RESPONSE(bp,o) \
PEM_ASN1_write_bio((int (*)())i2d_OCSP_RESPONSE,PEM_STRING_OCSP_RESPONSE,\
bp,(char *)(o), NULL,NULL,0,NULL,NULL)
# define i2d_OCSP_RESPONSE_bio(bp,o) ASN1_i2d_bio_of(OCSP_RESPONSE,i2d_OCSP_RESPONSE,bp,o)
# define i2d_OCSP_REQUEST_bio(bp,o) ASN1_i2d_bio_of(OCSP_REQUEST,i2d_OCSP_REQUEST,bp,o)
# define ASN1_BIT_STRING_digest(data,type,md,len) \
ASN1_item_digest(ASN1_ITEM_rptr(ASN1_BIT_STRING),type,data,md,len)
# define OCSP_CERTSTATUS_dup(cs)\
(OCSP_CERTSTATUS*)ASN1_dup((int(*)())i2d_OCSP_CERTSTATUS,\
(char *(*)())d2i_OCSP_CERTSTATUS,(char *)(cs))
OCSP_CERTID *OCSP_CERTID_dup(OCSP_CERTID *id);
OCSP_RESPONSE *OCSP_sendreq_bio(BIO *b, const char *path, OCSP_REQUEST *req);
OCSP_REQ_CTX *OCSP_sendreq_new(BIO *io, const char *path, OCSP_REQUEST *req,
int maxline);
int OCSP_REQ_CTX_nbio(OCSP_REQ_CTX *rctx);
int OCSP_sendreq_nbio(OCSP_RESPONSE **presp, OCSP_REQ_CTX *rctx);
OCSP_REQ_CTX *OCSP_REQ_CTX_new(BIO *io, int maxline);
void OCSP_REQ_CTX_free(OCSP_REQ_CTX *rctx);
void OCSP_set_max_response_length(OCSP_REQ_CTX *rctx, unsigned long len);
int OCSP_REQ_CTX_i2d(OCSP_REQ_CTX *rctx, const ASN1_ITEM *it,
ASN1_VALUE *val);
int OCSP_REQ_CTX_nbio_d2i(OCSP_REQ_CTX *rctx, ASN1_VALUE **pval,
const ASN1_ITEM *it);
BIO *OCSP_REQ_CTX_get0_mem_bio(OCSP_REQ_CTX *rctx);
int OCSP_REQ_CTX_http(OCSP_REQ_CTX *rctx, const char *op, const char *path);
int OCSP_REQ_CTX_set1_req(OCSP_REQ_CTX *rctx, OCSP_REQUEST *req);
int OCSP_REQ_CTX_add1_header(OCSP_REQ_CTX *rctx,
const char *name, const char *value);
OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, const X509 *subject,
const X509 *issuer);
OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst,
const X509_NAME *issuerName,
const ASN1_BIT_STRING *issuerKey,
const ASN1_INTEGER *serialNumber);
OCSP_ONEREQ *OCSP_request_add0_id(OCSP_REQUEST *req, OCSP_CERTID *cid);
int OCSP_request_add1_nonce(OCSP_REQUEST *req, unsigned char *val, int len);
int OCSP_basic_add1_nonce(OCSP_BASICRESP *resp, unsigned char *val, int len);
int OCSP_check_nonce(OCSP_REQUEST *req, OCSP_BASICRESP *bs);
int OCSP_copy_nonce(OCSP_BASICRESP *resp, OCSP_REQUEST *req);
int OCSP_request_set1_name(OCSP_REQUEST *req, X509_NAME *nm);
int OCSP_request_add1_cert(OCSP_REQUEST *req, X509 *cert);
int OCSP_request_sign(OCSP_REQUEST *req,
X509 *signer,
EVP_PKEY *key,
const EVP_MD *dgst,
STACK_OF(X509) *certs, unsigned long flags);
int OCSP_response_status(OCSP_RESPONSE *resp);
OCSP_BASICRESP *OCSP_response_get1_basic(OCSP_RESPONSE *resp);
const ASN1_OCTET_STRING *OCSP_resp_get0_signature(const OCSP_BASICRESP *bs);
const X509_ALGOR *OCSP_resp_get0_tbs_sigalg(const OCSP_BASICRESP *bs);
const OCSP_RESPDATA *OCSP_resp_get0_respdata(const OCSP_BASICRESP *bs);
int OCSP_resp_get0_signer(OCSP_BASICRESP *bs, X509 **signer,
STACK_OF(X509) *extra_certs);
int OCSP_resp_count(OCSP_BASICRESP *bs);
OCSP_SINGLERESP *OCSP_resp_get0(OCSP_BASICRESP *bs, int idx);
const ASN1_GENERALIZEDTIME *OCSP_resp_get0_produced_at(const OCSP_BASICRESP* bs);
const STACK_OF(X509) *OCSP_resp_get0_certs(const OCSP_BASICRESP *bs);
int OCSP_resp_get0_id(const OCSP_BASICRESP *bs,
const ASN1_OCTET_STRING **pid,
const X509_NAME **pname);
int OCSP_resp_get1_id(const OCSP_BASICRESP *bs,
ASN1_OCTET_STRING **pid,
X509_NAME **pname);
int OCSP_resp_find(OCSP_BASICRESP *bs, OCSP_CERTID *id, int last);
int OCSP_single_get0_status(OCSP_SINGLERESP *single, int *reason,
ASN1_GENERALIZEDTIME **revtime,
ASN1_GENERALIZEDTIME **thisupd,
ASN1_GENERALIZEDTIME **nextupd);
int OCSP_resp_find_status(OCSP_BASICRESP *bs, OCSP_CERTID *id, int *status,
int *reason,
ASN1_GENERALIZEDTIME **revtime,
ASN1_GENERALIZEDTIME **thisupd,
ASN1_GENERALIZEDTIME **nextupd);
int OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd,
ASN1_GENERALIZEDTIME *nextupd, long sec, long maxsec);
int OCSP_request_verify(OCSP_REQUEST *req, STACK_OF(X509) *certs,
X509_STORE *store, unsigned long flags);
int OCSP_parse_url(const char *url, char **phost, char **pport, char **ppath,
int *pssl);
-int OCSP_id_issuer_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
-int OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b);
+int OCSP_id_issuer_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
+int OCSP_id_cmp(const OCSP_CERTID *a, const OCSP_CERTID *b);
int OCSP_request_onereq_count(OCSP_REQUEST *req);
OCSP_ONEREQ *OCSP_request_onereq_get0(OCSP_REQUEST *req, int i);
OCSP_CERTID *OCSP_onereq_get0_id(OCSP_ONEREQ *one);
int OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd,
ASN1_OCTET_STRING **pikeyHash,
ASN1_INTEGER **pserial, OCSP_CERTID *cid);
int OCSP_request_is_signed(OCSP_REQUEST *req);
OCSP_RESPONSE *OCSP_response_create(int status, OCSP_BASICRESP *bs);
OCSP_SINGLERESP *OCSP_basic_add1_status(OCSP_BASICRESP *rsp,
OCSP_CERTID *cid,
int status, int reason,
ASN1_TIME *revtime,
ASN1_TIME *thisupd,
ASN1_TIME *nextupd);
int OCSP_basic_add1_cert(OCSP_BASICRESP *resp, X509 *cert);
int OCSP_basic_sign(OCSP_BASICRESP *brsp,
X509 *signer, EVP_PKEY *key, const EVP_MD *dgst,
STACK_OF(X509) *certs, unsigned long flags);
int OCSP_basic_sign_ctx(OCSP_BASICRESP *brsp,
X509 *signer, EVP_MD_CTX *ctx,
STACK_OF(X509) *certs, unsigned long flags);
int OCSP_RESPID_set_by_name(OCSP_RESPID *respid, X509 *cert);
int OCSP_RESPID_set_by_key(OCSP_RESPID *respid, X509 *cert);
int OCSP_RESPID_match(OCSP_RESPID *respid, X509 *cert);
X509_EXTENSION *OCSP_crlID_new(const char *url, long *n, char *tim);
X509_EXTENSION *OCSP_accept_responses_new(char **oids);
X509_EXTENSION *OCSP_archive_cutoff_new(char *tim);
X509_EXTENSION *OCSP_url_svcloc_new(X509_NAME *issuer, const char **urls);
int OCSP_REQUEST_get_ext_count(OCSP_REQUEST *x);
int OCSP_REQUEST_get_ext_by_NID(OCSP_REQUEST *x, int nid, int lastpos);
int OCSP_REQUEST_get_ext_by_OBJ(OCSP_REQUEST *x, const ASN1_OBJECT *obj,
int lastpos);
int OCSP_REQUEST_get_ext_by_critical(OCSP_REQUEST *x, int crit, int lastpos);
X509_EXTENSION *OCSP_REQUEST_get_ext(OCSP_REQUEST *x, int loc);
X509_EXTENSION *OCSP_REQUEST_delete_ext(OCSP_REQUEST *x, int loc);
void *OCSP_REQUEST_get1_ext_d2i(OCSP_REQUEST *x, int nid, int *crit,
int *idx);
int OCSP_REQUEST_add1_ext_i2d(OCSP_REQUEST *x, int nid, void *value, int crit,
unsigned long flags);
int OCSP_REQUEST_add_ext(OCSP_REQUEST *x, X509_EXTENSION *ex, int loc);
int OCSP_ONEREQ_get_ext_count(OCSP_ONEREQ *x);
int OCSP_ONEREQ_get_ext_by_NID(OCSP_ONEREQ *x, int nid, int lastpos);
int OCSP_ONEREQ_get_ext_by_OBJ(OCSP_ONEREQ *x, const ASN1_OBJECT *obj, int lastpos);
int OCSP_ONEREQ_get_ext_by_critical(OCSP_ONEREQ *x, int crit, int lastpos);
X509_EXTENSION *OCSP_ONEREQ_get_ext(OCSP_ONEREQ *x, int loc);
X509_EXTENSION *OCSP_ONEREQ_delete_ext(OCSP_ONEREQ *x, int loc);
void *OCSP_ONEREQ_get1_ext_d2i(OCSP_ONEREQ *x, int nid, int *crit, int *idx);
int OCSP_ONEREQ_add1_ext_i2d(OCSP_ONEREQ *x, int nid, void *value, int crit,
unsigned long flags);
int OCSP_ONEREQ_add_ext(OCSP_ONEREQ *x, X509_EXTENSION *ex, int loc);
int OCSP_BASICRESP_get_ext_count(OCSP_BASICRESP *x);
int OCSP_BASICRESP_get_ext_by_NID(OCSP_BASICRESP *x, int nid, int lastpos);
int OCSP_BASICRESP_get_ext_by_OBJ(OCSP_BASICRESP *x, const ASN1_OBJECT *obj,
int lastpos);
int OCSP_BASICRESP_get_ext_by_critical(OCSP_BASICRESP *x, int crit,
int lastpos);
X509_EXTENSION *OCSP_BASICRESP_get_ext(OCSP_BASICRESP *x, int loc);
X509_EXTENSION *OCSP_BASICRESP_delete_ext(OCSP_BASICRESP *x, int loc);
void *OCSP_BASICRESP_get1_ext_d2i(OCSP_BASICRESP *x, int nid, int *crit,
int *idx);
int OCSP_BASICRESP_add1_ext_i2d(OCSP_BASICRESP *x, int nid, void *value,
int crit, unsigned long flags);
int OCSP_BASICRESP_add_ext(OCSP_BASICRESP *x, X509_EXTENSION *ex, int loc);
int OCSP_SINGLERESP_get_ext_count(OCSP_SINGLERESP *x);
int OCSP_SINGLERESP_get_ext_by_NID(OCSP_SINGLERESP *x, int nid, int lastpos);
int OCSP_SINGLERESP_get_ext_by_OBJ(OCSP_SINGLERESP *x, const ASN1_OBJECT *obj,
int lastpos);
int OCSP_SINGLERESP_get_ext_by_critical(OCSP_SINGLERESP *x, int crit,
int lastpos);
X509_EXTENSION *OCSP_SINGLERESP_get_ext(OCSP_SINGLERESP *x, int loc);
X509_EXTENSION *OCSP_SINGLERESP_delete_ext(OCSP_SINGLERESP *x, int loc);
void *OCSP_SINGLERESP_get1_ext_d2i(OCSP_SINGLERESP *x, int nid, int *crit,
int *idx);
int OCSP_SINGLERESP_add1_ext_i2d(OCSP_SINGLERESP *x, int nid, void *value,
int crit, unsigned long flags);
int OCSP_SINGLERESP_add_ext(OCSP_SINGLERESP *x, X509_EXTENSION *ex, int loc);
const OCSP_CERTID *OCSP_SINGLERESP_get0_id(const OCSP_SINGLERESP *x);
DECLARE_ASN1_FUNCTIONS(OCSP_SINGLERESP)
DECLARE_ASN1_FUNCTIONS(OCSP_CERTSTATUS)
DECLARE_ASN1_FUNCTIONS(OCSP_REVOKEDINFO)
DECLARE_ASN1_FUNCTIONS(OCSP_BASICRESP)
DECLARE_ASN1_FUNCTIONS(OCSP_RESPDATA)
DECLARE_ASN1_FUNCTIONS(OCSP_RESPID)
DECLARE_ASN1_FUNCTIONS(OCSP_RESPONSE)
DECLARE_ASN1_FUNCTIONS(OCSP_RESPBYTES)
DECLARE_ASN1_FUNCTIONS(OCSP_ONEREQ)
DECLARE_ASN1_FUNCTIONS(OCSP_CERTID)
DECLARE_ASN1_FUNCTIONS(OCSP_REQUEST)
DECLARE_ASN1_FUNCTIONS(OCSP_SIGNATURE)
DECLARE_ASN1_FUNCTIONS(OCSP_REQINFO)
DECLARE_ASN1_FUNCTIONS(OCSP_CRLID)
DECLARE_ASN1_FUNCTIONS(OCSP_SERVICELOC)
const char *OCSP_response_status_str(long s);
const char *OCSP_cert_status_str(long s);
const char *OCSP_crl_reason_str(long s);
int OCSP_REQUEST_print(BIO *bp, OCSP_REQUEST *a, unsigned long flags);
int OCSP_RESPONSE_print(BIO *bp, OCSP_RESPONSE *o, unsigned long flags);
int OCSP_basic_verify(OCSP_BASICRESP *bs, STACK_OF(X509) *certs,
X509_STORE *st, unsigned long flags);
# ifdef __cplusplus
}
# endif
# endif
#endif
diff --git a/include/openssl/opensslv.h b/include/openssl/opensslv.h
index a4aa45bd246c..bdf44d47e599 100644
--- a/include/openssl/opensslv.h
+++ b/include/openssl/opensslv.h
@@ -1,101 +1,101 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_OPENSSLV_H
# define HEADER_OPENSSLV_H
#ifdef __cplusplus
extern "C" {
#endif
/*-
* Numeric release version identifier:
* MNNFFPPS: major minor fix patch status
* The status nibble has one of the values 0 for development, 1 to e for betas
* 1 to 14, and f for release. The patch level is exactly that.
* For example:
* 0.9.3-dev 0x00903000
* 0.9.3-beta1 0x00903001
* 0.9.3-beta2-dev 0x00903002
* 0.9.3-beta2 0x00903002 (same as ...beta2-dev)
* 0.9.3 0x0090300f
* 0.9.3a 0x0090301f
* 0.9.4 0x0090400f
* 1.2.3z 0x102031af
*
* For continuity reasons (because 0.9.5 is already out, and is coded
* 0x00905100), between 0.9.5 and 0.9.6 the coding of the patch level
* part is slightly different, by setting the highest bit. This means
* that 0.9.5a looks like this: 0x0090581f. At 0.9.6, we can start
* with 0x0090600S...
*
* (Prior to 0.9.3-dev a different scheme was used: 0.9.2b is 0x0922.)
* (Prior to 0.9.5a beta1, a different scheme was used: MMNNFFRBB for
* major minor fix final patch/beta)
*/
-# define OPENSSL_VERSION_NUMBER 0x1010102fL
-# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1b 26 Feb 2019"
+# define OPENSSL_VERSION_NUMBER 0x1010103fL
+# define OPENSSL_VERSION_TEXT "OpenSSL 1.1.1c 28 May 2019"
/*-
* The macros below are to be used for shared library (.so, .dll, ...)
* versioning. That kind of versioning works a bit differently between
* operating systems. The most usual scheme is to set a major and a minor
* number, and have the runtime loader check that the major number is equal
* to what it was at application link time, while the minor number has to
* be greater or equal to what it was at application link time. With this
* scheme, the version number is usually part of the file name, like this:
*
* libcrypto.so.0.9
*
* Some unixen also make a softlink with the major version number only:
*
* libcrypto.so.0
*
* On Tru64 and IRIX 6.x it works a little bit differently. There, the
* shared library version is stored in the file, and is actually a series
* of versions, separated by colons. The rightmost version present in the
* library when linking an application is stored in the application to be
* matched at run time. When the application is run, a check is done to
* see if the library version stored in the application matches any of the
* versions in the version string of the library itself.
* This version string can be constructed in any way, depending on what
* kind of matching is desired. However, to implement the same scheme as
* the one used in the other unixen, all compatible versions, from lowest
* to highest, should be part of the string. Consecutive builds would
* give the following versions strings:
*
* 3.0
* 3.0:3.1
* 3.0:3.1:3.2
* 4.0
* 4.0:4.1
*
* Notice how version 4 is completely incompatible with version, and
* therefore give the breach you can see.
*
* There may be other schemes as well that I haven't yet discovered.
*
* So, here's the way it works here: first of all, the library version
* number doesn't need at all to match the overall OpenSSL version.
* However, it's nice and more understandable if it actually does.
* The current library version is stored in the macro SHLIB_VERSION_NUMBER,
* which is just a piece of text in the format "M.m.e" (Major, minor, edit).
* For the sake of Tru64, IRIX, and any other OS that behaves in similar ways,
* we need to keep a history of version numbers, which is done in the
* macro SHLIB_VERSION_HISTORY. The numbers are separated by colons and
* should only keep the versions that are binary compatible with the current.
*/
# define SHLIB_VERSION_HISTORY ""
# define SHLIB_VERSION_NUMBER "1.1"
#ifdef __cplusplus
}
#endif
#endif /* HEADER_OPENSSLV_H */
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 48e1152a27e2..f93dc68fefdb 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1,2438 +1,2438 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_SSL_H
# define HEADER_SSL_H
# include <openssl/e_os2.h>
# include <openssl/opensslconf.h>
# include <openssl/comp.h>
# include <openssl/bio.h>
# if OPENSSL_API_COMPAT < 0x10100000L
# include <openssl/x509.h>
# include <openssl/crypto.h>
# include <openssl/buffer.h>
# endif
# include <openssl/lhash.h>
# include <openssl/pem.h>
# include <openssl/hmac.h>
# include <openssl/async.h>
# include <openssl/safestack.h>
# include <openssl/symhacks.h>
# include <openssl/ct.h>
# include <openssl/sslerr.h>
#ifdef __cplusplus
extern "C" {
#endif
/* OpenSSL version number for ASN.1 encoding of the session information */
/*-
* Version 0 - initial version
* Version 1 - added the optional peer certificate
*/
# define SSL_SESSION_ASN1_VERSION 0x0001
# define SSL_MAX_SSL_SESSION_ID_LENGTH 32
# define SSL_MAX_SID_CTX_LENGTH 32
# define SSL_MIN_RSA_MODULUS_LENGTH_IN_BYTES (512/8)
# define SSL_MAX_KEY_ARG_LENGTH 8
# define SSL_MAX_MASTER_KEY_LENGTH 48
/* The maximum number of encrypt/decrypt pipelines we can support */
# define SSL_MAX_PIPELINES 32
/* text strings for the ciphers */
/* These are used to specify which ciphers to use and not to use */
# define SSL_TXT_LOW "LOW"
# define SSL_TXT_MEDIUM "MEDIUM"
# define SSL_TXT_HIGH "HIGH"
# define SSL_TXT_FIPS "FIPS"
# define SSL_TXT_aNULL "aNULL"
# define SSL_TXT_eNULL "eNULL"
# define SSL_TXT_NULL "NULL"
# define SSL_TXT_kRSA "kRSA"
# define SSL_TXT_kDHr "kDHr"/* this cipher class has been removed */
# define SSL_TXT_kDHd "kDHd"/* this cipher class has been removed */
# define SSL_TXT_kDH "kDH"/* this cipher class has been removed */
# define SSL_TXT_kEDH "kEDH"/* alias for kDHE */
# define SSL_TXT_kDHE "kDHE"
# define SSL_TXT_kECDHr "kECDHr"/* this cipher class has been removed */
# define SSL_TXT_kECDHe "kECDHe"/* this cipher class has been removed */
# define SSL_TXT_kECDH "kECDH"/* this cipher class has been removed */
# define SSL_TXT_kEECDH "kEECDH"/* alias for kECDHE */
# define SSL_TXT_kECDHE "kECDHE"
# define SSL_TXT_kPSK "kPSK"
# define SSL_TXT_kRSAPSK "kRSAPSK"
# define SSL_TXT_kECDHEPSK "kECDHEPSK"
# define SSL_TXT_kDHEPSK "kDHEPSK"
# define SSL_TXT_kGOST "kGOST"
# define SSL_TXT_kSRP "kSRP"
# define SSL_TXT_aRSA "aRSA"
# define SSL_TXT_aDSS "aDSS"
# define SSL_TXT_aDH "aDH"/* this cipher class has been removed */
# define SSL_TXT_aECDH "aECDH"/* this cipher class has been removed */
# define SSL_TXT_aECDSA "aECDSA"
# define SSL_TXT_aPSK "aPSK"
# define SSL_TXT_aGOST94 "aGOST94"
# define SSL_TXT_aGOST01 "aGOST01"
# define SSL_TXT_aGOST12 "aGOST12"
# define SSL_TXT_aGOST "aGOST"
# define SSL_TXT_aSRP "aSRP"
# define SSL_TXT_DSS "DSS"
# define SSL_TXT_DH "DH"
# define SSL_TXT_DHE "DHE"/* same as "kDHE:-ADH" */
# define SSL_TXT_EDH "EDH"/* alias for DHE */
# define SSL_TXT_ADH "ADH"
# define SSL_TXT_RSA "RSA"
# define SSL_TXT_ECDH "ECDH"
# define SSL_TXT_EECDH "EECDH"/* alias for ECDHE" */
# define SSL_TXT_ECDHE "ECDHE"/* same as "kECDHE:-AECDH" */
# define SSL_TXT_AECDH "AECDH"
# define SSL_TXT_ECDSA "ECDSA"
# define SSL_TXT_PSK "PSK"
# define SSL_TXT_SRP "SRP"
# define SSL_TXT_DES "DES"
# define SSL_TXT_3DES "3DES"
# define SSL_TXT_RC4 "RC4"
# define SSL_TXT_RC2 "RC2"
# define SSL_TXT_IDEA "IDEA"
# define SSL_TXT_SEED "SEED"
# define SSL_TXT_AES128 "AES128"
# define SSL_TXT_AES256 "AES256"
# define SSL_TXT_AES "AES"
# define SSL_TXT_AES_GCM "AESGCM"
# define SSL_TXT_AES_CCM "AESCCM"
# define SSL_TXT_AES_CCM_8 "AESCCM8"
# define SSL_TXT_CAMELLIA128 "CAMELLIA128"
# define SSL_TXT_CAMELLIA256 "CAMELLIA256"
# define SSL_TXT_CAMELLIA "CAMELLIA"
# define SSL_TXT_CHACHA20 "CHACHA20"
# define SSL_TXT_GOST "GOST89"
# define SSL_TXT_ARIA "ARIA"
# define SSL_TXT_ARIA_GCM "ARIAGCM"
# define SSL_TXT_ARIA128 "ARIA128"
# define SSL_TXT_ARIA256 "ARIA256"
# define SSL_TXT_MD5 "MD5"
# define SSL_TXT_SHA1 "SHA1"
# define SSL_TXT_SHA "SHA"/* same as "SHA1" */
# define SSL_TXT_GOST94 "GOST94"
# define SSL_TXT_GOST89MAC "GOST89MAC"
# define SSL_TXT_GOST12 "GOST12"
# define SSL_TXT_GOST89MAC12 "GOST89MAC12"
# define SSL_TXT_SHA256 "SHA256"
# define SSL_TXT_SHA384 "SHA384"
# define SSL_TXT_SSLV3 "SSLv3"
# define SSL_TXT_TLSV1 "TLSv1"
# define SSL_TXT_TLSV1_1 "TLSv1.1"
# define SSL_TXT_TLSV1_2 "TLSv1.2"
# define SSL_TXT_ALL "ALL"
/*-
* COMPLEMENTOF* definitions. These identifiers are used to (de-select)
* ciphers normally not being used.
* Example: "RC4" will activate all ciphers using RC4 including ciphers
* without authentication, which would normally disabled by DEFAULT (due
* the "!ADH" being part of default). Therefore "RC4:!COMPLEMENTOFDEFAULT"
* will make sure that it is also disabled in the specific selection.
* COMPLEMENTOF* identifiers are portable between version, as adjustments
* to the default cipher setup will also be included here.
*
* COMPLEMENTOFDEFAULT does not experience the same special treatment that
* DEFAULT gets, as only selection is being done and no sorting as needed
* for DEFAULT.
*/
# define SSL_TXT_CMPALL "COMPLEMENTOFALL"
# define SSL_TXT_CMPDEF "COMPLEMENTOFDEFAULT"
/*
* The following cipher list is used by default. It also is substituted when
* an application-defined cipher list string starts with 'DEFAULT'.
* This applies to ciphersuites for TLSv1.2 and below.
*/
# define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL"
/* This is the default set of TLSv1.3 ciphersuites */
# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
"TLS_CHACHA20_POLY1305_SHA256:" \
"TLS_AES_128_GCM_SHA256"
# else
# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
"TLS_AES_128_GCM_SHA256"
#endif
/*
* As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
* starts with a reasonable order, and all we have to do for DEFAULT is
* throwing out anonymous and unencrypted ciphersuites! (The latter are not
* actually enabled by ALL, but "ALL:RSA" would enable some of them.)
*/
/* Used in SSL_set_shutdown()/SSL_get_shutdown(); */
# define SSL_SENT_SHUTDOWN 1
# define SSL_RECEIVED_SHUTDOWN 2
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
extern "C" {
#endif
# define SSL_FILETYPE_ASN1 X509_FILETYPE_ASN1
# define SSL_FILETYPE_PEM X509_FILETYPE_PEM
/*
* This is needed to stop compilers complaining about the 'struct ssl_st *'
* function parameters used to prototype callbacks in SSL_CTX.
*/
typedef struct ssl_st *ssl_crock_st;
typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
typedef struct ssl_method_st SSL_METHOD;
typedef struct ssl_cipher_st SSL_CIPHER;
typedef struct ssl_session_st SSL_SESSION;
typedef struct tls_sigalgs_st TLS_SIGALGS;
typedef struct ssl_conf_ctx_st SSL_CONF_CTX;
typedef struct ssl_comp_st SSL_COMP;
STACK_OF(SSL_CIPHER);
STACK_OF(SSL_COMP);
/* SRTP protection profiles for use with the use_srtp extension (RFC 5764)*/
typedef struct srtp_protection_profile_st {
const char *name;
unsigned long id;
} SRTP_PROTECTION_PROFILE;
DEFINE_STACK_OF(SRTP_PROTECTION_PROFILE)
typedef int (*tls_session_ticket_ext_cb_fn)(SSL *s, const unsigned char *data,
int len, void *arg);
typedef int (*tls_session_secret_cb_fn)(SSL *s, void *secret, int *secret_len,
STACK_OF(SSL_CIPHER) *peer_ciphers,
const SSL_CIPHER **cipher, void *arg);
/* Extension context codes */
/* This extension is only allowed in TLS */
#define SSL_EXT_TLS_ONLY 0x0001
/* This extension is only allowed in DTLS */
#define SSL_EXT_DTLS_ONLY 0x0002
/* Some extensions may be allowed in DTLS but we don't implement them for it */
#define SSL_EXT_TLS_IMPLEMENTATION_ONLY 0x0004
/* Most extensions are not defined for SSLv3 but EXT_TYPE_renegotiate is */
#define SSL_EXT_SSL3_ALLOWED 0x0008
/* Extension is only defined for TLS1.2 and below */
#define SSL_EXT_TLS1_2_AND_BELOW_ONLY 0x0010
/* Extension is only defined for TLS1.3 and above */
#define SSL_EXT_TLS1_3_ONLY 0x0020
/* Ignore this extension during parsing if we are resuming */
#define SSL_EXT_IGNORE_ON_RESUMPTION 0x0040
#define SSL_EXT_CLIENT_HELLO 0x0080
/* Really means TLS1.2 or below */
#define SSL_EXT_TLS1_2_SERVER_HELLO 0x0100
#define SSL_EXT_TLS1_3_SERVER_HELLO 0x0200
#define SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS 0x0400
#define SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST 0x0800
#define SSL_EXT_TLS1_3_CERTIFICATE 0x1000
#define SSL_EXT_TLS1_3_NEW_SESSION_TICKET 0x2000
#define SSL_EXT_TLS1_3_CERTIFICATE_REQUEST 0x4000
/* Typedefs for handling custom extensions */
typedef int (*custom_ext_add_cb)(SSL *s, unsigned int ext_type,
const unsigned char **out, size_t *outlen,
int *al, void *add_arg);
typedef void (*custom_ext_free_cb)(SSL *s, unsigned int ext_type,
const unsigned char *out, void *add_arg);
typedef int (*custom_ext_parse_cb)(SSL *s, unsigned int ext_type,
const unsigned char *in, size_t inlen,
int *al, void *parse_arg);
typedef int (*SSL_custom_ext_add_cb_ex)(SSL *s, unsigned int ext_type,
unsigned int context,
const unsigned char **out,
size_t *outlen, X509 *x,
size_t chainidx,
int *al, void *add_arg);
typedef void (*SSL_custom_ext_free_cb_ex)(SSL *s, unsigned int ext_type,
unsigned int context,
const unsigned char *out,
void *add_arg);
typedef int (*SSL_custom_ext_parse_cb_ex)(SSL *s, unsigned int ext_type,
unsigned int context,
const unsigned char *in,
size_t inlen, X509 *x,
size_t chainidx,
int *al, void *parse_arg);
/* Typedef for verification callback */
typedef int (*SSL_verify_cb)(int preverify_ok, X509_STORE_CTX *x509_ctx);
/*
* Some values are reserved until OpenSSL 1.2.0 because they were previously
* included in SSL_OP_ALL in a 1.1.x release.
*
* Reserved value (until OpenSSL 1.2.0) 0x00000001U
* Reserved value (until OpenSSL 1.2.0) 0x00000002U
*/
/* Allow initial connection to servers that don't support RI */
# define SSL_OP_LEGACY_SERVER_CONNECT 0x00000004U
/* Reserved value (until OpenSSL 1.2.0) 0x00000008U */
# define SSL_OP_TLSEXT_PADDING 0x00000010U
/* Reserved value (until OpenSSL 1.2.0) 0x00000020U */
# define SSL_OP_SAFARI_ECDHE_ECDSA_BUG 0x00000040U
/*
* Reserved value (until OpenSSL 1.2.0) 0x00000080U
* Reserved value (until OpenSSL 1.2.0) 0x00000100U
* Reserved value (until OpenSSL 1.2.0) 0x00000200U
*/
/* In TLSv1.3 allow a non-(ec)dhe based kex_mode */
# define SSL_OP_ALLOW_NO_DHE_KEX 0x00000400U
/*
* Disable SSL 3.0/TLS 1.0 CBC vulnerability workaround that was added in
* OpenSSL 0.9.6d. Usually (depending on the application protocol) the
* workaround is not needed. Unfortunately some broken SSL/TLS
* implementations cannot handle it at all, which is why we include it in
* SSL_OP_ALL. Added in 0.9.6e
*/
# define SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 0x00000800U
/* DTLS options */
# define SSL_OP_NO_QUERY_MTU 0x00001000U
/* Turn on Cookie Exchange (on relevant for servers) */
# define SSL_OP_COOKIE_EXCHANGE 0x00002000U
/* Don't use RFC4507 ticket extension */
# define SSL_OP_NO_TICKET 0x00004000U
# ifndef OPENSSL_NO_DTLS1_METHOD
/* Use Cisco's "speshul" version of DTLS_BAD_VER
* (only with deprecated DTLSv1_client_method()) */
# define SSL_OP_CISCO_ANYCONNECT 0x00008000U
# endif
/* As server, disallow session resumption on renegotiation */
# define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0x00010000U
/* Don't use compression even if supported */
# define SSL_OP_NO_COMPRESSION 0x00020000U
/* Permit unsafe legacy renegotiation */
# define SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION 0x00040000U
/* Disable encrypt-then-mac */
# define SSL_OP_NO_ENCRYPT_THEN_MAC 0x00080000U
/*
* Enable TLSv1.3 Compatibility mode. This is on by default. A future version
* of OpenSSL may have this disabled by default.
*/
# define SSL_OP_ENABLE_MIDDLEBOX_COMPAT 0x00100000U
/* Prioritize Chacha20Poly1305 when client does.
* Modifies SSL_OP_CIPHER_SERVER_PREFERENCE */
# define SSL_OP_PRIORITIZE_CHACHA 0x00200000U
/*
* Set on servers to choose the cipher according to the server's preferences
*/
# define SSL_OP_CIPHER_SERVER_PREFERENCE 0x00400000U
/*
* If set, a server will allow a client to issue a SSLv3.0 version number as
* latest version supported in the premaster secret, even when TLSv1.0
* (version 3.1) was announced in the client hello. Normally this is
* forbidden to prevent version rollback attacks.
*/
# define SSL_OP_TLS_ROLLBACK_BUG 0x00800000U
/*
* Switches off automatic TLSv1.3 anti-replay protection for early data. This
* is a server-side option only (no effect on the client).
*/
# define SSL_OP_NO_ANTI_REPLAY 0x01000000U
# define SSL_OP_NO_SSLv3 0x02000000U
# define SSL_OP_NO_TLSv1 0x04000000U
# define SSL_OP_NO_TLSv1_2 0x08000000U
# define SSL_OP_NO_TLSv1_1 0x10000000U
# define SSL_OP_NO_TLSv1_3 0x20000000U
# define SSL_OP_NO_DTLSv1 0x04000000U
# define SSL_OP_NO_DTLSv1_2 0x08000000U
# define SSL_OP_NO_SSL_MASK (SSL_OP_NO_SSLv3|\
SSL_OP_NO_TLSv1|SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2|SSL_OP_NO_TLSv1_3)
# define SSL_OP_NO_DTLS_MASK (SSL_OP_NO_DTLSv1|SSL_OP_NO_DTLSv1_2)
/* Disallow all renegotiation */
# define SSL_OP_NO_RENEGOTIATION 0x40000000U
/*
* Make server add server-hello extension from early version of cryptopro
* draft, when GOST ciphersuite is negotiated. Required for interoperability
* with CryptoPro CSP 3.x
*/
# define SSL_OP_CRYPTOPRO_TLSEXT_BUG 0x80000000U
/*
* SSL_OP_ALL: various bug workarounds that should be rather harmless.
* This used to be 0x000FFFFFL before 0.9.7.
* This used to be 0x80000BFFU before 1.1.1.
*/
# define SSL_OP_ALL (SSL_OP_CRYPTOPRO_TLSEXT_BUG|\
SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS|\
SSL_OP_LEGACY_SERVER_CONNECT|\
SSL_OP_TLSEXT_PADDING|\
SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
/* OBSOLETE OPTIONS: retained for compatibility */
/* Removed from OpenSSL 1.1.0. Was 0x00000001L */
/* Related to removed SSLv2. */
# define SSL_OP_MICROSOFT_SESS_ID_BUG 0x0
/* Removed from OpenSSL 1.1.0. Was 0x00000002L */
/* Related to removed SSLv2. */
# define SSL_OP_NETSCAPE_CHALLENGE_BUG 0x0
/* Removed from OpenSSL 0.9.8q and 1.0.0c. Was 0x00000008L */
/* Dead forever, see CVE-2010-4180 */
# define SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 0x0
/* Removed from OpenSSL 1.0.1h and 1.0.2. Was 0x00000010L */
/* Refers to ancient SSLREF and SSLv2. */
# define SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG 0x0
/* Removed from OpenSSL 1.1.0. Was 0x00000020 */
# define SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER 0x0
/* Removed from OpenSSL 0.9.7h and 0.9.8b. Was 0x00000040L */
# define SSL_OP_MSIE_SSLV2_RSA_PADDING 0x0
/* Removed from OpenSSL 1.1.0. Was 0x00000080 */
/* Ancient SSLeay version. */
# define SSL_OP_SSLEAY_080_CLIENT_DH_BUG 0x0
/* Removed from OpenSSL 1.1.0. Was 0x00000100L */
# define SSL_OP_TLS_D5_BUG 0x0
/* Removed from OpenSSL 1.1.0. Was 0x00000200L */
# define SSL_OP_TLS_BLOCK_PADDING_BUG 0x0
/* Removed from OpenSSL 1.1.0. Was 0x00080000L */
# define SSL_OP_SINGLE_ECDH_USE 0x0
/* Removed from OpenSSL 1.1.0. Was 0x00100000L */
# define SSL_OP_SINGLE_DH_USE 0x0
/* Removed from OpenSSL 1.0.1k and 1.0.2. Was 0x00200000L */
# define SSL_OP_EPHEMERAL_RSA 0x0
/* Removed from OpenSSL 1.1.0. Was 0x01000000L */
# define SSL_OP_NO_SSLv2 0x0
/* Removed from OpenSSL 1.0.1. Was 0x08000000L */
# define SSL_OP_PKCS1_CHECK_1 0x0
/* Removed from OpenSSL 1.0.1. Was 0x10000000L */
# define SSL_OP_PKCS1_CHECK_2 0x0
/* Removed from OpenSSL 1.1.0. Was 0x20000000L */
# define SSL_OP_NETSCAPE_CA_DN_BUG 0x0
/* Removed from OpenSSL 1.1.0. Was 0x40000000L */
# define SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG 0x0
/*
* Allow SSL_write(..., n) to return r with 0 < r < n (i.e. report success
* when just a single record has been written):
*/
# define SSL_MODE_ENABLE_PARTIAL_WRITE 0x00000001U
/*
* Make it possible to retry SSL_write() with changed buffer location (buffer
* contents must stay the same!); this is not the default to avoid the
* misconception that non-blocking SSL_write() behaves like non-blocking
* write():
*/
# define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002U
/*
* Never bother the application with retries if the transport is blocking:
*/
# define SSL_MODE_AUTO_RETRY 0x00000004U
/* Don't attempt to automatically build certificate chain */
# define SSL_MODE_NO_AUTO_CHAIN 0x00000008U
/*
* Save RAM by releasing read and write buffers when they're empty. (SSL3 and
* TLS only.) Released buffers are freed.
*/
# define SSL_MODE_RELEASE_BUFFERS 0x00000010U
/*
* Send the current time in the Random fields of the ClientHello and
* ServerHello records for compatibility with hypothetical implementations
* that require it.
*/
# define SSL_MODE_SEND_CLIENTHELLO_TIME 0x00000020U
# define SSL_MODE_SEND_SERVERHELLO_TIME 0x00000040U
/*
* Send TLS_FALLBACK_SCSV in the ClientHello. To be set only by applications
* that reconnect with a downgraded protocol version; see
* draft-ietf-tls-downgrade-scsv-00 for details. DO NOT ENABLE THIS if your
* application attempts a normal handshake. Only use this in explicit
* fallback retries, following the guidance in
* draft-ietf-tls-downgrade-scsv-00.
*/
# define SSL_MODE_SEND_FALLBACK_SCSV 0x00000080U
/*
* Support Asynchronous operation
*/
# define SSL_MODE_ASYNC 0x00000100U
/*
* When using DTLS/SCTP, include the terminating zero in the label
* used for computing the endpoint-pair shared secret. Required for
* interoperability with implementations having this bug like these
* older version of OpenSSL:
* - OpenSSL 1.0.0 series
* - OpenSSL 1.0.1 series
* - OpenSSL 1.0.2 series
* - OpenSSL 1.1.0 series
* - OpenSSL 1.1.1 and 1.1.1a
*/
# define SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG 0x00000400U
/* Cert related flags */
/*
* Many implementations ignore some aspects of the TLS standards such as
* enforcing certificate chain algorithms. When this is set we enforce them.
*/
# define SSL_CERT_FLAG_TLS_STRICT 0x00000001U
/* Suite B modes, takes same values as certificate verify flags */
# define SSL_CERT_FLAG_SUITEB_128_LOS_ONLY 0x10000
/* Suite B 192 bit only mode */
# define SSL_CERT_FLAG_SUITEB_192_LOS 0x20000
/* Suite B 128 bit mode allowing 192 bit algorithms */
# define SSL_CERT_FLAG_SUITEB_128_LOS 0x30000
/* Perform all sorts of protocol violations for testing purposes */
# define SSL_CERT_FLAG_BROKEN_PROTOCOL 0x10000000
/* Flags for building certificate chains */
/* Treat any existing certificates as untrusted CAs */
# define SSL_BUILD_CHAIN_FLAG_UNTRUSTED 0x1
/* Don't include root CA in chain */
# define SSL_BUILD_CHAIN_FLAG_NO_ROOT 0x2
/* Just check certificates already there */
# define SSL_BUILD_CHAIN_FLAG_CHECK 0x4
/* Ignore verification errors */
# define SSL_BUILD_CHAIN_FLAG_IGNORE_ERROR 0x8
/* Clear verification errors from queue */
# define SSL_BUILD_CHAIN_FLAG_CLEAR_ERROR 0x10
/* Flags returned by SSL_check_chain */
/* Certificate can be used with this session */
# define CERT_PKEY_VALID 0x1
/* Certificate can also be used for signing */
# define CERT_PKEY_SIGN 0x2
/* EE certificate signing algorithm OK */
# define CERT_PKEY_EE_SIGNATURE 0x10
/* CA signature algorithms OK */
# define CERT_PKEY_CA_SIGNATURE 0x20
/* EE certificate parameters OK */
# define CERT_PKEY_EE_PARAM 0x40
/* CA certificate parameters OK */
# define CERT_PKEY_CA_PARAM 0x80
/* Signing explicitly allowed as opposed to SHA1 fallback */
# define CERT_PKEY_EXPLICIT_SIGN 0x100
/* Client CA issuer names match (always set for server cert) */
# define CERT_PKEY_ISSUER_NAME 0x200
/* Cert type matches client types (always set for server cert) */
# define CERT_PKEY_CERT_TYPE 0x400
/* Cert chain suitable to Suite B */
# define CERT_PKEY_SUITEB 0x800
# define SSL_CONF_FLAG_CMDLINE 0x1
# define SSL_CONF_FLAG_FILE 0x2
# define SSL_CONF_FLAG_CLIENT 0x4
# define SSL_CONF_FLAG_SERVER 0x8
# define SSL_CONF_FLAG_SHOW_ERRORS 0x10
# define SSL_CONF_FLAG_CERTIFICATE 0x20
# define SSL_CONF_FLAG_REQUIRE_PRIVATE 0x40
/* Configuration value types */
# define SSL_CONF_TYPE_UNKNOWN 0x0
# define SSL_CONF_TYPE_STRING 0x1
# define SSL_CONF_TYPE_FILE 0x2
# define SSL_CONF_TYPE_DIR 0x3
# define SSL_CONF_TYPE_NONE 0x4
/* Maximum length of the application-controlled segment of a a TLSv1.3 cookie */
# define SSL_COOKIE_LENGTH 4096
/*
* Note: SSL[_CTX]_set_{options,mode} use |= op on the previous value, they
* cannot be used to clear bits.
*/
unsigned long SSL_CTX_get_options(const SSL_CTX *ctx);
unsigned long SSL_get_options(const SSL *s);
unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op);
unsigned long SSL_clear_options(SSL *s, unsigned long op);
unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
unsigned long SSL_set_options(SSL *s, unsigned long op);
# define SSL_CTX_set_mode(ctx,op) \
SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
# define SSL_CTX_clear_mode(ctx,op) \
SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_MODE,(op),NULL)
# define SSL_CTX_get_mode(ctx) \
SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,0,NULL)
# define SSL_clear_mode(ssl,op) \
SSL_ctrl((ssl),SSL_CTRL_CLEAR_MODE,(op),NULL)
# define SSL_set_mode(ssl,op) \
SSL_ctrl((ssl),SSL_CTRL_MODE,(op),NULL)
# define SSL_get_mode(ssl) \
SSL_ctrl((ssl),SSL_CTRL_MODE,0,NULL)
# define SSL_set_mtu(ssl, mtu) \
SSL_ctrl((ssl),SSL_CTRL_SET_MTU,(mtu),NULL)
# define DTLS_set_link_mtu(ssl, mtu) \
SSL_ctrl((ssl),DTLS_CTRL_SET_LINK_MTU,(mtu),NULL)
# define DTLS_get_link_min_mtu(ssl) \
SSL_ctrl((ssl),DTLS_CTRL_GET_LINK_MIN_MTU,0,NULL)
# define SSL_get_secure_renegotiation_support(ssl) \
SSL_ctrl((ssl), SSL_CTRL_GET_RI_SUPPORT, 0, NULL)
# ifndef OPENSSL_NO_HEARTBEATS
# define SSL_heartbeat(ssl) \
SSL_ctrl((ssl),SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT,0,NULL)
# endif
# define SSL_CTX_set_cert_flags(ctx,op) \
SSL_CTX_ctrl((ctx),SSL_CTRL_CERT_FLAGS,(op),NULL)
# define SSL_set_cert_flags(s,op) \
SSL_ctrl((s),SSL_CTRL_CERT_FLAGS,(op),NULL)
# define SSL_CTX_clear_cert_flags(ctx,op) \
SSL_CTX_ctrl((ctx),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
# define SSL_clear_cert_flags(s,op) \
SSL_ctrl((s),SSL_CTRL_CLEAR_CERT_FLAGS,(op),NULL)
void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
void (*cb) (int write_p, int version,
int content_type, const void *buf,
size_t len, SSL *ssl, void *arg));
void SSL_set_msg_callback(SSL *ssl,
void (*cb) (int write_p, int version,
int content_type, const void *buf,
size_t len, SSL *ssl, void *arg));
# define SSL_CTX_set_msg_callback_arg(ctx, arg) SSL_CTX_ctrl((ctx), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
# define SSL_set_msg_callback_arg(ssl, arg) SSL_ctrl((ssl), SSL_CTRL_SET_MSG_CALLBACK_ARG, 0, (arg))
# define SSL_get_extms_support(s) \
SSL_ctrl((s),SSL_CTRL_GET_EXTMS_SUPPORT,0,NULL)
# ifndef OPENSSL_NO_SRP
/* see tls_srp.c */
__owur int SSL_SRP_CTX_init(SSL *s);
__owur int SSL_CTX_SRP_CTX_init(SSL_CTX *ctx);
int SSL_SRP_CTX_free(SSL *ctx);
int SSL_CTX_SRP_CTX_free(SSL_CTX *ctx);
__owur int SSL_srp_server_param_with_username(SSL *s, int *ad);
__owur int SRP_Calc_A_param(SSL *s);
# endif
/* 100k max cert list */
# define SSL_MAX_CERT_LIST_DEFAULT 1024*100
# define SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (1024*20)
/*
* This callback type is used inside SSL_CTX, SSL, and in the functions that
* set them. It is used to override the generation of SSL/TLS session IDs in
* a server. Return value should be zero on an error, non-zero to proceed.
* Also, callbacks should themselves check if the id they generate is unique
* otherwise the SSL handshake will fail with an error - callbacks can do
* this using the 'ssl' value they're passed by;
* SSL_has_matching_session_id(ssl, id, *id_len) The length value passed in
* is set at the maximum size the session ID can be. In SSLv3/TLSv1 it is 32
* bytes. The callback can alter this length to be less if desired. It is
* also an error for the callback to set the size to zero.
*/
typedef int (*GEN_SESSION_CB) (SSL *ssl, unsigned char *id,
unsigned int *id_len);
# define SSL_SESS_CACHE_OFF 0x0000
# define SSL_SESS_CACHE_CLIENT 0x0001
# define SSL_SESS_CACHE_SERVER 0x0002
# define SSL_SESS_CACHE_BOTH (SSL_SESS_CACHE_CLIENT|SSL_SESS_CACHE_SERVER)
# define SSL_SESS_CACHE_NO_AUTO_CLEAR 0x0080
/* enough comments already ... see SSL_CTX_set_session_cache_mode(3) */
# define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP 0x0100
# define SSL_SESS_CACHE_NO_INTERNAL_STORE 0x0200
# define SSL_SESS_CACHE_NO_INTERNAL \
(SSL_SESS_CACHE_NO_INTERNAL_LOOKUP|SSL_SESS_CACHE_NO_INTERNAL_STORE)
LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx);
# define SSL_CTX_sess_number(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_NUMBER,0,NULL)
# define SSL_CTX_sess_connect(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT,0,NULL)
# define SSL_CTX_sess_connect_good(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_GOOD,0,NULL)
# define SSL_CTX_sess_connect_renegotiate(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CONNECT_RENEGOTIATE,0,NULL)
# define SSL_CTX_sess_accept(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT,0,NULL)
# define SSL_CTX_sess_accept_renegotiate(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_RENEGOTIATE,0,NULL)
# define SSL_CTX_sess_accept_good(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_ACCEPT_GOOD,0,NULL)
# define SSL_CTX_sess_hits(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_HIT,0,NULL)
# define SSL_CTX_sess_cb_hits(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CB_HIT,0,NULL)
# define SSL_CTX_sess_misses(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_MISSES,0,NULL)
# define SSL_CTX_sess_timeouts(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_TIMEOUTS,0,NULL)
# define SSL_CTX_sess_cache_full(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SESS_CACHE_FULL,0,NULL)
void SSL_CTX_sess_set_new_cb(SSL_CTX *ctx,
int (*new_session_cb) (struct ssl_st *ssl,
SSL_SESSION *sess));
int (*SSL_CTX_sess_get_new_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
SSL_SESSION *sess);
void SSL_CTX_sess_set_remove_cb(SSL_CTX *ctx,
void (*remove_session_cb) (struct ssl_ctx_st
*ctx,
SSL_SESSION *sess));
void (*SSL_CTX_sess_get_remove_cb(SSL_CTX *ctx)) (struct ssl_ctx_st *ctx,
SSL_SESSION *sess);
void SSL_CTX_sess_set_get_cb(SSL_CTX *ctx,
SSL_SESSION *(*get_session_cb) (struct ssl_st
*ssl,
const unsigned char
*data, int len,
int *copy));
SSL_SESSION *(*SSL_CTX_sess_get_get_cb(SSL_CTX *ctx)) (struct ssl_st *ssl,
const unsigned char *data,
int len, int *copy);
void SSL_CTX_set_info_callback(SSL_CTX *ctx,
void (*cb) (const SSL *ssl, int type, int val));
void (*SSL_CTX_get_info_callback(SSL_CTX *ctx)) (const SSL *ssl, int type,
int val);
void SSL_CTX_set_client_cert_cb(SSL_CTX *ctx,
int (*client_cert_cb) (SSL *ssl, X509 **x509,
EVP_PKEY **pkey));
int (*SSL_CTX_get_client_cert_cb(SSL_CTX *ctx)) (SSL *ssl, X509 **x509,
EVP_PKEY **pkey);
# ifndef OPENSSL_NO_ENGINE
__owur int SSL_CTX_set_client_cert_engine(SSL_CTX *ctx, ENGINE *e);
# endif
void SSL_CTX_set_cookie_generate_cb(SSL_CTX *ctx,
int (*app_gen_cookie_cb) (SSL *ssl,
unsigned char
*cookie,
unsigned int
*cookie_len));
void SSL_CTX_set_cookie_verify_cb(SSL_CTX *ctx,
int (*app_verify_cookie_cb) (SSL *ssl,
const unsigned
char *cookie,
unsigned int
cookie_len));
void SSL_CTX_set_stateless_cookie_generate_cb(
SSL_CTX *ctx,
int (*gen_stateless_cookie_cb) (SSL *ssl,
unsigned char *cookie,
size_t *cookie_len));
void SSL_CTX_set_stateless_cookie_verify_cb(
SSL_CTX *ctx,
int (*verify_stateless_cookie_cb) (SSL *ssl,
const unsigned char *cookie,
size_t cookie_len));
# ifndef OPENSSL_NO_NEXTPROTONEG
typedef int (*SSL_CTX_npn_advertised_cb_func)(SSL *ssl,
const unsigned char **out,
unsigned int *outlen,
void *arg);
void SSL_CTX_set_next_protos_advertised_cb(SSL_CTX *s,
SSL_CTX_npn_advertised_cb_func cb,
void *arg);
# define SSL_CTX_set_npn_advertised_cb SSL_CTX_set_next_protos_advertised_cb
typedef int (*SSL_CTX_npn_select_cb_func)(SSL *s,
unsigned char **out,
unsigned char *outlen,
const unsigned char *in,
unsigned int inlen,
void *arg);
void SSL_CTX_set_next_proto_select_cb(SSL_CTX *s,
SSL_CTX_npn_select_cb_func cb,
void *arg);
# define SSL_CTX_set_npn_select_cb SSL_CTX_set_next_proto_select_cb
void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
unsigned *len);
# define SSL_get0_npn_negotiated SSL_get0_next_proto_negotiated
# endif
__owur int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
const unsigned char *in, unsigned int inlen,
const unsigned char *client,
unsigned int client_len);
# define OPENSSL_NPN_UNSUPPORTED 0
# define OPENSSL_NPN_NEGOTIATED 1
# define OPENSSL_NPN_NO_OVERLAP 2
__owur int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
unsigned int protos_len);
__owur int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
unsigned int protos_len);
typedef int (*SSL_CTX_alpn_select_cb_func)(SSL *ssl,
const unsigned char **out,
unsigned char *outlen,
const unsigned char *in,
unsigned int inlen,
void *arg);
void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
SSL_CTX_alpn_select_cb_func cb,
void *arg);
void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
unsigned int *len);
# ifndef OPENSSL_NO_PSK
/*
* the maximum length of the buffer given to callbacks containing the
* resulting identity/psk
*/
# define PSK_MAX_IDENTITY_LEN 128
# define PSK_MAX_PSK_LEN 256
typedef unsigned int (*SSL_psk_client_cb_func)(SSL *ssl,
const char *hint,
char *identity,
unsigned int max_identity_len,
unsigned char *psk,
unsigned int max_psk_len);
void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb);
void SSL_set_psk_client_callback(SSL *ssl, SSL_psk_client_cb_func cb);
typedef unsigned int (*SSL_psk_server_cb_func)(SSL *ssl,
const char *identity,
unsigned char *psk,
unsigned int max_psk_len);
void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb);
void SSL_set_psk_server_callback(SSL *ssl, SSL_psk_server_cb_func cb);
__owur int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint);
__owur int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint);
const char *SSL_get_psk_identity_hint(const SSL *s);
const char *SSL_get_psk_identity(const SSL *s);
# endif
typedef int (*SSL_psk_find_session_cb_func)(SSL *ssl,
const unsigned char *identity,
size_t identity_len,
SSL_SESSION **sess);
typedef int (*SSL_psk_use_session_cb_func)(SSL *ssl, const EVP_MD *md,
const unsigned char **id,
size_t *idlen,
SSL_SESSION **sess);
void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb);
void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx,
SSL_psk_find_session_cb_func cb);
void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb);
void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx,
SSL_psk_use_session_cb_func cb);
/* Register callbacks to handle custom TLS Extensions for client or server. */
__owur int SSL_CTX_has_client_custom_ext(const SSL_CTX *ctx,
unsigned int ext_type);
__owur int SSL_CTX_add_client_custom_ext(SSL_CTX *ctx,
unsigned int ext_type,
custom_ext_add_cb add_cb,
custom_ext_free_cb free_cb,
void *add_arg,
custom_ext_parse_cb parse_cb,
void *parse_arg);
__owur int SSL_CTX_add_server_custom_ext(SSL_CTX *ctx,
unsigned int ext_type,
custom_ext_add_cb add_cb,
custom_ext_free_cb free_cb,
void *add_arg,
custom_ext_parse_cb parse_cb,
void *parse_arg);
__owur int SSL_CTX_add_custom_ext(SSL_CTX *ctx, unsigned int ext_type,
unsigned int context,
SSL_custom_ext_add_cb_ex add_cb,
SSL_custom_ext_free_cb_ex free_cb,
void *add_arg,
SSL_custom_ext_parse_cb_ex parse_cb,
void *parse_arg);
__owur int SSL_extension_supported(unsigned int ext_type);
# define SSL_NOTHING 1
# define SSL_WRITING 2
# define SSL_READING 3
# define SSL_X509_LOOKUP 4
# define SSL_ASYNC_PAUSED 5
# define SSL_ASYNC_NO_JOBS 6
# define SSL_CLIENT_HELLO_CB 7
/* These will only be used when doing non-blocking IO */
# define SSL_want_nothing(s) (SSL_want(s) == SSL_NOTHING)
# define SSL_want_read(s) (SSL_want(s) == SSL_READING)
# define SSL_want_write(s) (SSL_want(s) == SSL_WRITING)
# define SSL_want_x509_lookup(s) (SSL_want(s) == SSL_X509_LOOKUP)
# define SSL_want_async(s) (SSL_want(s) == SSL_ASYNC_PAUSED)
# define SSL_want_async_job(s) (SSL_want(s) == SSL_ASYNC_NO_JOBS)
# define SSL_want_client_hello_cb(s) (SSL_want(s) == SSL_CLIENT_HELLO_CB)
# define SSL_MAC_FLAG_READ_MAC_STREAM 1
# define SSL_MAC_FLAG_WRITE_MAC_STREAM 2
/*
* A callback for logging out TLS key material. This callback should log out
* |line| followed by a newline.
*/
typedef void (*SSL_CTX_keylog_cb_func)(const SSL *ssl, const char *line);
/*
* SSL_CTX_set_keylog_callback configures a callback to log key material. This
* is intended for debugging use with tools like Wireshark. The cb function
* should log line followed by a newline.
*/
void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb);
/*
* SSL_CTX_get_keylog_callback returns the callback configured by
* SSL_CTX_set_keylog_callback.
*/
SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx);
int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data);
uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx);
int SSL_set_max_early_data(SSL *s, uint32_t max_early_data);
uint32_t SSL_get_max_early_data(const SSL *s);
int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data);
uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx);
int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data);
uint32_t SSL_get_recv_max_early_data(const SSL *s);
#ifdef __cplusplus
}
#endif
# include <openssl/ssl2.h>
# include <openssl/ssl3.h>
# include <openssl/tls1.h> /* This is mostly sslv3 with a few tweaks */
# include <openssl/dtls1.h> /* Datagram TLS */
# include <openssl/srtp.h> /* Support for the use_srtp extension */
#ifdef __cplusplus
extern "C" {
#endif
/*
* These need to be after the above set of includes due to a compiler bug
* in VisualStudio 2015
*/
DEFINE_STACK_OF_CONST(SSL_CIPHER)
DEFINE_STACK_OF(SSL_COMP)
/* compatibility */
# define SSL_set_app_data(s,arg) (SSL_set_ex_data(s,0,(char *)(arg)))
# define SSL_get_app_data(s) (SSL_get_ex_data(s,0))
# define SSL_SESSION_set_app_data(s,a) (SSL_SESSION_set_ex_data(s,0, \
(char *)(a)))
# define SSL_SESSION_get_app_data(s) (SSL_SESSION_get_ex_data(s,0))
# define SSL_CTX_get_app_data(ctx) (SSL_CTX_get_ex_data(ctx,0))
# define SSL_CTX_set_app_data(ctx,arg) (SSL_CTX_set_ex_data(ctx,0, \
(char *)(arg)))
DEPRECATEDIN_1_1_0(void SSL_set_debug(SSL *s, int debug))
/* TLSv1.3 KeyUpdate message types */
/* -1 used so that this is an invalid value for the on-the-wire protocol */
#define SSL_KEY_UPDATE_NONE -1
/* Values as defined for the on-the-wire protocol */
#define SSL_KEY_UPDATE_NOT_REQUESTED 0
#define SSL_KEY_UPDATE_REQUESTED 1
/*
* The valid handshake states (one for each type message sent and one for each
* type of message received). There are also two "special" states:
* TLS = TLS or DTLS state
* DTLS = DTLS specific state
* CR/SR = Client Read/Server Read
* CW/SW = Client Write/Server Write
*
* The "special" states are:
* TLS_ST_BEFORE = No handshake has been initiated yet
* TLS_ST_OK = A handshake has been successfully completed
*/
typedef enum {
TLS_ST_BEFORE,
TLS_ST_OK,
DTLS_ST_CR_HELLO_VERIFY_REQUEST,
TLS_ST_CR_SRVR_HELLO,
TLS_ST_CR_CERT,
TLS_ST_CR_CERT_STATUS,
TLS_ST_CR_KEY_EXCH,
TLS_ST_CR_CERT_REQ,
TLS_ST_CR_SRVR_DONE,
TLS_ST_CR_SESSION_TICKET,
TLS_ST_CR_CHANGE,
TLS_ST_CR_FINISHED,
TLS_ST_CW_CLNT_HELLO,
TLS_ST_CW_CERT,
TLS_ST_CW_KEY_EXCH,
TLS_ST_CW_CERT_VRFY,
TLS_ST_CW_CHANGE,
TLS_ST_CW_NEXT_PROTO,
TLS_ST_CW_FINISHED,
TLS_ST_SW_HELLO_REQ,
TLS_ST_SR_CLNT_HELLO,
DTLS_ST_SW_HELLO_VERIFY_REQUEST,
TLS_ST_SW_SRVR_HELLO,
TLS_ST_SW_CERT,
TLS_ST_SW_KEY_EXCH,
TLS_ST_SW_CERT_REQ,
TLS_ST_SW_SRVR_DONE,
TLS_ST_SR_CERT,
TLS_ST_SR_KEY_EXCH,
TLS_ST_SR_CERT_VRFY,
TLS_ST_SR_NEXT_PROTO,
TLS_ST_SR_CHANGE,
TLS_ST_SR_FINISHED,
TLS_ST_SW_SESSION_TICKET,
TLS_ST_SW_CERT_STATUS,
TLS_ST_SW_CHANGE,
TLS_ST_SW_FINISHED,
TLS_ST_SW_ENCRYPTED_EXTENSIONS,
TLS_ST_CR_ENCRYPTED_EXTENSIONS,
TLS_ST_CR_CERT_VRFY,
TLS_ST_SW_CERT_VRFY,
TLS_ST_CR_HELLO_REQ,
TLS_ST_SW_KEY_UPDATE,
TLS_ST_CW_KEY_UPDATE,
TLS_ST_SR_KEY_UPDATE,
TLS_ST_CR_KEY_UPDATE,
TLS_ST_EARLY_DATA,
TLS_ST_PENDING_EARLY_DATA_END,
TLS_ST_CW_END_OF_EARLY_DATA,
TLS_ST_SR_END_OF_EARLY_DATA
} OSSL_HANDSHAKE_STATE;
/*
* Most of the following state values are no longer used and are defined to be
* the closest equivalent value in the current state machine code. Not all
* defines have an equivalent and are set to a dummy value (-1). SSL_ST_CONNECT
* and SSL_ST_ACCEPT are still in use in the definition of SSL_CB_ACCEPT_LOOP,
* SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP and SSL_CB_CONNECT_EXIT.
*/
# define SSL_ST_CONNECT 0x1000
# define SSL_ST_ACCEPT 0x2000
# define SSL_ST_MASK 0x0FFF
# define SSL_CB_LOOP 0x01
# define SSL_CB_EXIT 0x02
# define SSL_CB_READ 0x04
# define SSL_CB_WRITE 0x08
# define SSL_CB_ALERT 0x4000/* used in callback */
# define SSL_CB_READ_ALERT (SSL_CB_ALERT|SSL_CB_READ)
# define SSL_CB_WRITE_ALERT (SSL_CB_ALERT|SSL_CB_WRITE)
# define SSL_CB_ACCEPT_LOOP (SSL_ST_ACCEPT|SSL_CB_LOOP)
# define SSL_CB_ACCEPT_EXIT (SSL_ST_ACCEPT|SSL_CB_EXIT)
# define SSL_CB_CONNECT_LOOP (SSL_ST_CONNECT|SSL_CB_LOOP)
# define SSL_CB_CONNECT_EXIT (SSL_ST_CONNECT|SSL_CB_EXIT)
# define SSL_CB_HANDSHAKE_START 0x10
# define SSL_CB_HANDSHAKE_DONE 0x20
/* Is the SSL_connection established? */
# define SSL_in_connect_init(a) (SSL_in_init(a) && !SSL_is_server(a))
# define SSL_in_accept_init(a) (SSL_in_init(a) && SSL_is_server(a))
int SSL_in_init(const SSL *s);
int SSL_in_before(const SSL *s);
int SSL_is_init_finished(const SSL *s);
/*
* The following 3 states are kept in ssl->rlayer.rstate when reads fail, you
* should not need these
*/
# define SSL_ST_READ_HEADER 0xF0
# define SSL_ST_READ_BODY 0xF1
# define SSL_ST_READ_DONE 0xF2
/*-
* Obtain latest Finished message
* -- that we sent (SSL_get_finished)
* -- that we expected from peer (SSL_get_peer_finished).
* Returns length (0 == no Finished so far), copies up to 'count' bytes.
*/
size_t SSL_get_finished(const SSL *s, void *buf, size_t count);
size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
/*
* use either SSL_VERIFY_NONE or SSL_VERIFY_PEER, the last 3 options are
* 'ored' with SSL_VERIFY_PEER if they are desired
*/
# define SSL_VERIFY_NONE 0x00
# define SSL_VERIFY_PEER 0x01
# define SSL_VERIFY_FAIL_IF_NO_PEER_CERT 0x02
# define SSL_VERIFY_CLIENT_ONCE 0x04
# define SSL_VERIFY_POST_HANDSHAKE 0x08
# if OPENSSL_API_COMPAT < 0x10100000L
# define OpenSSL_add_ssl_algorithms() SSL_library_init()
# define SSLeay_add_ssl_algorithms() SSL_library_init()
# endif
/* More backward compatibility */
# define SSL_get_cipher(s) \
SSL_CIPHER_get_name(SSL_get_current_cipher(s))
# define SSL_get_cipher_bits(s,np) \
SSL_CIPHER_get_bits(SSL_get_current_cipher(s),np)
# define SSL_get_cipher_version(s) \
SSL_CIPHER_get_version(SSL_get_current_cipher(s))
# define SSL_get_cipher_name(s) \
SSL_CIPHER_get_name(SSL_get_current_cipher(s))
# define SSL_get_time(a) SSL_SESSION_get_time(a)
# define SSL_set_time(a,b) SSL_SESSION_set_time((a),(b))
# define SSL_get_timeout(a) SSL_SESSION_get_timeout(a)
# define SSL_set_timeout(a,b) SSL_SESSION_set_timeout((a),(b))
# define d2i_SSL_SESSION_bio(bp,s_id) ASN1_d2i_bio_of(SSL_SESSION,SSL_SESSION_new,d2i_SSL_SESSION,bp,s_id)
# define i2d_SSL_SESSION_bio(bp,s_id) ASN1_i2d_bio_of(SSL_SESSION,i2d_SSL_SESSION,bp,s_id)
DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
# define SSL_AD_REASON_OFFSET 1000/* offset to get SSL_R_... value
* from SSL_AD_... */
/* These alert types are for SSLv3 and TLSv1 */
# define SSL_AD_CLOSE_NOTIFY SSL3_AD_CLOSE_NOTIFY
/* fatal */
# define SSL_AD_UNEXPECTED_MESSAGE SSL3_AD_UNEXPECTED_MESSAGE
/* fatal */
# define SSL_AD_BAD_RECORD_MAC SSL3_AD_BAD_RECORD_MAC
# define SSL_AD_DECRYPTION_FAILED TLS1_AD_DECRYPTION_FAILED
# define SSL_AD_RECORD_OVERFLOW TLS1_AD_RECORD_OVERFLOW
/* fatal */
# define SSL_AD_DECOMPRESSION_FAILURE SSL3_AD_DECOMPRESSION_FAILURE
/* fatal */
# define SSL_AD_HANDSHAKE_FAILURE SSL3_AD_HANDSHAKE_FAILURE
/* Not for TLS */
# define SSL_AD_NO_CERTIFICATE SSL3_AD_NO_CERTIFICATE
# define SSL_AD_BAD_CERTIFICATE SSL3_AD_BAD_CERTIFICATE
# define SSL_AD_UNSUPPORTED_CERTIFICATE SSL3_AD_UNSUPPORTED_CERTIFICATE
# define SSL_AD_CERTIFICATE_REVOKED SSL3_AD_CERTIFICATE_REVOKED
# define SSL_AD_CERTIFICATE_EXPIRED SSL3_AD_CERTIFICATE_EXPIRED
# define SSL_AD_CERTIFICATE_UNKNOWN SSL3_AD_CERTIFICATE_UNKNOWN
/* fatal */
# define SSL_AD_ILLEGAL_PARAMETER SSL3_AD_ILLEGAL_PARAMETER
/* fatal */
# define SSL_AD_UNKNOWN_CA TLS1_AD_UNKNOWN_CA
/* fatal */
# define SSL_AD_ACCESS_DENIED TLS1_AD_ACCESS_DENIED
/* fatal */
# define SSL_AD_DECODE_ERROR TLS1_AD_DECODE_ERROR
# define SSL_AD_DECRYPT_ERROR TLS1_AD_DECRYPT_ERROR
/* fatal */
# define SSL_AD_EXPORT_RESTRICTION TLS1_AD_EXPORT_RESTRICTION
/* fatal */
# define SSL_AD_PROTOCOL_VERSION TLS1_AD_PROTOCOL_VERSION
/* fatal */
# define SSL_AD_INSUFFICIENT_SECURITY TLS1_AD_INSUFFICIENT_SECURITY
/* fatal */
# define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR
# define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
# define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
# define SSL_AD_MISSING_EXTENSION TLS13_AD_MISSING_EXTENSION
# define SSL_AD_CERTIFICATE_REQUIRED TLS13_AD_CERTIFICATE_REQUIRED
# define SSL_AD_UNSUPPORTED_EXTENSION TLS1_AD_UNSUPPORTED_EXTENSION
# define SSL_AD_CERTIFICATE_UNOBTAINABLE TLS1_AD_CERTIFICATE_UNOBTAINABLE
# define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
# define SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE TLS1_AD_BAD_CERTIFICATE_STATUS_RESPONSE
# define SSL_AD_BAD_CERTIFICATE_HASH_VALUE TLS1_AD_BAD_CERTIFICATE_HASH_VALUE
/* fatal */
# define SSL_AD_UNKNOWN_PSK_IDENTITY TLS1_AD_UNKNOWN_PSK_IDENTITY
/* fatal */
# define SSL_AD_INAPPROPRIATE_FALLBACK TLS1_AD_INAPPROPRIATE_FALLBACK
# define SSL_AD_NO_APPLICATION_PROTOCOL TLS1_AD_NO_APPLICATION_PROTOCOL
# define SSL_ERROR_NONE 0
# define SSL_ERROR_SSL 1
# define SSL_ERROR_WANT_READ 2
# define SSL_ERROR_WANT_WRITE 3
# define SSL_ERROR_WANT_X509_LOOKUP 4
# define SSL_ERROR_SYSCALL 5/* look at error stack/return
* value/errno */
# define SSL_ERROR_ZERO_RETURN 6
# define SSL_ERROR_WANT_CONNECT 7
# define SSL_ERROR_WANT_ACCEPT 8
# define SSL_ERROR_WANT_ASYNC 9
# define SSL_ERROR_WANT_ASYNC_JOB 10
# define SSL_ERROR_WANT_CLIENT_HELLO_CB 11
# define SSL_CTRL_SET_TMP_DH 3
# define SSL_CTRL_SET_TMP_ECDH 4
# define SSL_CTRL_SET_TMP_DH_CB 6
# define SSL_CTRL_GET_CLIENT_CERT_REQUEST 9
# define SSL_CTRL_GET_NUM_RENEGOTIATIONS 10
# define SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS 11
# define SSL_CTRL_GET_TOTAL_RENEGOTIATIONS 12
# define SSL_CTRL_GET_FLAGS 13
# define SSL_CTRL_EXTRA_CHAIN_CERT 14
# define SSL_CTRL_SET_MSG_CALLBACK 15
# define SSL_CTRL_SET_MSG_CALLBACK_ARG 16
/* only applies to datagram connections */
# define SSL_CTRL_SET_MTU 17
/* Stats */
# define SSL_CTRL_SESS_NUMBER 20
# define SSL_CTRL_SESS_CONNECT 21
# define SSL_CTRL_SESS_CONNECT_GOOD 22
# define SSL_CTRL_SESS_CONNECT_RENEGOTIATE 23
# define SSL_CTRL_SESS_ACCEPT 24
# define SSL_CTRL_SESS_ACCEPT_GOOD 25
# define SSL_CTRL_SESS_ACCEPT_RENEGOTIATE 26
# define SSL_CTRL_SESS_HIT 27
# define SSL_CTRL_SESS_CB_HIT 28
# define SSL_CTRL_SESS_MISSES 29
# define SSL_CTRL_SESS_TIMEOUTS 30
# define SSL_CTRL_SESS_CACHE_FULL 31
# define SSL_CTRL_MODE 33
# define SSL_CTRL_GET_READ_AHEAD 40
# define SSL_CTRL_SET_READ_AHEAD 41
# define SSL_CTRL_SET_SESS_CACHE_SIZE 42
# define SSL_CTRL_GET_SESS_CACHE_SIZE 43
# define SSL_CTRL_SET_SESS_CACHE_MODE 44
# define SSL_CTRL_GET_SESS_CACHE_MODE 45
# define SSL_CTRL_GET_MAX_CERT_LIST 50
# define SSL_CTRL_SET_MAX_CERT_LIST 51
# define SSL_CTRL_SET_MAX_SEND_FRAGMENT 52
/* see tls1.h for macros based on these */
# define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
# define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
# define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
# define SSL_CTRL_SET_TLSEXT_DEBUG_CB 56
# define SSL_CTRL_SET_TLSEXT_DEBUG_ARG 57
# define SSL_CTRL_GET_TLSEXT_TICKET_KEYS 58
# define SSL_CTRL_SET_TLSEXT_TICKET_KEYS 59
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT 60 */
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB 61 */
/*# define SSL_CTRL_SET_TLSEXT_OPAQUE_PRF_INPUT_CB_ARG 62 */
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_TYPE 65
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_EXTS 66
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_EXTS 67
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_IDS 68
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_IDS 69
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP 70
# define SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP 71
# define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72
# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME_CB 75
# define SSL_CTRL_SET_SRP_VERIFY_PARAM_CB 76
# define SSL_CTRL_SET_SRP_GIVE_CLIENT_PWD_CB 77
# define SSL_CTRL_SET_SRP_ARG 78
# define SSL_CTRL_SET_TLS_EXT_SRP_USERNAME 79
# define SSL_CTRL_SET_TLS_EXT_SRP_STRENGTH 80
# define SSL_CTRL_SET_TLS_EXT_SRP_PASSWORD 81
# ifndef OPENSSL_NO_HEARTBEATS
# define SSL_CTRL_DTLS_EXT_SEND_HEARTBEAT 85
# define SSL_CTRL_GET_DTLS_EXT_HEARTBEAT_PENDING 86
# define SSL_CTRL_SET_DTLS_EXT_HEARTBEAT_NO_REQUESTS 87
# endif
# define DTLS_CTRL_GET_TIMEOUT 73
# define DTLS_CTRL_HANDLE_TIMEOUT 74
# define SSL_CTRL_GET_RI_SUPPORT 76
# define SSL_CTRL_CLEAR_MODE 78
# define SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB 79
# define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82
# define SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS 83
# define SSL_CTRL_CHAIN 88
# define SSL_CTRL_CHAIN_CERT 89
# define SSL_CTRL_GET_GROUPS 90
# define SSL_CTRL_SET_GROUPS 91
# define SSL_CTRL_SET_GROUPS_LIST 92
# define SSL_CTRL_GET_SHARED_GROUP 93
# define SSL_CTRL_SET_SIGALGS 97
# define SSL_CTRL_SET_SIGALGS_LIST 98
# define SSL_CTRL_CERT_FLAGS 99
# define SSL_CTRL_CLEAR_CERT_FLAGS 100
# define SSL_CTRL_SET_CLIENT_SIGALGS 101
# define SSL_CTRL_SET_CLIENT_SIGALGS_LIST 102
# define SSL_CTRL_GET_CLIENT_CERT_TYPES 103
# define SSL_CTRL_SET_CLIENT_CERT_TYPES 104
# define SSL_CTRL_BUILD_CERT_CHAIN 105
# define SSL_CTRL_SET_VERIFY_CERT_STORE 106
# define SSL_CTRL_SET_CHAIN_CERT_STORE 107
# define SSL_CTRL_GET_PEER_SIGNATURE_NID 108
# define SSL_CTRL_GET_PEER_TMP_KEY 109
# define SSL_CTRL_GET_RAW_CIPHERLIST 110
# define SSL_CTRL_GET_EC_POINT_FORMATS 111
# define SSL_CTRL_GET_CHAIN_CERTS 115
# define SSL_CTRL_SELECT_CURRENT_CERT 116
# define SSL_CTRL_SET_CURRENT_CERT 117
# define SSL_CTRL_SET_DH_AUTO 118
# define DTLS_CTRL_SET_LINK_MTU 120
# define DTLS_CTRL_GET_LINK_MIN_MTU 121
# define SSL_CTRL_GET_EXTMS_SUPPORT 122
# define SSL_CTRL_SET_MIN_PROTO_VERSION 123
# define SSL_CTRL_SET_MAX_PROTO_VERSION 124
# define SSL_CTRL_SET_SPLIT_SEND_FRAGMENT 125
# define SSL_CTRL_SET_MAX_PIPELINES 126
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_TYPE 127
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB 128
# define SSL_CTRL_GET_TLSEXT_STATUS_REQ_CB_ARG 129
# define SSL_CTRL_GET_MIN_PROTO_VERSION 130
# define SSL_CTRL_GET_MAX_PROTO_VERSION 131
# define SSL_CTRL_GET_SIGNATURE_NID 132
# define SSL_CTRL_GET_TMP_KEY 133
# define SSL_CERT_SET_FIRST 1
# define SSL_CERT_SET_NEXT 2
# define SSL_CERT_SET_SERVER 3
# define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)(arg))
# define DTLSv1_handle_timeout(ssl) \
SSL_ctrl(ssl,DTLS_CTRL_HANDLE_TIMEOUT,0, NULL)
# define SSL_num_renegotiations(ssl) \
SSL_ctrl((ssl),SSL_CTRL_GET_NUM_RENEGOTIATIONS,0,NULL)
# define SSL_clear_num_renegotiations(ssl) \
SSL_ctrl((ssl),SSL_CTRL_CLEAR_NUM_RENEGOTIATIONS,0,NULL)
# define SSL_total_renegotiations(ssl) \
SSL_ctrl((ssl),SSL_CTRL_GET_TOTAL_RENEGOTIATIONS,0,NULL)
# define SSL_CTX_set_tmp_dh(ctx,dh) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
# define SSL_CTX_set_tmp_ecdh(ctx,ecdh) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
# define SSL_CTX_set_dh_auto(ctx, onoff) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
# define SSL_set_dh_auto(s, onoff) \
SSL_ctrl(s,SSL_CTRL_SET_DH_AUTO,onoff,NULL)
# define SSL_set_tmp_dh(ssl,dh) \
SSL_ctrl(ssl,SSL_CTRL_SET_TMP_DH,0,(char *)(dh))
# define SSL_set_tmp_ecdh(ssl,ecdh) \
SSL_ctrl(ssl,SSL_CTRL_SET_TMP_ECDH,0,(char *)(ecdh))
# define SSL_CTX_add_extra_chain_cert(ctx,x509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)(x509))
# define SSL_CTX_get_extra_chain_certs(ctx,px509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,0,px509)
# define SSL_CTX_get_extra_chain_certs_only(ctx,px509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_EXTRA_CHAIN_CERTS,1,px509)
# define SSL_CTX_clear_extra_chain_certs(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_CLEAR_EXTRA_CHAIN_CERTS,0,NULL)
# define SSL_CTX_set0_chain(ctx,sk) \
SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk))
# define SSL_CTX_set1_chain(ctx,sk) \
SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk))
# define SSL_CTX_add0_chain_cert(ctx,x509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
# define SSL_CTX_add1_chain_cert(ctx,x509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
# define SSL_CTX_get0_chain_certs(ctx,px509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
# define SSL_CTX_clear_chain_certs(ctx) \
SSL_CTX_set0_chain(ctx,NULL)
# define SSL_CTX_build_cert_chain(ctx, flags) \
SSL_CTX_ctrl(ctx,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
# define SSL_CTX_select_current_cert(ctx,x509) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
# define SSL_CTX_set_current_cert(ctx, op) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
# define SSL_CTX_set0_verify_cert_store(ctx,st) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set1_verify_cert_store(ctx,st) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
# define SSL_CTX_set0_chain_cert_store(ctx,st) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_CTX_set1_chain_cert_store(ctx,st) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
# define SSL_set0_chain(ctx,sk) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN,0,(char *)(sk))
# define SSL_set1_chain(ctx,sk) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN,1,(char *)(sk))
# define SSL_add0_chain_cert(ctx,x509) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)(x509))
# define SSL_add1_chain_cert(ctx,x509) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)(x509))
# define SSL_get0_chain_certs(ctx,px509) \
SSL_ctrl(ctx,SSL_CTRL_GET_CHAIN_CERTS,0,px509)
# define SSL_clear_chain_certs(ctx) \
SSL_set0_chain(ctx,NULL)
# define SSL_build_cert_chain(s, flags) \
SSL_ctrl(s,SSL_CTRL_BUILD_CERT_CHAIN, flags, NULL)
# define SSL_select_current_cert(ctx,x509) \
SSL_ctrl(ctx,SSL_CTRL_SELECT_CURRENT_CERT,0,(char *)(x509))
# define SSL_set_current_cert(ctx,op) \
SSL_ctrl(ctx,SSL_CTRL_SET_CURRENT_CERT, op, NULL)
# define SSL_set0_verify_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,0,(char *)(st))
# define SSL_set1_verify_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_VERIFY_CERT_STORE,1,(char *)(st))
# define SSL_set0_chain_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,0,(char *)(st))
# define SSL_set1_chain_cert_store(s,st) \
SSL_ctrl(s,SSL_CTRL_SET_CHAIN_CERT_STORE,1,(char *)(st))
# define SSL_get1_groups(ctx, s) \
SSL_ctrl(ctx,SSL_CTRL_GET_GROUPS,0,(char *)(s))
# define SSL_CTX_set1_groups(ctx, glist, glistlen) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist))
# define SSL_CTX_set1_groups_list(ctx, s) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s))
# define SSL_set1_groups(ctx, glist, glistlen) \
SSL_ctrl(ctx,SSL_CTRL_SET_GROUPS,glistlen,(char *)(glist))
# define SSL_set1_groups_list(ctx, s) \
SSL_ctrl(ctx,SSL_CTRL_SET_GROUPS_LIST,0,(char *)(s))
# define SSL_get_shared_group(s, n) \
SSL_ctrl(s,SSL_CTRL_GET_SHARED_GROUP,n,NULL)
# define SSL_CTX_set1_sigalgs(ctx, slist, slistlen) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
# define SSL_CTX_set1_sigalgs_list(ctx, s) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s))
# define SSL_set1_sigalgs(ctx, slist, slistlen) \
SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS,slistlen,(int *)(slist))
# define SSL_set1_sigalgs_list(ctx, s) \
SSL_ctrl(ctx,SSL_CTRL_SET_SIGALGS_LIST,0,(char *)(s))
# define SSL_CTX_set1_client_sigalgs(ctx, slist, slistlen) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,slistlen,(int *)(slist))
# define SSL_CTX_set1_client_sigalgs_list(ctx, s) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s))
# define SSL_set1_client_sigalgs(ctx, slist, slistlen) \
SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS,clistlen,(int *)(slist))
# define SSL_set1_client_sigalgs_list(ctx, s) \
SSL_ctrl(ctx,SSL_CTRL_SET_CLIENT_SIGALGS_LIST,0,(char *)(s))
# define SSL_get0_certificate_types(s, clist) \
SSL_ctrl(s, SSL_CTRL_GET_CLIENT_CERT_TYPES, 0, (char *)(clist))
# define SSL_CTX_set1_client_certificate_types(ctx, clist, clistlen) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen, \
(char *)(clist))
# define SSL_set1_client_certificate_types(s, clist, clistlen) \
SSL_ctrl(s,SSL_CTRL_SET_CLIENT_CERT_TYPES,clistlen,(char *)(clist))
# define SSL_get_signature_nid(s, pn) \
SSL_ctrl(s,SSL_CTRL_GET_SIGNATURE_NID,0,pn)
# define SSL_get_peer_signature_nid(s, pn) \
SSL_ctrl(s,SSL_CTRL_GET_PEER_SIGNATURE_NID,0,pn)
# define SSL_get_peer_tmp_key(s, pk) \
SSL_ctrl(s,SSL_CTRL_GET_PEER_TMP_KEY,0,pk)
# define SSL_get_tmp_key(s, pk) \
SSL_ctrl(s,SSL_CTRL_GET_TMP_KEY,0,pk)
# define SSL_get0_raw_cipherlist(s, plst) \
SSL_ctrl(s,SSL_CTRL_GET_RAW_CIPHERLIST,0,plst)
# define SSL_get0_ec_point_formats(s, plst) \
SSL_ctrl(s,SSL_CTRL_GET_EC_POINT_FORMATS,0,plst)
# define SSL_CTX_set_min_proto_version(ctx, version) \
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
# define SSL_CTX_set_max_proto_version(ctx, version) \
SSL_CTX_ctrl(ctx, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
# define SSL_CTX_get_min_proto_version(ctx) \
SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
# define SSL_CTX_get_max_proto_version(ctx) \
SSL_CTX_ctrl(ctx, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
# define SSL_set_min_proto_version(s, version) \
SSL_ctrl(s, SSL_CTRL_SET_MIN_PROTO_VERSION, version, NULL)
# define SSL_set_max_proto_version(s, version) \
SSL_ctrl(s, SSL_CTRL_SET_MAX_PROTO_VERSION, version, NULL)
# define SSL_get_min_proto_version(s) \
SSL_ctrl(s, SSL_CTRL_GET_MIN_PROTO_VERSION, 0, NULL)
# define SSL_get_max_proto_version(s) \
SSL_ctrl(s, SSL_CTRL_GET_MAX_PROTO_VERSION, 0, NULL)
/* Backwards compatibility, original 1.1.0 names */
# define SSL_CTRL_GET_SERVER_TMP_KEY \
SSL_CTRL_GET_PEER_TMP_KEY
# define SSL_get_server_tmp_key(s, pk) \
SSL_get_peer_tmp_key(s, pk)
/*
* The following symbol names are old and obsolete. They are kept
* for compatibility reasons only and should not be used anymore.
*/
# define SSL_CTRL_GET_CURVES SSL_CTRL_GET_GROUPS
# define SSL_CTRL_SET_CURVES SSL_CTRL_SET_GROUPS
# define SSL_CTRL_SET_CURVES_LIST SSL_CTRL_SET_GROUPS_LIST
# define SSL_CTRL_GET_SHARED_CURVE SSL_CTRL_GET_SHARED_GROUP
# define SSL_get1_curves SSL_get1_groups
# define SSL_CTX_set1_curves SSL_CTX_set1_groups
# define SSL_CTX_set1_curves_list SSL_CTX_set1_groups_list
# define SSL_set1_curves SSL_set1_groups
# define SSL_set1_curves_list SSL_set1_groups_list
# define SSL_get_shared_curve SSL_get_shared_group
# if OPENSSL_API_COMPAT < 0x10100000L
/* Provide some compatibility macros for removed functionality. */
# define SSL_CTX_need_tmp_RSA(ctx) 0
# define SSL_CTX_set_tmp_rsa(ctx,rsa) 1
# define SSL_need_tmp_RSA(ssl) 0
# define SSL_set_tmp_rsa(ssl,rsa) 1
# define SSL_CTX_set_ecdh_auto(dummy, onoff) ((onoff) != 0)
# define SSL_set_ecdh_auto(dummy, onoff) ((onoff) != 0)
/*
* We "pretend" to call the callback to avoid warnings about unused static
* functions.
*/
# define SSL_CTX_set_tmp_rsa_callback(ctx, cb) while(0) (cb)(NULL, 0, 0)
# define SSL_set_tmp_rsa_callback(ssl, cb) while(0) (cb)(NULL, 0, 0)
# endif
__owur const BIO_METHOD *BIO_f_ssl(void);
__owur BIO *BIO_new_ssl(SSL_CTX *ctx, int client);
__owur BIO *BIO_new_ssl_connect(SSL_CTX *ctx);
__owur BIO *BIO_new_buffer_ssl_connect(SSL_CTX *ctx);
__owur int BIO_ssl_copy_session_id(BIO *to, BIO *from);
void BIO_ssl_shutdown(BIO *ssl_bio);
__owur int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
__owur SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
int SSL_CTX_up_ref(SSL_CTX *ctx);
void SSL_CTX_free(SSL_CTX *);
__owur long SSL_CTX_set_timeout(SSL_CTX *ctx, long t);
__owur long SSL_CTX_get_timeout(const SSL_CTX *ctx);
__owur X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *);
void SSL_CTX_set_cert_store(SSL_CTX *, X509_STORE *);
void SSL_CTX_set1_cert_store(SSL_CTX *, X509_STORE *);
__owur int SSL_want(const SSL *s);
__owur int SSL_clear(SSL *s);
void SSL_CTX_flush_sessions(SSL_CTX *ctx, long tm);
__owur const SSL_CIPHER *SSL_get_current_cipher(const SSL *s);
__owur const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s);
__owur int SSL_CIPHER_get_bits(const SSL_CIPHER *c, int *alg_bits);
__owur const char *SSL_CIPHER_get_version(const SSL_CIPHER *c);
__owur const char *SSL_CIPHER_get_name(const SSL_CIPHER *c);
__owur const char *SSL_CIPHER_standard_name(const SSL_CIPHER *c);
__owur const char *OPENSSL_cipher_name(const char *rfc_name);
__owur uint32_t SSL_CIPHER_get_id(const SSL_CIPHER *c);
__owur uint16_t SSL_CIPHER_get_protocol_id(const SSL_CIPHER *c);
__owur int SSL_CIPHER_get_kx_nid(const SSL_CIPHER *c);
__owur int SSL_CIPHER_get_auth_nid(const SSL_CIPHER *c);
__owur const EVP_MD *SSL_CIPHER_get_handshake_digest(const SSL_CIPHER *c);
__owur int SSL_CIPHER_is_aead(const SSL_CIPHER *c);
__owur int SSL_get_fd(const SSL *s);
__owur int SSL_get_rfd(const SSL *s);
__owur int SSL_get_wfd(const SSL *s);
__owur const char *SSL_get_cipher_list(const SSL *s, int n);
__owur char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size);
__owur int SSL_get_read_ahead(const SSL *s);
__owur int SSL_pending(const SSL *s);
__owur int SSL_has_pending(const SSL *s);
# ifndef OPENSSL_NO_SOCK
__owur int SSL_set_fd(SSL *s, int fd);
__owur int SSL_set_rfd(SSL *s, int fd);
__owur int SSL_set_wfd(SSL *s, int fd);
# endif
void SSL_set0_rbio(SSL *s, BIO *rbio);
void SSL_set0_wbio(SSL *s, BIO *wbio);
void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);
__owur BIO *SSL_get_rbio(const SSL *s);
__owur BIO *SSL_get_wbio(const SSL *s);
__owur int SSL_set_cipher_list(SSL *s, const char *str);
__owur int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
__owur int SSL_set_ciphersuites(SSL *s, const char *str);
void SSL_set_read_ahead(SSL *s, int yes);
__owur int SSL_get_verify_mode(const SSL *s);
__owur int SSL_get_verify_depth(const SSL *s);
__owur SSL_verify_cb SSL_get_verify_callback(const SSL *s);
void SSL_set_verify(SSL *s, int mode, SSL_verify_cb callback);
void SSL_set_verify_depth(SSL *s, int depth);
void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg);
# ifndef OPENSSL_NO_RSA
__owur int SSL_use_RSAPrivateKey(SSL *ssl, RSA *rsa);
__owur int SSL_use_RSAPrivateKey_ASN1(SSL *ssl, const unsigned char *d,
long len);
# endif
__owur int SSL_use_PrivateKey(SSL *ssl, EVP_PKEY *pkey);
__owur int SSL_use_PrivateKey_ASN1(int pk, SSL *ssl, const unsigned char *d,
long len);
__owur int SSL_use_certificate(SSL *ssl, X509 *x);
__owur int SSL_use_certificate_ASN1(SSL *ssl, const unsigned char *d, int len);
__owur int SSL_use_cert_and_key(SSL *ssl, X509 *x509, EVP_PKEY *privatekey,
STACK_OF(X509) *chain, int override);
/* serverinfo file format versions */
# define SSL_SERVERINFOV1 1
# define SSL_SERVERINFOV2 2
/* Set serverinfo data for the current active cert. */
__owur int SSL_CTX_use_serverinfo(SSL_CTX *ctx, const unsigned char *serverinfo,
size_t serverinfo_length);
__owur int SSL_CTX_use_serverinfo_ex(SSL_CTX *ctx, unsigned int version,
const unsigned char *serverinfo,
size_t serverinfo_length);
__owur int SSL_CTX_use_serverinfo_file(SSL_CTX *ctx, const char *file);
#ifndef OPENSSL_NO_RSA
__owur int SSL_use_RSAPrivateKey_file(SSL *ssl, const char *file, int type);
#endif
__owur int SSL_use_PrivateKey_file(SSL *ssl, const char *file, int type);
__owur int SSL_use_certificate_file(SSL *ssl, const char *file, int type);
#ifndef OPENSSL_NO_RSA
__owur int SSL_CTX_use_RSAPrivateKey_file(SSL_CTX *ctx, const char *file,
int type);
#endif
__owur int SSL_CTX_use_PrivateKey_file(SSL_CTX *ctx, const char *file,
int type);
__owur int SSL_CTX_use_certificate_file(SSL_CTX *ctx, const char *file,
int type);
/* PEM type */
__owur int SSL_CTX_use_certificate_chain_file(SSL_CTX *ctx, const char *file);
__owur int SSL_use_certificate_chain_file(SSL *ssl, const char *file);
__owur STACK_OF(X509_NAME) *SSL_load_client_CA_file(const char *file);
__owur int SSL_add_file_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
const char *file);
int SSL_add_dir_cert_subjects_to_stack(STACK_OF(X509_NAME) *stackCAs,
const char *dir);
# if OPENSSL_API_COMPAT < 0x10100000L
# define SSL_load_error_strings() \
OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
| OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
# endif
__owur const char *SSL_state_string(const SSL *s);
__owur const char *SSL_rstate_string(const SSL *s);
__owur const char *SSL_state_string_long(const SSL *s);
__owur const char *SSL_rstate_string_long(const SSL *s);
__owur long SSL_SESSION_get_time(const SSL_SESSION *s);
__owur long SSL_SESSION_set_time(SSL_SESSION *s, long t);
__owur long SSL_SESSION_get_timeout(const SSL_SESSION *s);
__owur long SSL_SESSION_set_timeout(SSL_SESSION *s, long t);
__owur int SSL_SESSION_get_protocol_version(const SSL_SESSION *s);
__owur int SSL_SESSION_set_protocol_version(SSL_SESSION *s, int version);
__owur const char *SSL_SESSION_get0_hostname(const SSL_SESSION *s);
__owur int SSL_SESSION_set1_hostname(SSL_SESSION *s, const char *hostname);
void SSL_SESSION_get0_alpn_selected(const SSL_SESSION *s,
const unsigned char **alpn,
size_t *len);
__owur int SSL_SESSION_set1_alpn_selected(SSL_SESSION *s,
const unsigned char *alpn,
size_t len);
__owur const SSL_CIPHER *SSL_SESSION_get0_cipher(const SSL_SESSION *s);
__owur int SSL_SESSION_set_cipher(SSL_SESSION *s, const SSL_CIPHER *cipher);
__owur int SSL_SESSION_has_ticket(const SSL_SESSION *s);
__owur unsigned long SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *s);
void SSL_SESSION_get0_ticket(const SSL_SESSION *s, const unsigned char **tick,
size_t *len);
__owur uint32_t SSL_SESSION_get_max_early_data(const SSL_SESSION *s);
__owur int SSL_SESSION_set_max_early_data(SSL_SESSION *s,
uint32_t max_early_data);
__owur int SSL_copy_session_id(SSL *to, const SSL *from);
__owur X509 *SSL_SESSION_get0_peer(SSL_SESSION *s);
__owur int SSL_SESSION_set1_id_context(SSL_SESSION *s,
const unsigned char *sid_ctx,
unsigned int sid_ctx_len);
__owur int SSL_SESSION_set1_id(SSL_SESSION *s, const unsigned char *sid,
unsigned int sid_len);
__owur int SSL_SESSION_is_resumable(const SSL_SESSION *s);
__owur SSL_SESSION *SSL_SESSION_new(void);
__owur SSL_SESSION *SSL_SESSION_dup(SSL_SESSION *src);
const unsigned char *SSL_SESSION_get_id(const SSL_SESSION *s,
unsigned int *len);
const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *s,
unsigned int *len);
__owur unsigned int SSL_SESSION_get_compress_id(const SSL_SESSION *s);
# ifndef OPENSSL_NO_STDIO
int SSL_SESSION_print_fp(FILE *fp, const SSL_SESSION *ses);
# endif
int SSL_SESSION_print(BIO *fp, const SSL_SESSION *ses);
int SSL_SESSION_print_keylog(BIO *bp, const SSL_SESSION *x);
int SSL_SESSION_up_ref(SSL_SESSION *ses);
void SSL_SESSION_free(SSL_SESSION *ses);
__owur int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
__owur int SSL_set_session(SSL *to, SSL_SESSION *session);
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session);
int SSL_CTX_remove_session(SSL_CTX *ctx, SSL_SESSION *session);
__owur int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb);
__owur int SSL_set_generate_session_id(SSL *s, GEN_SESSION_CB cb);
__owur int SSL_has_matching_session_id(const SSL *s,
const unsigned char *id,
unsigned int id_len);
SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
long length);
# ifdef HEADER_X509_H
__owur X509 *SSL_get_peer_certificate(const SSL *s);
# endif
__owur STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s);
__owur int SSL_CTX_get_verify_mode(const SSL_CTX *ctx);
__owur int SSL_CTX_get_verify_depth(const SSL_CTX *ctx);
__owur SSL_verify_cb SSL_CTX_get_verify_callback(const SSL_CTX *ctx);
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb callback);
void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);
void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
int (*cb) (X509_STORE_CTX *, void *),
void *arg);
void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg),
void *arg);
# ifndef OPENSSL_NO_RSA
__owur int SSL_CTX_use_RSAPrivateKey(SSL_CTX *ctx, RSA *rsa);
__owur int SSL_CTX_use_RSAPrivateKey_ASN1(SSL_CTX *ctx, const unsigned char *d,
long len);
# endif
__owur int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);
__owur int SSL_CTX_use_PrivateKey_ASN1(int pk, SSL_CTX *ctx,
const unsigned char *d, long len);
__owur int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);
__owur int SSL_CTX_use_certificate_ASN1(SSL_CTX *ctx, int len,
const unsigned char *d);
__owur int SSL_CTX_use_cert_and_key(SSL_CTX *ctx, X509 *x509, EVP_PKEY *privatekey,
STACK_OF(X509) *chain, int override);
void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb);
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u);
pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx);
void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx);
void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb);
void SSL_set_default_passwd_cb_userdata(SSL *s, void *u);
pem_password_cb *SSL_get_default_passwd_cb(SSL *s);
void *SSL_get_default_passwd_cb_userdata(SSL *s);
__owur int SSL_CTX_check_private_key(const SSL_CTX *ctx);
__owur int SSL_check_private_key(const SSL *ctx);
__owur int SSL_CTX_set_session_id_context(SSL_CTX *ctx,
const unsigned char *sid_ctx,
unsigned int sid_ctx_len);
SSL *SSL_new(SSL_CTX *ctx);
int SSL_up_ref(SSL *s);
int SSL_is_dtls(const SSL *s);
__owur int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
unsigned int sid_ctx_len);
__owur int SSL_CTX_set_purpose(SSL_CTX *ctx, int purpose);
__owur int SSL_set_purpose(SSL *ssl, int purpose);
__owur int SSL_CTX_set_trust(SSL_CTX *ctx, int trust);
__owur int SSL_set_trust(SSL *ssl, int trust);
__owur int SSL_set1_host(SSL *s, const char *hostname);
__owur int SSL_add1_host(SSL *s, const char *hostname);
__owur const char *SSL_get0_peername(SSL *s);
void SSL_set_hostflags(SSL *s, unsigned int flags);
__owur int SSL_CTX_dane_enable(SSL_CTX *ctx);
__owur int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md,
uint8_t mtype, uint8_t ord);
__owur int SSL_dane_enable(SSL *s, const char *basedomain);
__owur int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
uint8_t mtype, unsigned const char *data, size_t dlen);
__owur int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki);
__owur int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
uint8_t *mtype, unsigned const char **data,
size_t *dlen);
/*
* Bridge opacity barrier between libcrypt and libssl, also needed to support
* offline testing in test/danetest.c
*/
SSL_DANE *SSL_get0_dane(SSL *ssl);
/*
* DANE flags
*/
unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags);
unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags);
unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags);
__owur int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm);
__owur int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm);
__owur X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx);
__owur X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl);
# ifndef OPENSSL_NO_SRP
int SSL_CTX_set_srp_username(SSL_CTX *ctx, char *name);
int SSL_CTX_set_srp_password(SSL_CTX *ctx, char *password);
int SSL_CTX_set_srp_strength(SSL_CTX *ctx, int strength);
int SSL_CTX_set_srp_client_pwd_callback(SSL_CTX *ctx,
char *(*cb) (SSL *, void *));
int SSL_CTX_set_srp_verify_param_callback(SSL_CTX *ctx,
int (*cb) (SSL *, void *));
int SSL_CTX_set_srp_username_callback(SSL_CTX *ctx,
int (*cb) (SSL *, int *, void *));
int SSL_CTX_set_srp_cb_arg(SSL_CTX *ctx, void *arg);
int SSL_set_srp_server_param(SSL *s, const BIGNUM *N, const BIGNUM *g,
BIGNUM *sa, BIGNUM *v, char *info);
int SSL_set_srp_server_param_pw(SSL *s, const char *user, const char *pass,
const char *grp);
__owur BIGNUM *SSL_get_srp_g(SSL *s);
__owur BIGNUM *SSL_get_srp_N(SSL *s);
__owur char *SSL_get_srp_username(SSL *s);
__owur char *SSL_get_srp_userinfo(SSL *s);
# endif
/*
* ClientHello callback and helpers.
*/
# define SSL_CLIENT_HELLO_SUCCESS 1
# define SSL_CLIENT_HELLO_ERROR 0
# define SSL_CLIENT_HELLO_RETRY (-1)
typedef int (*SSL_client_hello_cb_fn) (SSL *s, int *al, void *arg);
void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb,
void *arg);
int SSL_client_hello_isv2(SSL *s);
unsigned int SSL_client_hello_get0_legacy_version(SSL *s);
size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out);
size_t SSL_client_hello_get0_compression_methods(SSL *s,
const unsigned char **out);
int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen);
int SSL_client_hello_get0_ext(SSL *s, unsigned int type,
const unsigned char **out, size_t *outlen);
void SSL_certs_clear(SSL *s);
void SSL_free(SSL *ssl);
# ifdef OSSL_ASYNC_FD
/*
* Windows application developer has to include windows.h to use these.
*/
__owur int SSL_waiting_for_async(SSL *s);
__owur int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds);
__owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd,
size_t *numaddfds, OSSL_ASYNC_FD *delfd,
size_t *numdelfds);
# endif
__owur int SSL_accept(SSL *ssl);
__owur int SSL_stateless(SSL *s);
__owur int SSL_connect(SSL *ssl);
__owur int SSL_read(SSL *ssl, void *buf, int num);
__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
# define SSL_READ_EARLY_DATA_ERROR 0
# define SSL_READ_EARLY_DATA_SUCCESS 1
# define SSL_READ_EARLY_DATA_FINISH 2
__owur int SSL_read_early_data(SSL *s, void *buf, size_t num,
size_t *readbytes);
__owur int SSL_peek(SSL *ssl, void *buf, int num);
__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes);
__owur int SSL_write(SSL *ssl, const void *buf, int num);
__owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written);
__owur int SSL_write_early_data(SSL *s, const void *buf, size_t num,
size_t *written);
long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg);
long SSL_callback_ctrl(SSL *, int, void (*)(void));
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg);
long SSL_CTX_callback_ctrl(SSL_CTX *, int, void (*)(void));
# define SSL_EARLY_DATA_NOT_SENT 0
# define SSL_EARLY_DATA_REJECTED 1
# define SSL_EARLY_DATA_ACCEPTED 2
__owur int SSL_get_early_data_status(const SSL *s);
__owur int SSL_get_error(const SSL *s, int ret_code);
__owur const char *SSL_get_version(const SSL *s);
/* This sets the 'default' SSL version that SSL_new() will create */
__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
# ifndef OPENSSL_NO_SSL3_METHOD
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_method(void)) /* SSLv3 */
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_server_method(void))
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *SSLv3_client_method(void))
# endif
#define SSLv23_method TLS_method
#define SSLv23_server_method TLS_server_method
#define SSLv23_client_method TLS_client_method
/* Negotiate highest available SSL/TLS version */
__owur const SSL_METHOD *TLS_method(void);
__owur const SSL_METHOD *TLS_server_method(void);
__owur const SSL_METHOD *TLS_client_method(void);
# ifndef OPENSSL_NO_TLS1_METHOD
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_method(void)) /* TLSv1.0 */
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_server_method(void))
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_client_method(void))
# endif
# ifndef OPENSSL_NO_TLS1_1_METHOD
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_method(void)) /* TLSv1.1 */
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_server_method(void))
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_client_method(void))
# endif
# ifndef OPENSSL_NO_TLS1_2_METHOD
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_method(void)) /* TLSv1.2 */
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_server_method(void))
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_client_method(void))
# endif
# ifndef OPENSSL_NO_DTLS1_METHOD
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_method(void)) /* DTLSv1.0 */
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_server_method(void))
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_client_method(void))
# endif
# ifndef OPENSSL_NO_DTLS1_2_METHOD
/* DTLSv1.2 */
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_method(void))
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_server_method(void))
DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *DTLSv1_2_client_method(void))
# endif
__owur const SSL_METHOD *DTLS_method(void); /* DTLS 1.0 and 1.2 */
__owur const SSL_METHOD *DTLS_server_method(void); /* DTLS 1.0 and 1.2 */
__owur const SSL_METHOD *DTLS_client_method(void); /* DTLS 1.0 and 1.2 */
__owur size_t DTLS_get_data_mtu(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
__owur STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s);
__owur STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s);
__owur int SSL_do_handshake(SSL *s);
int SSL_key_update(SSL *s, int updatetype);
int SSL_get_key_update_type(const SSL *s);
int SSL_renegotiate(SSL *s);
int SSL_renegotiate_abbreviated(SSL *s);
__owur int SSL_renegotiate_pending(const SSL *s);
int SSL_shutdown(SSL *s);
__owur int SSL_verify_client_post_handshake(SSL *s);
void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val);
void SSL_set_post_handshake_auth(SSL *s, int val);
__owur const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx);
__owur const SSL_METHOD *SSL_get_ssl_method(const SSL *s);
__owur int SSL_set_ssl_method(SSL *s, const SSL_METHOD *method);
__owur const char *SSL_alert_type_string_long(int value);
__owur const char *SSL_alert_type_string(int value);
__owur const char *SSL_alert_desc_string_long(int value);
__owur const char *SSL_alert_desc_string(int value);
void SSL_set0_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
void SSL_CTX_set0_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
__owur const STACK_OF(X509_NAME) *SSL_get0_CA_list(const SSL *s);
__owur const STACK_OF(X509_NAME) *SSL_CTX_get0_CA_list(const SSL_CTX *ctx);
__owur int SSL_add1_to_CA_list(SSL *ssl, const X509 *x);
__owur int SSL_CTX_add1_to_CA_list(SSL_CTX *ctx, const X509 *x);
__owur const STACK_OF(X509_NAME) *SSL_get0_peer_CA_list(const SSL *s);
void SSL_set_client_CA_list(SSL *s, STACK_OF(X509_NAME) *name_list);
void SSL_CTX_set_client_CA_list(SSL_CTX *ctx, STACK_OF(X509_NAME) *name_list);
__owur STACK_OF(X509_NAME) *SSL_get_client_CA_list(const SSL *s);
__owur STACK_OF(X509_NAME) *SSL_CTX_get_client_CA_list(const SSL_CTX *s);
__owur int SSL_add_client_CA(SSL *ssl, X509 *x);
__owur int SSL_CTX_add_client_CA(SSL_CTX *ctx, X509 *x);
void SSL_set_connect_state(SSL *s);
void SSL_set_accept_state(SSL *s);
__owur long SSL_get_default_timeout(const SSL *s);
# if OPENSSL_API_COMPAT < 0x10100000L
# define SSL_library_init() OPENSSL_init_ssl(0, NULL)
# endif
__owur char *SSL_CIPHER_description(const SSL_CIPHER *, char *buf, int size);
__owur STACK_OF(X509_NAME) *SSL_dup_CA_list(const STACK_OF(X509_NAME) *sk);
__owur SSL *SSL_dup(SSL *ssl);
__owur X509 *SSL_get_certificate(const SSL *ssl);
/*
* EVP_PKEY
*/
struct evp_pkey_st *SSL_get_privatekey(const SSL *ssl);
__owur X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx);
__owur EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx);
void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode);
__owur int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx);
void SSL_set_quiet_shutdown(SSL *ssl, int mode);
__owur int SSL_get_quiet_shutdown(const SSL *ssl);
void SSL_set_shutdown(SSL *ssl, int mode);
__owur int SSL_get_shutdown(const SSL *ssl);
__owur int SSL_version(const SSL *ssl);
__owur int SSL_client_version(const SSL *s);
__owur int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx);
__owur int SSL_CTX_set_default_verify_file(SSL_CTX *ctx);
__owur int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath);
# define SSL_get0_session SSL_get_session/* just peek at pointer */
__owur SSL_SESSION *SSL_get_session(const SSL *ssl);
__owur SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
__owur SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx);
void SSL_set_info_callback(SSL *ssl,
void (*cb) (const SSL *ssl, int type, int val));
void (*SSL_get_info_callback(const SSL *ssl)) (const SSL *ssl, int type,
int val);
__owur OSSL_HANDSHAKE_STATE SSL_get_state(const SSL *ssl);
void SSL_set_verify_result(SSL *ssl, long v);
__owur long SSL_get_verify_result(const SSL *ssl);
__owur STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s);
__owur size_t SSL_get_client_random(const SSL *ssl, unsigned char *out,
size_t outlen);
__owur size_t SSL_get_server_random(const SSL *ssl, unsigned char *out,
size_t outlen);
__owur size_t SSL_SESSION_get_master_key(const SSL_SESSION *sess,
unsigned char *out, size_t outlen);
__owur int SSL_SESSION_set1_master_key(SSL_SESSION *sess,
const unsigned char *in, size_t len);
uint8_t SSL_SESSION_get_max_fragment_length(const SSL_SESSION *sess);
#define SSL_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, l, p, newf, dupf, freef)
__owur int SSL_set_ex_data(SSL *ssl, int idx, void *data);
void *SSL_get_ex_data(const SSL *ssl, int idx);
#define SSL_SESSION_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_SESSION, l, p, newf, dupf, freef)
__owur int SSL_SESSION_set_ex_data(SSL_SESSION *ss, int idx, void *data);
void *SSL_SESSION_get_ex_data(const SSL_SESSION *ss, int idx);
#define SSL_CTX_get_ex_new_index(l, p, newf, dupf, freef) \
CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL_CTX, l, p, newf, dupf, freef)
__owur int SSL_CTX_set_ex_data(SSL_CTX *ssl, int idx, void *data);
void *SSL_CTX_get_ex_data(const SSL_CTX *ssl, int idx);
__owur int SSL_get_ex_data_X509_STORE_CTX_idx(void);
# define SSL_CTX_sess_set_cache_size(ctx,t) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_SIZE,t,NULL)
# define SSL_CTX_sess_get_cache_size(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_SIZE,0,NULL)
# define SSL_CTX_set_session_cache_mode(ctx,m) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SESS_CACHE_MODE,m,NULL)
# define SSL_CTX_get_session_cache_mode(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_SESS_CACHE_MODE,0,NULL)
# define SSL_CTX_get_default_read_ahead(ctx) SSL_CTX_get_read_ahead(ctx)
# define SSL_CTX_set_default_read_ahead(ctx,m) SSL_CTX_set_read_ahead(ctx,m)
# define SSL_CTX_get_read_ahead(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_READ_AHEAD,0,NULL)
# define SSL_CTX_set_read_ahead(ctx,m) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_READ_AHEAD,m,NULL)
# define SSL_CTX_get_max_cert_list(ctx) \
SSL_CTX_ctrl(ctx,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
# define SSL_CTX_set_max_cert_list(ctx,m) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
# define SSL_get_max_cert_list(ssl) \
SSL_ctrl(ssl,SSL_CTRL_GET_MAX_CERT_LIST,0,NULL)
# define SSL_set_max_cert_list(ssl,m) \
SSL_ctrl(ssl,SSL_CTRL_SET_MAX_CERT_LIST,m,NULL)
# define SSL_CTX_set_max_send_fragment(ctx,m) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_set_max_send_fragment(ssl,m) \
SSL_ctrl(ssl,SSL_CTRL_SET_MAX_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_split_send_fragment(ctx,m) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_set_split_send_fragment(ssl,m) \
SSL_ctrl(ssl,SSL_CTRL_SET_SPLIT_SEND_FRAGMENT,m,NULL)
# define SSL_CTX_set_max_pipelines(ctx,m) \
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
# define SSL_set_max_pipelines(ssl,m) \
SSL_ctrl(ssl,SSL_CTRL_SET_MAX_PIPELINES,m,NULL)
void SSL_CTX_set_default_read_buffer_len(SSL_CTX *ctx, size_t len);
void SSL_set_default_read_buffer_len(SSL *s, size_t len);
# ifndef OPENSSL_NO_DH
/* NB: the |keylength| is only applicable when is_export is true */
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
DH *(*dh) (SSL *ssl, int is_export,
int keylength));
void SSL_set_tmp_dh_callback(SSL *ssl,
DH *(*dh) (SSL *ssl, int is_export,
int keylength));
# endif
__owur const COMP_METHOD *SSL_get_current_compression(const SSL *s);
__owur const COMP_METHOD *SSL_get_current_expansion(const SSL *s);
__owur const char *SSL_COMP_get_name(const COMP_METHOD *comp);
__owur const char *SSL_COMP_get0_name(const SSL_COMP *comp);
__owur int SSL_COMP_get_id(const SSL_COMP *comp);
STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void);
__owur STACK_OF(SSL_COMP) *SSL_COMP_set0_compression_methods(STACK_OF(SSL_COMP)
*meths);
# if OPENSSL_API_COMPAT < 0x10100000L
# define SSL_COMP_free_compression_methods() while(0) continue
# endif
__owur int SSL_COMP_add_compression_method(int id, COMP_METHOD *cm);
const SSL_CIPHER *SSL_CIPHER_find(SSL *ssl, const unsigned char *ptr);
int SSL_CIPHER_get_cipher_nid(const SSL_CIPHER *c);
int SSL_CIPHER_get_digest_nid(const SSL_CIPHER *c);
int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
int isv2format, STACK_OF(SSL_CIPHER) **sk,
STACK_OF(SSL_CIPHER) **scsvs);
/* TLS extensions functions */
__owur int SSL_set_session_ticket_ext(SSL *s, void *ext_data, int ext_len);
__owur int SSL_set_session_ticket_ext_cb(SSL *s,
tls_session_ticket_ext_cb_fn cb,
void *arg);
/* Pre-shared secret session resumption functions */
__owur int SSL_set_session_secret_cb(SSL *s,
tls_session_secret_cb_fn session_secret_cb,
void *arg);
void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
int (*cb) (SSL *ssl,
int
is_forward_secure));
void SSL_set_not_resumable_session_callback(SSL *ssl,
int (*cb) (SSL *ssl,
int is_forward_secure));
void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg));
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg);
void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx);
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size);
void SSL_set_record_padding_callback(SSL *ssl,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg));
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg);
void *SSL_get_record_padding_callback_arg(const SSL *ssl);
int SSL_set_block_padding(SSL *ssl, size_t block_size);
int SSL_set_num_tickets(SSL *s, size_t num_tickets);
size_t SSL_get_num_tickets(const SSL *s);
int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets);
size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx);
# if OPENSSL_API_COMPAT < 0x10100000L
# define SSL_cache_hit(s) SSL_session_reused(s)
# endif
-__owur int SSL_session_reused(SSL *s);
+__owur int SSL_session_reused(const SSL *s);
__owur int SSL_is_server(const SSL *s);
__owur __owur SSL_CONF_CTX *SSL_CONF_CTX_new(void);
int SSL_CONF_CTX_finish(SSL_CONF_CTX *cctx);
void SSL_CONF_CTX_free(SSL_CONF_CTX *cctx);
unsigned int SSL_CONF_CTX_set_flags(SSL_CONF_CTX *cctx, unsigned int flags);
__owur unsigned int SSL_CONF_CTX_clear_flags(SSL_CONF_CTX *cctx,
unsigned int flags);
__owur int SSL_CONF_CTX_set1_prefix(SSL_CONF_CTX *cctx, const char *pre);
void SSL_CONF_CTX_set_ssl(SSL_CONF_CTX *cctx, SSL *ssl);
void SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *cctx, SSL_CTX *ctx);
__owur int SSL_CONF_cmd(SSL_CONF_CTX *cctx, const char *cmd, const char *value);
__owur int SSL_CONF_cmd_argv(SSL_CONF_CTX *cctx, int *pargc, char ***pargv);
__owur int SSL_CONF_cmd_value_type(SSL_CONF_CTX *cctx, const char *cmd);
void SSL_add_ssl_module(void);
int SSL_config(SSL *s, const char *name);
int SSL_CTX_config(SSL_CTX *ctx, const char *name);
# ifndef OPENSSL_NO_SSL_TRACE
void SSL_trace(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg);
# endif
# ifndef OPENSSL_NO_SOCK
int DTLSv1_listen(SSL *s, BIO_ADDR *client);
# endif
# ifndef OPENSSL_NO_CT
/*
* A callback for verifying that the received SCTs are sufficient.
* Expected to return 1 if they are sufficient, otherwise 0.
* May return a negative integer if an error occurs.
* A connection should be aborted if the SCTs are deemed insufficient.
*/
typedef int (*ssl_ct_validation_cb)(const CT_POLICY_EVAL_CTX *ctx,
const STACK_OF(SCT) *scts, void *arg);
/*
* Sets a |callback| that is invoked upon receipt of ServerHelloDone to validate
* the received SCTs.
* If the callback returns a non-positive result, the connection is terminated.
* Call this function before beginning a handshake.
* If a NULL |callback| is provided, SCT validation is disabled.
* |arg| is arbitrary userdata that will be passed to the callback whenever it
* is invoked. Ownership of |arg| remains with the caller.
*
* NOTE: A side-effect of setting a CT callback is that an OCSP stapled response
* will be requested.
*/
int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
void *arg);
int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
ssl_ct_validation_cb callback,
void *arg);
#define SSL_disable_ct(s) \
((void) SSL_set_validation_callback((s), NULL, NULL))
#define SSL_CTX_disable_ct(ctx) \
((void) SSL_CTX_set_validation_callback((ctx), NULL, NULL))
/*
* The validation type enumerates the available behaviours of the built-in SSL
* CT validation callback selected via SSL_enable_ct() and SSL_CTX_enable_ct().
* The underlying callback is a static function in libssl.
*/
enum {
SSL_CT_VALIDATION_PERMISSIVE = 0,
SSL_CT_VALIDATION_STRICT
};
/*
* Enable CT by setting up a callback that implements one of the built-in
* validation variants. The SSL_CT_VALIDATION_PERMISSIVE variant always
* continues the handshake, the application can make appropriate decisions at
* handshake completion. The SSL_CT_VALIDATION_STRICT variant requires at
* least one valid SCT, or else handshake termination will be requested. The
* handshake may continue anyway if SSL_VERIFY_NONE is in effect.
*/
int SSL_enable_ct(SSL *s, int validation_mode);
int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode);
/*
* Report whether a non-NULL callback is enabled.
*/
int SSL_ct_is_enabled(const SSL *s);
int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx);
/* Gets the SCTs received from a connection */
const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s);
/*
* Loads the CT log list from the default location.
* If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
* the log information loaded from this file will be appended to the
* CTLOG_STORE.
* Returns 1 on success, 0 otherwise.
*/
int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx);
/*
* Loads the CT log list from the specified file path.
* If a CTLOG_STORE has previously been set using SSL_CTX_set_ctlog_store,
* the log information loaded from this file will be appended to the
* CTLOG_STORE.
* Returns 1 on success, 0 otherwise.
*/
int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path);
/*
* Sets the CT log list used by all SSL connections created from this SSL_CTX.
* Ownership of the CTLOG_STORE is transferred to the SSL_CTX.
*/
void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE *logs);
/*
* Gets the CT log list used by all SSL connections created from this SSL_CTX.
* This will be NULL unless one of the following functions has been called:
* - SSL_CTX_set_default_ctlog_list_file
* - SSL_CTX_set_ctlog_list_file
* - SSL_CTX_set_ctlog_store
*/
const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx);
# endif /* OPENSSL_NO_CT */
/* What the "other" parameter contains in security callback */
/* Mask for type */
# define SSL_SECOP_OTHER_TYPE 0xffff0000
# define SSL_SECOP_OTHER_NONE 0
# define SSL_SECOP_OTHER_CIPHER (1 << 16)
# define SSL_SECOP_OTHER_CURVE (2 << 16)
# define SSL_SECOP_OTHER_DH (3 << 16)
# define SSL_SECOP_OTHER_PKEY (4 << 16)
# define SSL_SECOP_OTHER_SIGALG (5 << 16)
# define SSL_SECOP_OTHER_CERT (6 << 16)
/* Indicated operation refers to peer key or certificate */
# define SSL_SECOP_PEER 0x1000
/* Values for "op" parameter in security callback */
/* Called to filter ciphers */
/* Ciphers client supports */
# define SSL_SECOP_CIPHER_SUPPORTED (1 | SSL_SECOP_OTHER_CIPHER)
/* Cipher shared by client/server */
# define SSL_SECOP_CIPHER_SHARED (2 | SSL_SECOP_OTHER_CIPHER)
/* Sanity check of cipher server selects */
# define SSL_SECOP_CIPHER_CHECK (3 | SSL_SECOP_OTHER_CIPHER)
/* Curves supported by client */
# define SSL_SECOP_CURVE_SUPPORTED (4 | SSL_SECOP_OTHER_CURVE)
/* Curves shared by client/server */
# define SSL_SECOP_CURVE_SHARED (5 | SSL_SECOP_OTHER_CURVE)
/* Sanity check of curve server selects */
# define SSL_SECOP_CURVE_CHECK (6 | SSL_SECOP_OTHER_CURVE)
/* Temporary DH key */
# define SSL_SECOP_TMP_DH (7 | SSL_SECOP_OTHER_PKEY)
/* SSL/TLS version */
# define SSL_SECOP_VERSION (9 | SSL_SECOP_OTHER_NONE)
/* Session tickets */
# define SSL_SECOP_TICKET (10 | SSL_SECOP_OTHER_NONE)
/* Supported signature algorithms sent to peer */
# define SSL_SECOP_SIGALG_SUPPORTED (11 | SSL_SECOP_OTHER_SIGALG)
/* Shared signature algorithm */
# define SSL_SECOP_SIGALG_SHARED (12 | SSL_SECOP_OTHER_SIGALG)
/* Sanity check signature algorithm allowed */
# define SSL_SECOP_SIGALG_CHECK (13 | SSL_SECOP_OTHER_SIGALG)
/* Used to get mask of supported public key signature algorithms */
# define SSL_SECOP_SIGALG_MASK (14 | SSL_SECOP_OTHER_SIGALG)
/* Use to see if compression is allowed */
# define SSL_SECOP_COMPRESSION (15 | SSL_SECOP_OTHER_NONE)
/* EE key in certificate */
# define SSL_SECOP_EE_KEY (16 | SSL_SECOP_OTHER_CERT)
/* CA key in certificate */
# define SSL_SECOP_CA_KEY (17 | SSL_SECOP_OTHER_CERT)
/* CA digest algorithm in certificate */
# define SSL_SECOP_CA_MD (18 | SSL_SECOP_OTHER_CERT)
/* Peer EE key in certificate */
# define SSL_SECOP_PEER_EE_KEY (SSL_SECOP_EE_KEY | SSL_SECOP_PEER)
/* Peer CA key in certificate */
# define SSL_SECOP_PEER_CA_KEY (SSL_SECOP_CA_KEY | SSL_SECOP_PEER)
/* Peer CA digest algorithm in certificate */
# define SSL_SECOP_PEER_CA_MD (SSL_SECOP_CA_MD | SSL_SECOP_PEER)
void SSL_set_security_level(SSL *s, int level);
__owur int SSL_get_security_level(const SSL *s);
void SSL_set_security_callback(SSL *s,
int (*cb) (const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid,
void *other, void *ex));
int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
const SSL_CTX *ctx, int op,
int bits, int nid, void *other,
void *ex);
void SSL_set0_security_ex_data(SSL *s, void *ex);
__owur void *SSL_get0_security_ex_data(const SSL *s);
void SSL_CTX_set_security_level(SSL_CTX *ctx, int level);
__owur int SSL_CTX_get_security_level(const SSL_CTX *ctx);
void SSL_CTX_set_security_callback(SSL_CTX *ctx,
int (*cb) (const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid,
void *other, void *ex));
int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s,
const SSL_CTX *ctx,
int op, int bits,
int nid,
void *other,
void *ex);
void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex);
__owur void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx);
/* OPENSSL_INIT flag 0x010000 reserved for internal use */
# define OPENSSL_INIT_NO_LOAD_SSL_STRINGS 0x00100000L
# define OPENSSL_INIT_LOAD_SSL_STRINGS 0x00200000L
# define OPENSSL_INIT_SSL_DEFAULT \
(OPENSSL_INIT_LOAD_SSL_STRINGS | OPENSSL_INIT_LOAD_CRYPTO_STRINGS)
int OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
# ifndef OPENSSL_NO_UNIT_TEST
__owur const struct openssl_ssl_test_functions *SSL_test_functions(void);
# endif
__owur int SSL_free_buffers(SSL *ssl);
__owur int SSL_alloc_buffers(SSL *ssl);
/* Status codes passed to the decrypt session ticket callback. Some of these
* are for internal use only and are never passed to the callback. */
typedef int SSL_TICKET_STATUS;
/* Support for ticket appdata */
/* fatal error, malloc failure */
# define SSL_TICKET_FATAL_ERR_MALLOC 0
/* fatal error, either from parsing or decrypting the ticket */
# define SSL_TICKET_FATAL_ERR_OTHER 1
/* No ticket present */
# define SSL_TICKET_NONE 2
/* Empty ticket present */
# define SSL_TICKET_EMPTY 3
/* the ticket couldn't be decrypted */
# define SSL_TICKET_NO_DECRYPT 4
/* a ticket was successfully decrypted */
# define SSL_TICKET_SUCCESS 5
/* same as above but the ticket needs to be renewed */
# define SSL_TICKET_SUCCESS_RENEW 6
/* Return codes for the decrypt session ticket callback */
typedef int SSL_TICKET_RETURN;
/* An error occurred */
#define SSL_TICKET_RETURN_ABORT 0
/* Do not use the ticket, do not send a renewed ticket to the client */
#define SSL_TICKET_RETURN_IGNORE 1
/* Do not use the ticket, send a renewed ticket to the client */
#define SSL_TICKET_RETURN_IGNORE_RENEW 2
/* Use the ticket, do not send a renewed ticket to the client */
#define SSL_TICKET_RETURN_USE 3
/* Use the ticket, send a renewed ticket to the client */
#define SSL_TICKET_RETURN_USE_RENEW 4
typedef int (*SSL_CTX_generate_session_ticket_fn)(SSL *s, void *arg);
typedef SSL_TICKET_RETURN (*SSL_CTX_decrypt_session_ticket_fn)(SSL *s, SSL_SESSION *ss,
const unsigned char *keyname,
size_t keyname_length,
SSL_TICKET_STATUS status,
void *arg);
int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx,
SSL_CTX_generate_session_ticket_fn gen_cb,
SSL_CTX_decrypt_session_ticket_fn dec_cb,
void *arg);
int SSL_SESSION_set1_ticket_appdata(SSL_SESSION *ss, const void *data, size_t len);
int SSL_SESSION_get0_ticket_appdata(SSL_SESSION *ss, void **data, size_t *len);
extern const char SSL_version_str[];
typedef unsigned int (*DTLS_timer_cb)(SSL *s, unsigned int timer_us);
void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);
typedef int (*SSL_allow_early_data_cb_fn)(SSL *s, void *arg);
void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx,
SSL_allow_early_data_cb_fn cb,
void *arg);
void SSL_set_allow_early_data_cb(SSL *s,
SSL_allow_early_data_cb_fn cb,
void *arg);
# ifdef __cplusplus
}
# endif
#endif
diff --git a/include/openssl/x509v3.h b/include/openssl/x509v3.h
index fe1791c6819a..9ea20275ac34 100644
--- a/include/openssl/x509v3.h
+++ b/include/openssl/x509v3.h
@@ -1,935 +1,935 @@
/*
- * Copyright 1999-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1999-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_X509V3_H
# define HEADER_X509V3_H
# include <openssl/bio.h>
# include <openssl/x509.h>
# include <openssl/conf.h>
# include <openssl/x509v3err.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Forward reference */
struct v3_ext_method;
struct v3_ext_ctx;
/* Useful typedefs */
typedef void *(*X509V3_EXT_NEW)(void);
typedef void (*X509V3_EXT_FREE) (void *);
typedef void *(*X509V3_EXT_D2I)(void *, const unsigned char **, long);
typedef int (*X509V3_EXT_I2D) (void *, unsigned char **);
typedef STACK_OF(CONF_VALUE) *
(*X509V3_EXT_I2V) (const struct v3_ext_method *method, void *ext,
STACK_OF(CONF_VALUE) *extlist);
typedef void *(*X509V3_EXT_V2I)(const struct v3_ext_method *method,
struct v3_ext_ctx *ctx,
STACK_OF(CONF_VALUE) *values);
typedef char *(*X509V3_EXT_I2S)(const struct v3_ext_method *method,
void *ext);
typedef void *(*X509V3_EXT_S2I)(const struct v3_ext_method *method,
struct v3_ext_ctx *ctx, const char *str);
typedef int (*X509V3_EXT_I2R) (const struct v3_ext_method *method, void *ext,
BIO *out, int indent);
typedef void *(*X509V3_EXT_R2I)(const struct v3_ext_method *method,
struct v3_ext_ctx *ctx, const char *str);
/* V3 extension structure */
struct v3_ext_method {
int ext_nid;
int ext_flags;
/* If this is set the following four fields are ignored */
ASN1_ITEM_EXP *it;
/* Old style ASN1 calls */
X509V3_EXT_NEW ext_new;
X509V3_EXT_FREE ext_free;
X509V3_EXT_D2I d2i;
X509V3_EXT_I2D i2d;
/* The following pair is used for string extensions */
X509V3_EXT_I2S i2s;
X509V3_EXT_S2I s2i;
/* The following pair is used for multi-valued extensions */
X509V3_EXT_I2V i2v;
X509V3_EXT_V2I v2i;
/* The following are used for raw extensions */
X509V3_EXT_I2R i2r;
X509V3_EXT_R2I r2i;
void *usr_data; /* Any extension specific data */
};
typedef struct X509V3_CONF_METHOD_st {
char *(*get_string) (void *db, const char *section, const char *value);
STACK_OF(CONF_VALUE) *(*get_section) (void *db, const char *section);
void (*free_string) (void *db, char *string);
void (*free_section) (void *db, STACK_OF(CONF_VALUE) *section);
} X509V3_CONF_METHOD;
/* Context specific info */
struct v3_ext_ctx {
# define CTX_TEST 0x1
# define X509V3_CTX_REPLACE 0x2
int flags;
X509 *issuer_cert;
X509 *subject_cert;
X509_REQ *subject_req;
X509_CRL *crl;
X509V3_CONF_METHOD *db_meth;
void *db;
/* Maybe more here */
};
typedef struct v3_ext_method X509V3_EXT_METHOD;
DEFINE_STACK_OF(X509V3_EXT_METHOD)
/* ext_flags values */
# define X509V3_EXT_DYNAMIC 0x1
# define X509V3_EXT_CTX_DEP 0x2
# define X509V3_EXT_MULTILINE 0x4
typedef BIT_STRING_BITNAME ENUMERATED_NAMES;
typedef struct BASIC_CONSTRAINTS_st {
int ca;
ASN1_INTEGER *pathlen;
} BASIC_CONSTRAINTS;
typedef struct PKEY_USAGE_PERIOD_st {
ASN1_GENERALIZEDTIME *notBefore;
ASN1_GENERALIZEDTIME *notAfter;
} PKEY_USAGE_PERIOD;
typedef struct otherName_st {
ASN1_OBJECT *type_id;
ASN1_TYPE *value;
} OTHERNAME;
typedef struct EDIPartyName_st {
ASN1_STRING *nameAssigner;
ASN1_STRING *partyName;
} EDIPARTYNAME;
typedef struct GENERAL_NAME_st {
# define GEN_OTHERNAME 0
# define GEN_EMAIL 1
# define GEN_DNS 2
# define GEN_X400 3
# define GEN_DIRNAME 4
# define GEN_EDIPARTY 5
# define GEN_URI 6
# define GEN_IPADD 7
# define GEN_RID 8
int type;
union {
char *ptr;
OTHERNAME *otherName; /* otherName */
ASN1_IA5STRING *rfc822Name;
ASN1_IA5STRING *dNSName;
ASN1_TYPE *x400Address;
X509_NAME *directoryName;
EDIPARTYNAME *ediPartyName;
ASN1_IA5STRING *uniformResourceIdentifier;
ASN1_OCTET_STRING *iPAddress;
ASN1_OBJECT *registeredID;
/* Old names */
ASN1_OCTET_STRING *ip; /* iPAddress */
X509_NAME *dirn; /* dirn */
ASN1_IA5STRING *ia5; /* rfc822Name, dNSName,
* uniformResourceIdentifier */
ASN1_OBJECT *rid; /* registeredID */
ASN1_TYPE *other; /* x400Address */
} d;
} GENERAL_NAME;
typedef struct ACCESS_DESCRIPTION_st {
ASN1_OBJECT *method;
GENERAL_NAME *location;
} ACCESS_DESCRIPTION;
typedef STACK_OF(ACCESS_DESCRIPTION) AUTHORITY_INFO_ACCESS;
typedef STACK_OF(ASN1_OBJECT) EXTENDED_KEY_USAGE;
typedef STACK_OF(ASN1_INTEGER) TLS_FEATURE;
DEFINE_STACK_OF(GENERAL_NAME)
typedef STACK_OF(GENERAL_NAME) GENERAL_NAMES;
DEFINE_STACK_OF(GENERAL_NAMES)
DEFINE_STACK_OF(ACCESS_DESCRIPTION)
typedef struct DIST_POINT_NAME_st {
int type;
union {
GENERAL_NAMES *fullname;
STACK_OF(X509_NAME_ENTRY) *relativename;
} name;
/* If relativename then this contains the full distribution point name */
X509_NAME *dpname;
} DIST_POINT_NAME;
/* All existing reasons */
# define CRLDP_ALL_REASONS 0x807f
# define CRL_REASON_NONE -1
# define CRL_REASON_UNSPECIFIED 0
# define CRL_REASON_KEY_COMPROMISE 1
# define CRL_REASON_CA_COMPROMISE 2
# define CRL_REASON_AFFILIATION_CHANGED 3
# define CRL_REASON_SUPERSEDED 4
# define CRL_REASON_CESSATION_OF_OPERATION 5
# define CRL_REASON_CERTIFICATE_HOLD 6
# define CRL_REASON_REMOVE_FROM_CRL 8
# define CRL_REASON_PRIVILEGE_WITHDRAWN 9
# define CRL_REASON_AA_COMPROMISE 10
struct DIST_POINT_st {
DIST_POINT_NAME *distpoint;
ASN1_BIT_STRING *reasons;
GENERAL_NAMES *CRLissuer;
int dp_reasons;
};
typedef STACK_OF(DIST_POINT) CRL_DIST_POINTS;
DEFINE_STACK_OF(DIST_POINT)
struct AUTHORITY_KEYID_st {
ASN1_OCTET_STRING *keyid;
GENERAL_NAMES *issuer;
ASN1_INTEGER *serial;
};
/* Strong extranet structures */
typedef struct SXNET_ID_st {
ASN1_INTEGER *zone;
ASN1_OCTET_STRING *user;
} SXNETID;
DEFINE_STACK_OF(SXNETID)
typedef struct SXNET_st {
ASN1_INTEGER *version;
STACK_OF(SXNETID) *ids;
} SXNET;
typedef struct NOTICEREF_st {
ASN1_STRING *organization;
STACK_OF(ASN1_INTEGER) *noticenos;
} NOTICEREF;
typedef struct USERNOTICE_st {
NOTICEREF *noticeref;
ASN1_STRING *exptext;
} USERNOTICE;
typedef struct POLICYQUALINFO_st {
ASN1_OBJECT *pqualid;
union {
ASN1_IA5STRING *cpsuri;
USERNOTICE *usernotice;
ASN1_TYPE *other;
} d;
} POLICYQUALINFO;
DEFINE_STACK_OF(POLICYQUALINFO)
typedef struct POLICYINFO_st {
ASN1_OBJECT *policyid;
STACK_OF(POLICYQUALINFO) *qualifiers;
} POLICYINFO;
typedef STACK_OF(POLICYINFO) CERTIFICATEPOLICIES;
DEFINE_STACK_OF(POLICYINFO)
typedef struct POLICY_MAPPING_st {
ASN1_OBJECT *issuerDomainPolicy;
ASN1_OBJECT *subjectDomainPolicy;
} POLICY_MAPPING;
DEFINE_STACK_OF(POLICY_MAPPING)
typedef STACK_OF(POLICY_MAPPING) POLICY_MAPPINGS;
typedef struct GENERAL_SUBTREE_st {
GENERAL_NAME *base;
ASN1_INTEGER *minimum;
ASN1_INTEGER *maximum;
} GENERAL_SUBTREE;
DEFINE_STACK_OF(GENERAL_SUBTREE)
struct NAME_CONSTRAINTS_st {
STACK_OF(GENERAL_SUBTREE) *permittedSubtrees;
STACK_OF(GENERAL_SUBTREE) *excludedSubtrees;
};
typedef struct POLICY_CONSTRAINTS_st {
ASN1_INTEGER *requireExplicitPolicy;
ASN1_INTEGER *inhibitPolicyMapping;
} POLICY_CONSTRAINTS;
/* Proxy certificate structures, see RFC 3820 */
typedef struct PROXY_POLICY_st {
ASN1_OBJECT *policyLanguage;
ASN1_OCTET_STRING *policy;
} PROXY_POLICY;
typedef struct PROXY_CERT_INFO_EXTENSION_st {
ASN1_INTEGER *pcPathLengthConstraint;
PROXY_POLICY *proxyPolicy;
} PROXY_CERT_INFO_EXTENSION;
DECLARE_ASN1_FUNCTIONS(PROXY_POLICY)
DECLARE_ASN1_FUNCTIONS(PROXY_CERT_INFO_EXTENSION)
struct ISSUING_DIST_POINT_st {
DIST_POINT_NAME *distpoint;
int onlyuser;
int onlyCA;
ASN1_BIT_STRING *onlysomereasons;
int indirectCRL;
int onlyattr;
};
/* Values in idp_flags field */
/* IDP present */
# define IDP_PRESENT 0x1
/* IDP values inconsistent */
# define IDP_INVALID 0x2
/* onlyuser true */
# define IDP_ONLYUSER 0x4
/* onlyCA true */
# define IDP_ONLYCA 0x8
/* onlyattr true */
# define IDP_ONLYATTR 0x10
/* indirectCRL true */
# define IDP_INDIRECT 0x20
/* onlysomereasons present */
# define IDP_REASONS 0x40
# define X509V3_conf_err(val) ERR_add_error_data(6, \
"section:", (val)->section, \
",name:", (val)->name, ",value:", (val)->value)
# define X509V3_set_ctx_test(ctx) \
X509V3_set_ctx(ctx, NULL, NULL, NULL, NULL, CTX_TEST)
# define X509V3_set_ctx_nodb(ctx) (ctx)->db = NULL;
# define EXT_BITSTRING(nid, table) { nid, 0, ASN1_ITEM_ref(ASN1_BIT_STRING), \
0,0,0,0, \
0,0, \
(X509V3_EXT_I2V)i2v_ASN1_BIT_STRING, \
(X509V3_EXT_V2I)v2i_ASN1_BIT_STRING, \
NULL, NULL, \
table}
# define EXT_IA5STRING(nid) { nid, 0, ASN1_ITEM_ref(ASN1_IA5STRING), \
0,0,0,0, \
(X509V3_EXT_I2S)i2s_ASN1_IA5STRING, \
(X509V3_EXT_S2I)s2i_ASN1_IA5STRING, \
0,0,0,0, \
NULL}
# define EXT_END { -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
/* X509_PURPOSE stuff */
# define EXFLAG_BCONS 0x1
# define EXFLAG_KUSAGE 0x2
# define EXFLAG_XKUSAGE 0x4
# define EXFLAG_NSCERT 0x8
# define EXFLAG_CA 0x10
/* Really self issued not necessarily self signed */
# define EXFLAG_SI 0x20
# define EXFLAG_V1 0x40
# define EXFLAG_INVALID 0x80
/* EXFLAG_SET is set to indicate that some values have been precomputed */
# define EXFLAG_SET 0x100
# define EXFLAG_CRITICAL 0x200
# define EXFLAG_PROXY 0x400
# define EXFLAG_INVALID_POLICY 0x800
# define EXFLAG_FRESHEST 0x1000
/* Self signed */
# define EXFLAG_SS 0x2000
# define KU_DIGITAL_SIGNATURE 0x0080
# define KU_NON_REPUDIATION 0x0040
# define KU_KEY_ENCIPHERMENT 0x0020
# define KU_DATA_ENCIPHERMENT 0x0010
# define KU_KEY_AGREEMENT 0x0008
# define KU_KEY_CERT_SIGN 0x0004
# define KU_CRL_SIGN 0x0002
# define KU_ENCIPHER_ONLY 0x0001
# define KU_DECIPHER_ONLY 0x8000
# define NS_SSL_CLIENT 0x80
# define NS_SSL_SERVER 0x40
# define NS_SMIME 0x20
# define NS_OBJSIGN 0x10
# define NS_SSL_CA 0x04
# define NS_SMIME_CA 0x02
# define NS_OBJSIGN_CA 0x01
# define NS_ANY_CA (NS_SSL_CA|NS_SMIME_CA|NS_OBJSIGN_CA)
# define XKU_SSL_SERVER 0x1
# define XKU_SSL_CLIENT 0x2
# define XKU_SMIME 0x4
# define XKU_CODE_SIGN 0x8
# define XKU_SGC 0x10
# define XKU_OCSP_SIGN 0x20
# define XKU_TIMESTAMP 0x40
# define XKU_DVCS 0x80
# define XKU_ANYEKU 0x100
# define X509_PURPOSE_DYNAMIC 0x1
# define X509_PURPOSE_DYNAMIC_NAME 0x2
typedef struct x509_purpose_st {
int purpose;
int trust; /* Default trust ID */
int flags;
int (*check_purpose) (const struct x509_purpose_st *, const X509 *, int);
char *name;
char *sname;
void *usr_data;
} X509_PURPOSE;
# define X509_PURPOSE_SSL_CLIENT 1
# define X509_PURPOSE_SSL_SERVER 2
# define X509_PURPOSE_NS_SSL_SERVER 3
# define X509_PURPOSE_SMIME_SIGN 4
# define X509_PURPOSE_SMIME_ENCRYPT 5
# define X509_PURPOSE_CRL_SIGN 6
# define X509_PURPOSE_ANY 7
# define X509_PURPOSE_OCSP_HELPER 8
# define X509_PURPOSE_TIMESTAMP_SIGN 9
# define X509_PURPOSE_MIN 1
# define X509_PURPOSE_MAX 9
/* Flags for X509V3_EXT_print() */
# define X509V3_EXT_UNKNOWN_MASK (0xfL << 16)
/* Return error for unknown extensions */
# define X509V3_EXT_DEFAULT 0
/* Print error for unknown extensions */
# define X509V3_EXT_ERROR_UNKNOWN (1L << 16)
/* ASN1 parse unknown extensions */
# define X509V3_EXT_PARSE_UNKNOWN (2L << 16)
/* BIO_dump unknown extensions */
# define X509V3_EXT_DUMP_UNKNOWN (3L << 16)
/* Flags for X509V3_add1_i2d */
# define X509V3_ADD_OP_MASK 0xfL
# define X509V3_ADD_DEFAULT 0L
# define X509V3_ADD_APPEND 1L
# define X509V3_ADD_REPLACE 2L
# define X509V3_ADD_REPLACE_EXISTING 3L
# define X509V3_ADD_KEEP_EXISTING 4L
# define X509V3_ADD_DELETE 5L
# define X509V3_ADD_SILENT 0x10
DEFINE_STACK_OF(X509_PURPOSE)
DECLARE_ASN1_FUNCTIONS(BASIC_CONSTRAINTS)
DECLARE_ASN1_FUNCTIONS(SXNET)
DECLARE_ASN1_FUNCTIONS(SXNETID)
int SXNET_add_id_asc(SXNET **psx, const char *zone, const char *user, int userlen);
int SXNET_add_id_ulong(SXNET **psx, unsigned long lzone, const char *user,
int userlen);
int SXNET_add_id_INTEGER(SXNET **psx, ASN1_INTEGER *izone, const char *user,
int userlen);
ASN1_OCTET_STRING *SXNET_get_id_asc(SXNET *sx, const char *zone);
ASN1_OCTET_STRING *SXNET_get_id_ulong(SXNET *sx, unsigned long lzone);
ASN1_OCTET_STRING *SXNET_get_id_INTEGER(SXNET *sx, ASN1_INTEGER *zone);
DECLARE_ASN1_FUNCTIONS(AUTHORITY_KEYID)
DECLARE_ASN1_FUNCTIONS(PKEY_USAGE_PERIOD)
DECLARE_ASN1_FUNCTIONS(GENERAL_NAME)
GENERAL_NAME *GENERAL_NAME_dup(GENERAL_NAME *a);
int GENERAL_NAME_cmp(GENERAL_NAME *a, GENERAL_NAME *b);
ASN1_BIT_STRING *v2i_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx,
STACK_OF(CONF_VALUE) *nval);
STACK_OF(CONF_VALUE) *i2v_ASN1_BIT_STRING(X509V3_EXT_METHOD *method,
ASN1_BIT_STRING *bits,
STACK_OF(CONF_VALUE) *extlist);
char *i2s_ASN1_IA5STRING(X509V3_EXT_METHOD *method, ASN1_IA5STRING *ia5);
ASN1_IA5STRING *s2i_ASN1_IA5STRING(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, const char *str);
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
GENERAL_NAME *gen,
STACK_OF(CONF_VALUE) *ret);
int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen);
DECLARE_ASN1_FUNCTIONS(GENERAL_NAMES)
STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
GENERAL_NAMES *gen,
STACK_OF(CONF_VALUE) *extlist);
GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
DECLARE_ASN1_FUNCTIONS(OTHERNAME)
DECLARE_ASN1_FUNCTIONS(EDIPARTYNAME)
int OTHERNAME_cmp(OTHERNAME *a, OTHERNAME *b);
void GENERAL_NAME_set0_value(GENERAL_NAME *a, int type, void *value);
-void *GENERAL_NAME_get0_value(GENERAL_NAME *a, int *ptype);
+void *GENERAL_NAME_get0_value(const GENERAL_NAME *a, int *ptype);
int GENERAL_NAME_set0_othername(GENERAL_NAME *gen,
ASN1_OBJECT *oid, ASN1_TYPE *value);
-int GENERAL_NAME_get0_otherName(GENERAL_NAME *gen,
+int GENERAL_NAME_get0_otherName(const GENERAL_NAME *gen,
ASN1_OBJECT **poid, ASN1_TYPE **pvalue);
char *i2s_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
const ASN1_OCTET_STRING *ia5);
ASN1_OCTET_STRING *s2i_ASN1_OCTET_STRING(X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, const char *str);
DECLARE_ASN1_FUNCTIONS(EXTENDED_KEY_USAGE)
int i2a_ACCESS_DESCRIPTION(BIO *bp, const ACCESS_DESCRIPTION *a);
DECLARE_ASN1_ALLOC_FUNCTIONS(TLS_FEATURE)
DECLARE_ASN1_FUNCTIONS(CERTIFICATEPOLICIES)
DECLARE_ASN1_FUNCTIONS(POLICYINFO)
DECLARE_ASN1_FUNCTIONS(POLICYQUALINFO)
DECLARE_ASN1_FUNCTIONS(USERNOTICE)
DECLARE_ASN1_FUNCTIONS(NOTICEREF)
DECLARE_ASN1_FUNCTIONS(CRL_DIST_POINTS)
DECLARE_ASN1_FUNCTIONS(DIST_POINT)
DECLARE_ASN1_FUNCTIONS(DIST_POINT_NAME)
DECLARE_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname);
int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc);
int NAME_CONSTRAINTS_check_CN(X509 *x, NAME_CONSTRAINTS *nc);
DECLARE_ASN1_FUNCTIONS(ACCESS_DESCRIPTION)
DECLARE_ASN1_FUNCTIONS(AUTHORITY_INFO_ACCESS)
DECLARE_ASN1_ITEM(POLICY_MAPPING)
DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_MAPPING)
DECLARE_ASN1_ITEM(POLICY_MAPPINGS)
DECLARE_ASN1_ITEM(GENERAL_SUBTREE)
DECLARE_ASN1_ALLOC_FUNCTIONS(GENERAL_SUBTREE)
DECLARE_ASN1_ITEM(NAME_CONSTRAINTS)
DECLARE_ASN1_ALLOC_FUNCTIONS(NAME_CONSTRAINTS)
DECLARE_ASN1_ALLOC_FUNCTIONS(POLICY_CONSTRAINTS)
DECLARE_ASN1_ITEM(POLICY_CONSTRAINTS)
GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, int gen_type,
const char *value, int is_nc);
# ifdef HEADER_CONF_H
GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, CONF_VALUE *cnf);
GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
const X509V3_EXT_METHOD *method,
X509V3_CTX *ctx, CONF_VALUE *cnf,
int is_nc);
void X509V3_conf_free(CONF_VALUE *val);
X509_EXTENSION *X509V3_EXT_nconf_nid(CONF *conf, X509V3_CTX *ctx, int ext_nid,
const char *value);
X509_EXTENSION *X509V3_EXT_nconf(CONF *conf, X509V3_CTX *ctx, const char *name,
const char *value);
int X509V3_EXT_add_nconf_sk(CONF *conf, X509V3_CTX *ctx, const char *section,
STACK_OF(X509_EXTENSION) **sk);
int X509V3_EXT_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
X509 *cert);
int X509V3_EXT_REQ_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
X509_REQ *req);
int X509V3_EXT_CRL_add_nconf(CONF *conf, X509V3_CTX *ctx, const char *section,
X509_CRL *crl);
X509_EXTENSION *X509V3_EXT_conf_nid(LHASH_OF(CONF_VALUE) *conf,
X509V3_CTX *ctx, int ext_nid,
const char *value);
X509_EXTENSION *X509V3_EXT_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
const char *name, const char *value);
int X509V3_EXT_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
const char *section, X509 *cert);
int X509V3_EXT_REQ_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
const char *section, X509_REQ *req);
int X509V3_EXT_CRL_add_conf(LHASH_OF(CONF_VALUE) *conf, X509V3_CTX *ctx,
const char *section, X509_CRL *crl);
int X509V3_add_value_bool_nf(const char *name, int asn1_bool,
STACK_OF(CONF_VALUE) **extlist);
int X509V3_get_value_bool(const CONF_VALUE *value, int *asn1_bool);
int X509V3_get_value_int(const CONF_VALUE *value, ASN1_INTEGER **aint);
void X509V3_set_nconf(X509V3_CTX *ctx, CONF *conf);
void X509V3_set_conf_lhash(X509V3_CTX *ctx, LHASH_OF(CONF_VALUE) *lhash);
# endif
char *X509V3_get_string(X509V3_CTX *ctx, const char *name, const char *section);
STACK_OF(CONF_VALUE) *X509V3_get_section(X509V3_CTX *ctx, const char *section);
void X509V3_string_free(X509V3_CTX *ctx, char *str);
void X509V3_section_free(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *section);
void X509V3_set_ctx(X509V3_CTX *ctx, X509 *issuer, X509 *subject,
X509_REQ *req, X509_CRL *crl, int flags);
int X509V3_add_value(const char *name, const char *value,
STACK_OF(CONF_VALUE) **extlist);
int X509V3_add_value_uchar(const char *name, const unsigned char *value,
STACK_OF(CONF_VALUE) **extlist);
int X509V3_add_value_bool(const char *name, int asn1_bool,
STACK_OF(CONF_VALUE) **extlist);
int X509V3_add_value_int(const char *name, const ASN1_INTEGER *aint,
STACK_OF(CONF_VALUE) **extlist);
char *i2s_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const ASN1_INTEGER *aint);
ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *meth, const char *value);
char *i2s_ASN1_ENUMERATED(X509V3_EXT_METHOD *meth, const ASN1_ENUMERATED *aint);
char *i2s_ASN1_ENUMERATED_TABLE(X509V3_EXT_METHOD *meth,
const ASN1_ENUMERATED *aint);
int X509V3_EXT_add(X509V3_EXT_METHOD *ext);
int X509V3_EXT_add_list(X509V3_EXT_METHOD *extlist);
int X509V3_EXT_add_alias(int nid_to, int nid_from);
void X509V3_EXT_cleanup(void);
const X509V3_EXT_METHOD *X509V3_EXT_get(X509_EXTENSION *ext);
const X509V3_EXT_METHOD *X509V3_EXT_get_nid(int nid);
int X509V3_add_standard_extensions(void);
STACK_OF(CONF_VALUE) *X509V3_parse_list(const char *line);
void *X509V3_EXT_d2i(X509_EXTENSION *ext);
void *X509V3_get_d2i(const STACK_OF(X509_EXTENSION) *x, int nid, int *crit,
int *idx);
X509_EXTENSION *X509V3_EXT_i2d(int ext_nid, int crit, void *ext_struc);
int X509V3_add1_i2d(STACK_OF(X509_EXTENSION) **x, int nid, void *value,
int crit, unsigned long flags);
#if OPENSSL_API_COMPAT < 0x10100000L
/* The new declarations are in crypto.h, but the old ones were here. */
# define hex_to_string OPENSSL_buf2hexstr
# define string_to_hex OPENSSL_hexstr2buf
#endif
void X509V3_EXT_val_prn(BIO *out, STACK_OF(CONF_VALUE) *val, int indent,
int ml);
int X509V3_EXT_print(BIO *out, X509_EXTENSION *ext, unsigned long flag,
int indent);
#ifndef OPENSSL_NO_STDIO
int X509V3_EXT_print_fp(FILE *out, X509_EXTENSION *ext, int flag, int indent);
#endif
int X509V3_extensions_print(BIO *out, const char *title,
const STACK_OF(X509_EXTENSION) *exts,
unsigned long flag, int indent);
int X509_check_ca(X509 *x);
int X509_check_purpose(X509 *x, int id, int ca);
int X509_supported_extension(X509_EXTENSION *ex);
int X509_PURPOSE_set(int *p, int purpose);
int X509_check_issued(X509 *issuer, X509 *subject);
int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid);
void X509_set_proxy_flag(X509 *x);
void X509_set_proxy_pathlen(X509 *x, long l);
long X509_get_proxy_pathlen(X509 *x);
uint32_t X509_get_extension_flags(X509 *x);
uint32_t X509_get_key_usage(X509 *x);
uint32_t X509_get_extended_key_usage(X509 *x);
const ASN1_OCTET_STRING *X509_get0_subject_key_id(X509 *x);
const ASN1_OCTET_STRING *X509_get0_authority_key_id(X509 *x);
int X509_PURPOSE_get_count(void);
X509_PURPOSE *X509_PURPOSE_get0(int idx);
int X509_PURPOSE_get_by_sname(const char *sname);
int X509_PURPOSE_get_by_id(int id);
int X509_PURPOSE_add(int id, int trust, int flags,
int (*ck) (const X509_PURPOSE *, const X509 *, int),
const char *name, const char *sname, void *arg);
char *X509_PURPOSE_get0_name(const X509_PURPOSE *xp);
char *X509_PURPOSE_get0_sname(const X509_PURPOSE *xp);
int X509_PURPOSE_get_trust(const X509_PURPOSE *xp);
void X509_PURPOSE_cleanup(void);
int X509_PURPOSE_get_id(const X509_PURPOSE *);
STACK_OF(OPENSSL_STRING) *X509_get1_email(X509 *x);
STACK_OF(OPENSSL_STRING) *X509_REQ_get1_email(X509_REQ *x);
void X509_email_free(STACK_OF(OPENSSL_STRING) *sk);
STACK_OF(OPENSSL_STRING) *X509_get1_ocsp(X509 *x);
/* Flags for X509_check_* functions */
/*
* Always check subject name for host match even if subject alt names present
*/
# define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT 0x1
/* Disable wildcard matching for dnsName fields and common name. */
# define X509_CHECK_FLAG_NO_WILDCARDS 0x2
/* Wildcards must not match a partial label. */
# define X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS 0x4
/* Allow (non-partial) wildcards to match multiple labels. */
# define X509_CHECK_FLAG_MULTI_LABEL_WILDCARDS 0x8
/* Constraint verifier subdomain patterns to match a single labels. */
# define X509_CHECK_FLAG_SINGLE_LABEL_SUBDOMAINS 0x10
/* Never check the subject CN */
# define X509_CHECK_FLAG_NEVER_CHECK_SUBJECT 0x20
/*
* Match reference identifiers starting with "." to any sub-domain.
* This is a non-public flag, turned on implicitly when the subject
* reference identity is a DNS name.
*/
# define _X509_CHECK_FLAG_DOT_SUBDOMAINS 0x8000
int X509_check_host(X509 *x, const char *chk, size_t chklen,
unsigned int flags, char **peername);
int X509_check_email(X509 *x, const char *chk, size_t chklen,
unsigned int flags);
int X509_check_ip(X509 *x, const unsigned char *chk, size_t chklen,
unsigned int flags);
int X509_check_ip_asc(X509 *x, const char *ipasc, unsigned int flags);
ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc);
ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc);
int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE) *dn_sk,
unsigned long chtype);
void X509_POLICY_NODE_print(BIO *out, X509_POLICY_NODE *node, int indent);
DEFINE_STACK_OF(X509_POLICY_NODE)
#ifndef OPENSSL_NO_RFC3779
typedef struct ASRange_st {
ASN1_INTEGER *min, *max;
} ASRange;
# define ASIdOrRange_id 0
# define ASIdOrRange_range 1
typedef struct ASIdOrRange_st {
int type;
union {
ASN1_INTEGER *id;
ASRange *range;
} u;
} ASIdOrRange;
typedef STACK_OF(ASIdOrRange) ASIdOrRanges;
DEFINE_STACK_OF(ASIdOrRange)
# define ASIdentifierChoice_inherit 0
# define ASIdentifierChoice_asIdsOrRanges 1
typedef struct ASIdentifierChoice_st {
int type;
union {
ASN1_NULL *inherit;
ASIdOrRanges *asIdsOrRanges;
} u;
} ASIdentifierChoice;
typedef struct ASIdentifiers_st {
ASIdentifierChoice *asnum, *rdi;
} ASIdentifiers;
DECLARE_ASN1_FUNCTIONS(ASRange)
DECLARE_ASN1_FUNCTIONS(ASIdOrRange)
DECLARE_ASN1_FUNCTIONS(ASIdentifierChoice)
DECLARE_ASN1_FUNCTIONS(ASIdentifiers)
typedef struct IPAddressRange_st {
ASN1_BIT_STRING *min, *max;
} IPAddressRange;
# define IPAddressOrRange_addressPrefix 0
# define IPAddressOrRange_addressRange 1
typedef struct IPAddressOrRange_st {
int type;
union {
ASN1_BIT_STRING *addressPrefix;
IPAddressRange *addressRange;
} u;
} IPAddressOrRange;
typedef STACK_OF(IPAddressOrRange) IPAddressOrRanges;
DEFINE_STACK_OF(IPAddressOrRange)
# define IPAddressChoice_inherit 0
# define IPAddressChoice_addressesOrRanges 1
typedef struct IPAddressChoice_st {
int type;
union {
ASN1_NULL *inherit;
IPAddressOrRanges *addressesOrRanges;
} u;
} IPAddressChoice;
typedef struct IPAddressFamily_st {
ASN1_OCTET_STRING *addressFamily;
IPAddressChoice *ipAddressChoice;
} IPAddressFamily;
typedef STACK_OF(IPAddressFamily) IPAddrBlocks;
DEFINE_STACK_OF(IPAddressFamily)
DECLARE_ASN1_FUNCTIONS(IPAddressRange)
DECLARE_ASN1_FUNCTIONS(IPAddressOrRange)
DECLARE_ASN1_FUNCTIONS(IPAddressChoice)
DECLARE_ASN1_FUNCTIONS(IPAddressFamily)
/*
* API tag for elements of the ASIdentifer SEQUENCE.
*/
# define V3_ASID_ASNUM 0
# define V3_ASID_RDI 1
/*
* AFI values, assigned by IANA. It'd be nice to make the AFI
* handling code totally generic, but there are too many little things
* that would need to be defined for other address families for it to
* be worth the trouble.
*/
# define IANA_AFI_IPV4 1
# define IANA_AFI_IPV6 2
/*
* Utilities to construct and extract values from RFC3779 extensions,
* since some of the encodings (particularly for IP address prefixes
* and ranges) are a bit tedious to work with directly.
*/
int X509v3_asid_add_inherit(ASIdentifiers *asid, int which);
int X509v3_asid_add_id_or_range(ASIdentifiers *asid, int which,
ASN1_INTEGER *min, ASN1_INTEGER *max);
int X509v3_addr_add_inherit(IPAddrBlocks *addr,
const unsigned afi, const unsigned *safi);
int X509v3_addr_add_prefix(IPAddrBlocks *addr,
const unsigned afi, const unsigned *safi,
unsigned char *a, const int prefixlen);
int X509v3_addr_add_range(IPAddrBlocks *addr,
const unsigned afi, const unsigned *safi,
unsigned char *min, unsigned char *max);
unsigned X509v3_addr_get_afi(const IPAddressFamily *f);
int X509v3_addr_get_range(IPAddressOrRange *aor, const unsigned afi,
unsigned char *min, unsigned char *max,
const int length);
/*
* Canonical forms.
*/
int X509v3_asid_is_canonical(ASIdentifiers *asid);
int X509v3_addr_is_canonical(IPAddrBlocks *addr);
int X509v3_asid_canonize(ASIdentifiers *asid);
int X509v3_addr_canonize(IPAddrBlocks *addr);
/*
* Tests for inheritance and containment.
*/
int X509v3_asid_inherits(ASIdentifiers *asid);
int X509v3_addr_inherits(IPAddrBlocks *addr);
int X509v3_asid_subset(ASIdentifiers *a, ASIdentifiers *b);
int X509v3_addr_subset(IPAddrBlocks *a, IPAddrBlocks *b);
/*
* Check whether RFC 3779 extensions nest properly in chains.
*/
int X509v3_asid_validate_path(X509_STORE_CTX *);
int X509v3_addr_validate_path(X509_STORE_CTX *);
int X509v3_asid_validate_resource_set(STACK_OF(X509) *chain,
ASIdentifiers *ext,
int allow_inheritance);
int X509v3_addr_validate_resource_set(STACK_OF(X509) *chain,
IPAddrBlocks *ext, int allow_inheritance);
#endif /* OPENSSL_NO_RFC3779 */
DEFINE_STACK_OF(ASN1_STRING)
/*
* Admission Syntax
*/
typedef struct NamingAuthority_st NAMING_AUTHORITY;
typedef struct ProfessionInfo_st PROFESSION_INFO;
typedef struct Admissions_st ADMISSIONS;
typedef struct AdmissionSyntax_st ADMISSION_SYNTAX;
DECLARE_ASN1_FUNCTIONS(NAMING_AUTHORITY)
DECLARE_ASN1_FUNCTIONS(PROFESSION_INFO)
DECLARE_ASN1_FUNCTIONS(ADMISSIONS)
DECLARE_ASN1_FUNCTIONS(ADMISSION_SYNTAX)
DEFINE_STACK_OF(ADMISSIONS)
DEFINE_STACK_OF(PROFESSION_INFO)
typedef STACK_OF(PROFESSION_INFO) PROFESSION_INFOS;
const ASN1_OBJECT *NAMING_AUTHORITY_get0_authorityId(
const NAMING_AUTHORITY *n);
const ASN1_IA5STRING *NAMING_AUTHORITY_get0_authorityURL(
const NAMING_AUTHORITY *n);
const ASN1_STRING *NAMING_AUTHORITY_get0_authorityText(
const NAMING_AUTHORITY *n);
void NAMING_AUTHORITY_set0_authorityId(NAMING_AUTHORITY *n,
ASN1_OBJECT* namingAuthorityId);
void NAMING_AUTHORITY_set0_authorityURL(NAMING_AUTHORITY *n,
ASN1_IA5STRING* namingAuthorityUrl);
void NAMING_AUTHORITY_set0_authorityText(NAMING_AUTHORITY *n,
ASN1_STRING* namingAuthorityText);
const GENERAL_NAME *ADMISSION_SYNTAX_get0_admissionAuthority(
const ADMISSION_SYNTAX *as);
void ADMISSION_SYNTAX_set0_admissionAuthority(
ADMISSION_SYNTAX *as, GENERAL_NAME *aa);
const STACK_OF(ADMISSIONS) *ADMISSION_SYNTAX_get0_contentsOfAdmissions(
const ADMISSION_SYNTAX *as);
void ADMISSION_SYNTAX_set0_contentsOfAdmissions(
ADMISSION_SYNTAX *as, STACK_OF(ADMISSIONS) *a);
const GENERAL_NAME *ADMISSIONS_get0_admissionAuthority(const ADMISSIONS *a);
void ADMISSIONS_set0_admissionAuthority(ADMISSIONS *a, GENERAL_NAME *aa);
const NAMING_AUTHORITY *ADMISSIONS_get0_namingAuthority(const ADMISSIONS *a);
void ADMISSIONS_set0_namingAuthority(ADMISSIONS *a, NAMING_AUTHORITY *na);
const PROFESSION_INFOS *ADMISSIONS_get0_professionInfos(const ADMISSIONS *a);
void ADMISSIONS_set0_professionInfos(ADMISSIONS *a, PROFESSION_INFOS *pi);
const ASN1_OCTET_STRING *PROFESSION_INFO_get0_addProfessionInfo(
const PROFESSION_INFO *pi);
void PROFESSION_INFO_set0_addProfessionInfo(
PROFESSION_INFO *pi, ASN1_OCTET_STRING *aos);
const NAMING_AUTHORITY *PROFESSION_INFO_get0_namingAuthority(
const PROFESSION_INFO *pi);
void PROFESSION_INFO_set0_namingAuthority(
PROFESSION_INFO *pi, NAMING_AUTHORITY *na);
const STACK_OF(ASN1_STRING) *PROFESSION_INFO_get0_professionItems(
const PROFESSION_INFO *pi);
void PROFESSION_INFO_set0_professionItems(
PROFESSION_INFO *pi, STACK_OF(ASN1_STRING) *as);
const STACK_OF(ASN1_OBJECT) *PROFESSION_INFO_get0_professionOIDs(
const PROFESSION_INFO *pi);
void PROFESSION_INFO_set0_professionOIDs(
PROFESSION_INFO *pi, STACK_OF(ASN1_OBJECT) *po);
const ASN1_PRINTABLESTRING *PROFESSION_INFO_get0_registrationNumber(
const PROFESSION_INFO *pi);
void PROFESSION_INFO_set0_registrationNumber(
PROFESSION_INFO *pi, ASN1_PRINTABLESTRING *rn);
# ifdef __cplusplus
}
# endif
#endif
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 4440a9ffe9be..f559bc10eff4 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1,5581 +1,5586 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "ssl_locl.h"
#include <openssl/objects.h>
#include <openssl/x509v3.h>
#include <openssl/rand.h>
#include <openssl/rand_drbg.h>
#include <openssl/ocsp.h>
#include <openssl/dh.h>
#include <openssl/engine.h>
#include <openssl/async.h>
#include <openssl/ct.h>
#include "internal/cryptlib.h"
#include "internal/refcount.h"
const char SSL_version_str[] = OPENSSL_VERSION_TEXT;
static int ssl_undefined_function_1(SSL *ssl, SSL3_RECORD *r, size_t s, int t)
{
(void)r;
(void)s;
(void)t;
return ssl_undefined_function(ssl);
}
static int ssl_undefined_function_2(SSL *ssl, SSL3_RECORD *r, unsigned char *s,
int t)
{
(void)r;
(void)s;
(void)t;
return ssl_undefined_function(ssl);
}
static int ssl_undefined_function_3(SSL *ssl, unsigned char *r,
unsigned char *s, size_t t, size_t *u)
{
(void)r;
(void)s;
(void)t;
(void)u;
return ssl_undefined_function(ssl);
}
static int ssl_undefined_function_4(SSL *ssl, int r)
{
(void)r;
return ssl_undefined_function(ssl);
}
static size_t ssl_undefined_function_5(SSL *ssl, const char *r, size_t s,
unsigned char *t)
{
(void)r;
(void)s;
(void)t;
return ssl_undefined_function(ssl);
}
static int ssl_undefined_function_6(int r)
{
(void)r;
return ssl_undefined_function(NULL);
}
static int ssl_undefined_function_7(SSL *ssl, unsigned char *r, size_t s,
const char *t, size_t u,
const unsigned char *v, size_t w, int x)
{
(void)r;
(void)s;
(void)t;
(void)u;
(void)v;
(void)w;
(void)x;
return ssl_undefined_function(ssl);
}
SSL3_ENC_METHOD ssl3_undef_enc_method = {
ssl_undefined_function_1,
ssl_undefined_function_2,
ssl_undefined_function,
ssl_undefined_function_3,
ssl_undefined_function_4,
ssl_undefined_function_5,
NULL, /* client_finished_label */
0, /* client_finished_label_len */
NULL, /* server_finished_label */
0, /* server_finished_label_len */
ssl_undefined_function_6,
ssl_undefined_function_7,
};
struct ssl_async_args {
SSL *s;
void *buf;
size_t num;
enum { READFUNC, WRITEFUNC, OTHERFUNC } type;
union {
int (*func_read) (SSL *, void *, size_t, size_t *);
int (*func_write) (SSL *, const void *, size_t, size_t *);
int (*func_other) (SSL *);
} f;
};
static const struct {
uint8_t mtype;
uint8_t ord;
int nid;
} dane_mds[] = {
{
DANETLS_MATCHING_FULL, 0, NID_undef
},
{
DANETLS_MATCHING_2256, 1, NID_sha256
},
{
DANETLS_MATCHING_2512, 2, NID_sha512
},
};
static int dane_ctx_enable(struct dane_ctx_st *dctx)
{
const EVP_MD **mdevp;
uint8_t *mdord;
uint8_t mdmax = DANETLS_MATCHING_LAST;
int n = ((int)mdmax) + 1; /* int to handle PrivMatch(255) */
size_t i;
if (dctx->mdevp != NULL)
return 1;
mdevp = OPENSSL_zalloc(n * sizeof(*mdevp));
mdord = OPENSSL_zalloc(n * sizeof(*mdord));
if (mdord == NULL || mdevp == NULL) {
OPENSSL_free(mdord);
OPENSSL_free(mdevp);
SSLerr(SSL_F_DANE_CTX_ENABLE, ERR_R_MALLOC_FAILURE);
return 0;
}
/* Install default entries */
for (i = 0; i < OSSL_NELEM(dane_mds); ++i) {
const EVP_MD *md;
if (dane_mds[i].nid == NID_undef ||
(md = EVP_get_digestbynid(dane_mds[i].nid)) == NULL)
continue;
mdevp[dane_mds[i].mtype] = md;
mdord[dane_mds[i].mtype] = dane_mds[i].ord;
}
dctx->mdevp = mdevp;
dctx->mdord = mdord;
dctx->mdmax = mdmax;
return 1;
}
static void dane_ctx_final(struct dane_ctx_st *dctx)
{
OPENSSL_free(dctx->mdevp);
dctx->mdevp = NULL;
OPENSSL_free(dctx->mdord);
dctx->mdord = NULL;
dctx->mdmax = 0;
}
static void tlsa_free(danetls_record *t)
{
if (t == NULL)
return;
OPENSSL_free(t->data);
EVP_PKEY_free(t->spki);
OPENSSL_free(t);
}
static void dane_final(SSL_DANE *dane)
{
sk_danetls_record_pop_free(dane->trecs, tlsa_free);
dane->trecs = NULL;
sk_X509_pop_free(dane->certs, X509_free);
dane->certs = NULL;
X509_free(dane->mcert);
dane->mcert = NULL;
dane->mtlsa = NULL;
dane->mdpth = -1;
dane->pdpth = -1;
}
/*
* dane_copy - Copy dane configuration, sans verification state.
*/
static int ssl_dane_dup(SSL *to, SSL *from)
{
int num;
int i;
if (!DANETLS_ENABLED(&from->dane))
return 1;
num = sk_danetls_record_num(from->dane.trecs);
dane_final(&to->dane);
to->dane.flags = from->dane.flags;
to->dane.dctx = &to->ctx->dane;
to->dane.trecs = sk_danetls_record_new_reserve(NULL, num);
if (to->dane.trecs == NULL) {
SSLerr(SSL_F_SSL_DANE_DUP, ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < num; ++i) {
danetls_record *t = sk_danetls_record_value(from->dane.trecs, i);
if (SSL_dane_tlsa_add(to, t->usage, t->selector, t->mtype,
t->data, t->dlen) <= 0)
return 0;
}
return 1;
}
static int dane_mtype_set(struct dane_ctx_st *dctx,
const EVP_MD *md, uint8_t mtype, uint8_t ord)
{
int i;
if (mtype == DANETLS_MATCHING_FULL && md != NULL) {
SSLerr(SSL_F_DANE_MTYPE_SET, SSL_R_DANE_CANNOT_OVERRIDE_MTYPE_FULL);
return 0;
}
if (mtype > dctx->mdmax) {
const EVP_MD **mdevp;
uint8_t *mdord;
int n = ((int)mtype) + 1;
mdevp = OPENSSL_realloc(dctx->mdevp, n * sizeof(*mdevp));
if (mdevp == NULL) {
SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE);
return -1;
}
dctx->mdevp = mdevp;
mdord = OPENSSL_realloc(dctx->mdord, n * sizeof(*mdord));
if (mdord == NULL) {
SSLerr(SSL_F_DANE_MTYPE_SET, ERR_R_MALLOC_FAILURE);
return -1;
}
dctx->mdord = mdord;
/* Zero-fill any gaps */
for (i = dctx->mdmax + 1; i < mtype; ++i) {
mdevp[i] = NULL;
mdord[i] = 0;
}
dctx->mdmax = mtype;
}
dctx->mdevp[mtype] = md;
/* Coerce ordinal of disabled matching types to 0 */
dctx->mdord[mtype] = (md == NULL) ? 0 : ord;
return 1;
}
static const EVP_MD *tlsa_md_get(SSL_DANE *dane, uint8_t mtype)
{
if (mtype > dane->dctx->mdmax)
return NULL;
return dane->dctx->mdevp[mtype];
}
static int dane_tlsa_add(SSL_DANE *dane,
uint8_t usage,
uint8_t selector,
uint8_t mtype, unsigned const char *data, size_t dlen)
{
danetls_record *t;
const EVP_MD *md = NULL;
int ilen = (int)dlen;
int i;
int num;
if (dane->trecs == NULL) {
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_NOT_ENABLED);
return -1;
}
if (ilen < 0 || dlen != (size_t)ilen) {
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DATA_LENGTH);
return 0;
}
if (usage > DANETLS_USAGE_LAST) {
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE_USAGE);
return 0;
}
if (selector > DANETLS_SELECTOR_LAST) {
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_SELECTOR);
return 0;
}
if (mtype != DANETLS_MATCHING_FULL) {
md = tlsa_md_get(dane, mtype);
if (md == NULL) {
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_MATCHING_TYPE);
return 0;
}
}
if (md != NULL && dlen != (size_t)EVP_MD_size(md)) {
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_DIGEST_LENGTH);
return 0;
}
if (!data) {
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_NULL_DATA);
return 0;
}
if ((t = OPENSSL_zalloc(sizeof(*t))) == NULL) {
SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
return -1;
}
t->usage = usage;
t->selector = selector;
t->mtype = mtype;
t->data = OPENSSL_malloc(dlen);
if (t->data == NULL) {
tlsa_free(t);
SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
return -1;
}
memcpy(t->data, data, dlen);
t->dlen = dlen;
/* Validate and cache full certificate or public key */
if (mtype == DANETLS_MATCHING_FULL) {
const unsigned char *p = data;
X509 *cert = NULL;
EVP_PKEY *pkey = NULL;
switch (selector) {
case DANETLS_SELECTOR_CERT:
if (!d2i_X509(&cert, &p, ilen) || p < data ||
dlen != (size_t)(p - data)) {
tlsa_free(t);
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
return 0;
}
if (X509_get0_pubkey(cert) == NULL) {
tlsa_free(t);
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_CERTIFICATE);
return 0;
}
if ((DANETLS_USAGE_BIT(usage) & DANETLS_TA_MASK) == 0) {
X509_free(cert);
break;
}
/*
* For usage DANE-TA(2), we support authentication via "2 0 0" TLSA
* records that contain full certificates of trust-anchors that are
* not present in the wire chain. For usage PKIX-TA(0), we augment
* the chain with untrusted Full(0) certificates from DNS, in case
* they are missing from the chain.
*/
if ((dane->certs == NULL &&
(dane->certs = sk_X509_new_null()) == NULL) ||
!sk_X509_push(dane->certs, cert)) {
SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
X509_free(cert);
tlsa_free(t);
return -1;
}
break;
case DANETLS_SELECTOR_SPKI:
if (!d2i_PUBKEY(&pkey, &p, ilen) || p < data ||
dlen != (size_t)(p - data)) {
tlsa_free(t);
SSLerr(SSL_F_DANE_TLSA_ADD, SSL_R_DANE_TLSA_BAD_PUBLIC_KEY);
return 0;
}
/*
* For usage DANE-TA(2), we support authentication via "2 1 0" TLSA
* records that contain full bare keys of trust-anchors that are
* not present in the wire chain.
*/
if (usage == DANETLS_USAGE_DANE_TA)
t->spki = pkey;
else
EVP_PKEY_free(pkey);
break;
}
}
/*-
* Find the right insertion point for the new record.
*
* See crypto/x509/x509_vfy.c. We sort DANE-EE(3) records first, so that
* they can be processed first, as they require no chain building, and no
* expiration or hostname checks. Because DANE-EE(3) is numerically
* largest, this is accomplished via descending sort by "usage".
*
* We also sort in descending order by matching ordinal to simplify
* the implementation of digest agility in the verification code.
*
* The choice of order for the selector is not significant, so we
* use the same descending order for consistency.
*/
num = sk_danetls_record_num(dane->trecs);
for (i = 0; i < num; ++i) {
danetls_record *rec = sk_danetls_record_value(dane->trecs, i);
if (rec->usage > usage)
continue;
if (rec->usage < usage)
break;
if (rec->selector > selector)
continue;
if (rec->selector < selector)
break;
if (dane->dctx->mdord[rec->mtype] > dane->dctx->mdord[mtype])
continue;
break;
}
if (!sk_danetls_record_insert(dane->trecs, t, i)) {
tlsa_free(t);
SSLerr(SSL_F_DANE_TLSA_ADD, ERR_R_MALLOC_FAILURE);
return -1;
}
dane->umask |= DANETLS_USAGE_BIT(usage);
return 1;
}
/*
* Return 0 if there is only one version configured and it was disabled
* at configure time. Return 1 otherwise.
*/
static int ssl_check_allowed_versions(int min_version, int max_version)
{
int minisdtls = 0, maxisdtls = 0;
/* Figure out if we're doing DTLS versions or TLS versions */
if (min_version == DTLS1_BAD_VER
|| min_version >> 8 == DTLS1_VERSION_MAJOR)
minisdtls = 1;
if (max_version == DTLS1_BAD_VER
|| max_version >> 8 == DTLS1_VERSION_MAJOR)
maxisdtls = 1;
/* A wildcard version of 0 could be DTLS or TLS. */
if ((minisdtls && !maxisdtls && max_version != 0)
|| (maxisdtls && !minisdtls && min_version != 0)) {
/* Mixing DTLS and TLS versions will lead to sadness; deny it. */
return 0;
}
if (minisdtls || maxisdtls) {
/* Do DTLS version checks. */
if (min_version == 0)
/* Ignore DTLS1_BAD_VER */
min_version = DTLS1_VERSION;
if (max_version == 0)
max_version = DTLS1_2_VERSION;
#ifdef OPENSSL_NO_DTLS1_2
if (max_version == DTLS1_2_VERSION)
max_version = DTLS1_VERSION;
#endif
#ifdef OPENSSL_NO_DTLS1
if (min_version == DTLS1_VERSION)
min_version = DTLS1_2_VERSION;
#endif
/* Done massaging versions; do the check. */
if (0
#ifdef OPENSSL_NO_DTLS1
|| (DTLS_VERSION_GE(min_version, DTLS1_VERSION)
&& DTLS_VERSION_GE(DTLS1_VERSION, max_version))
#endif
#ifdef OPENSSL_NO_DTLS1_2
|| (DTLS_VERSION_GE(min_version, DTLS1_2_VERSION)
&& DTLS_VERSION_GE(DTLS1_2_VERSION, max_version))
#endif
)
return 0;
} else {
/* Regular TLS version checks. */
if (min_version == 0)
min_version = SSL3_VERSION;
if (max_version == 0)
max_version = TLS1_3_VERSION;
#ifdef OPENSSL_NO_TLS1_3
if (max_version == TLS1_3_VERSION)
max_version = TLS1_2_VERSION;
#endif
#ifdef OPENSSL_NO_TLS1_2
if (max_version == TLS1_2_VERSION)
max_version = TLS1_1_VERSION;
#endif
#ifdef OPENSSL_NO_TLS1_1
if (max_version == TLS1_1_VERSION)
max_version = TLS1_VERSION;
#endif
#ifdef OPENSSL_NO_TLS1
if (max_version == TLS1_VERSION)
max_version = SSL3_VERSION;
#endif
#ifdef OPENSSL_NO_SSL3
if (min_version == SSL3_VERSION)
min_version = TLS1_VERSION;
#endif
#ifdef OPENSSL_NO_TLS1
if (min_version == TLS1_VERSION)
min_version = TLS1_1_VERSION;
#endif
#ifdef OPENSSL_NO_TLS1_1
if (min_version == TLS1_1_VERSION)
min_version = TLS1_2_VERSION;
#endif
#ifdef OPENSSL_NO_TLS1_2
if (min_version == TLS1_2_VERSION)
min_version = TLS1_3_VERSION;
#endif
/* Done massaging versions; do the check. */
if (0
#ifdef OPENSSL_NO_SSL3
|| (min_version <= SSL3_VERSION && SSL3_VERSION <= max_version)
#endif
#ifdef OPENSSL_NO_TLS1
|| (min_version <= TLS1_VERSION && TLS1_VERSION <= max_version)
#endif
#ifdef OPENSSL_NO_TLS1_1
|| (min_version <= TLS1_1_VERSION && TLS1_1_VERSION <= max_version)
#endif
#ifdef OPENSSL_NO_TLS1_2
|| (min_version <= TLS1_2_VERSION && TLS1_2_VERSION <= max_version)
#endif
#ifdef OPENSSL_NO_TLS1_3
|| (min_version <= TLS1_3_VERSION && TLS1_3_VERSION <= max_version)
#endif
)
return 0;
}
return 1;
}
static void clear_ciphers(SSL *s)
{
/* clear the current cipher */
ssl_clear_cipher_ctx(s);
ssl_clear_hash_ctx(&s->read_hash);
ssl_clear_hash_ctx(&s->write_hash);
}
int SSL_clear(SSL *s)
{
if (s->method == NULL) {
SSLerr(SSL_F_SSL_CLEAR, SSL_R_NO_METHOD_SPECIFIED);
return 0;
}
if (ssl_clear_bad_session(s)) {
SSL_SESSION_free(s->session);
s->session = NULL;
}
SSL_SESSION_free(s->psksession);
s->psksession = NULL;
OPENSSL_free(s->psksession_id);
s->psksession_id = NULL;
s->psksession_id_len = 0;
s->hello_retry_request = 0;
s->sent_tickets = 0;
s->error = 0;
s->hit = 0;
s->shutdown = 0;
if (s->renegotiate) {
SSLerr(SSL_F_SSL_CLEAR, ERR_R_INTERNAL_ERROR);
return 0;
}
ossl_statem_clear(s);
s->version = s->method->version;
s->client_version = s->version;
s->rwstate = SSL_NOTHING;
BUF_MEM_free(s->init_buf);
s->init_buf = NULL;
clear_ciphers(s);
s->first_packet = 0;
s->key_update = SSL_KEY_UPDATE_NONE;
EVP_MD_CTX_free(s->pha_dgst);
s->pha_dgst = NULL;
/* Reset DANE verification result state */
s->dane.mdpth = -1;
s->dane.pdpth = -1;
X509_free(s->dane.mcert);
s->dane.mcert = NULL;
s->dane.mtlsa = NULL;
/* Clear the verification result peername */
X509_VERIFY_PARAM_move_peername(s->param, NULL);
/*
* Check to see if we were changed into a different method, if so, revert
* back.
*/
if (s->method != s->ctx->method) {
s->method->ssl_free(s);
s->method = s->ctx->method;
if (!s->method->ssl_new(s))
return 0;
} else {
if (!s->method->ssl_clear(s))
return 0;
}
RECORD_LAYER_clear(&s->rlayer);
return 1;
}
/** Used to change an SSL_CTXs default SSL method type */
int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth)
{
STACK_OF(SSL_CIPHER) *sk;
ctx->method = meth;
if (!SSL_CTX_set_ciphersuites(ctx, TLS_DEFAULT_CIPHERSUITES)) {
SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
return 0;
}
sk = ssl_create_cipher_list(ctx->method,
ctx->tls13_ciphersuites,
&(ctx->cipher_list),
&(ctx->cipher_list_by_id),
SSL_DEFAULT_CIPHER_LIST, ctx->cert);
if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= 0)) {
SSLerr(SSL_F_SSL_CTX_SET_SSL_VERSION, SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
return 0;
}
return 1;
}
SSL *SSL_new(SSL_CTX *ctx)
{
SSL *s;
if (ctx == NULL) {
SSLerr(SSL_F_SSL_NEW, SSL_R_NULL_SSL_CTX);
return NULL;
}
if (ctx->method == NULL) {
SSLerr(SSL_F_SSL_NEW, SSL_R_SSL_CTX_HAS_NO_DEFAULT_SSL_VERSION);
return NULL;
}
s = OPENSSL_zalloc(sizeof(*s));
if (s == NULL)
goto err;
s->references = 1;
s->lock = CRYPTO_THREAD_lock_new();
if (s->lock == NULL) {
OPENSSL_free(s);
s = NULL;
goto err;
}
RECORD_LAYER_init(&s->rlayer, s);
s->options = ctx->options;
s->dane.flags = ctx->dane.flags;
s->min_proto_version = ctx->min_proto_version;
s->max_proto_version = ctx->max_proto_version;
s->mode = ctx->mode;
s->max_cert_list = ctx->max_cert_list;
s->max_early_data = ctx->max_early_data;
s->recv_max_early_data = ctx->recv_max_early_data;
s->num_tickets = ctx->num_tickets;
s->pha_enabled = ctx->pha_enabled;
/* Shallow copy of the ciphersuites stack */
s->tls13_ciphersuites = sk_SSL_CIPHER_dup(ctx->tls13_ciphersuites);
if (s->tls13_ciphersuites == NULL)
goto err;
/*
* Earlier library versions used to copy the pointer to the CERT, not
* its contents; only when setting new parameters for the per-SSL
* copy, ssl_cert_new would be called (and the direct reference to
* the per-SSL_CTX settings would be lost, but those still were
* indirectly accessed for various purposes, and for that reason they
* used to be known as s->ctx->default_cert). Now we don't look at the
* SSL_CTX's CERT after having duplicated it once.
*/
s->cert = ssl_cert_dup(ctx->cert);
if (s->cert == NULL)
goto err;
RECORD_LAYER_set_read_ahead(&s->rlayer, ctx->read_ahead);
s->msg_callback = ctx->msg_callback;
s->msg_callback_arg = ctx->msg_callback_arg;
s->verify_mode = ctx->verify_mode;
s->not_resumable_session_cb = ctx->not_resumable_session_cb;
s->record_padding_cb = ctx->record_padding_cb;
s->record_padding_arg = ctx->record_padding_arg;
s->block_padding = ctx->block_padding;
s->sid_ctx_length = ctx->sid_ctx_length;
if (!ossl_assert(s->sid_ctx_length <= sizeof(s->sid_ctx)))
goto err;
memcpy(&s->sid_ctx, &ctx->sid_ctx, sizeof(s->sid_ctx));
s->verify_callback = ctx->default_verify_callback;
s->generate_session_id = ctx->generate_session_id;
s->param = X509_VERIFY_PARAM_new();
if (s->param == NULL)
goto err;
X509_VERIFY_PARAM_inherit(s->param, ctx->param);
s->quiet_shutdown = ctx->quiet_shutdown;
s->ext.max_fragment_len_mode = ctx->ext.max_fragment_len_mode;
s->max_send_fragment = ctx->max_send_fragment;
s->split_send_fragment = ctx->split_send_fragment;
s->max_pipelines = ctx->max_pipelines;
if (s->max_pipelines > 1)
RECORD_LAYER_set_read_ahead(&s->rlayer, 1);
if (ctx->default_read_buf_len > 0)
SSL_set_default_read_buffer_len(s, ctx->default_read_buf_len);
SSL_CTX_up_ref(ctx);
s->ctx = ctx;
s->ext.debug_cb = 0;
s->ext.debug_arg = NULL;
s->ext.ticket_expected = 0;
s->ext.status_type = ctx->ext.status_type;
s->ext.status_expected = 0;
s->ext.ocsp.ids = NULL;
s->ext.ocsp.exts = NULL;
s->ext.ocsp.resp = NULL;
s->ext.ocsp.resp_len = 0;
SSL_CTX_up_ref(ctx);
s->session_ctx = ctx;
#ifndef OPENSSL_NO_EC
if (ctx->ext.ecpointformats) {
s->ext.ecpointformats =
OPENSSL_memdup(ctx->ext.ecpointformats,
ctx->ext.ecpointformats_len);
if (!s->ext.ecpointformats)
goto err;
s->ext.ecpointformats_len =
ctx->ext.ecpointformats_len;
}
if (ctx->ext.supportedgroups) {
s->ext.supportedgroups =
OPENSSL_memdup(ctx->ext.supportedgroups,
ctx->ext.supportedgroups_len
* sizeof(*ctx->ext.supportedgroups));
if (!s->ext.supportedgroups)
goto err;
s->ext.supportedgroups_len = ctx->ext.supportedgroups_len;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
s->ext.npn = NULL;
#endif
if (s->ctx->ext.alpn) {
s->ext.alpn = OPENSSL_malloc(s->ctx->ext.alpn_len);
if (s->ext.alpn == NULL)
goto err;
memcpy(s->ext.alpn, s->ctx->ext.alpn, s->ctx->ext.alpn_len);
s->ext.alpn_len = s->ctx->ext.alpn_len;
}
s->verified_chain = NULL;
s->verify_result = X509_V_OK;
s->default_passwd_callback = ctx->default_passwd_callback;
s->default_passwd_callback_userdata = ctx->default_passwd_callback_userdata;
s->method = ctx->method;
s->key_update = SSL_KEY_UPDATE_NONE;
s->allow_early_data_cb = ctx->allow_early_data_cb;
s->allow_early_data_cb_data = ctx->allow_early_data_cb_data;
if (!s->method->ssl_new(s))
goto err;
s->server = (ctx->method->ssl_accept == ssl_undefined_function) ? 0 : 1;
if (!SSL_clear(s))
goto err;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data))
goto err;
#ifndef OPENSSL_NO_PSK
s->psk_client_callback = ctx->psk_client_callback;
s->psk_server_callback = ctx->psk_server_callback;
#endif
s->psk_find_session_cb = ctx->psk_find_session_cb;
s->psk_use_session_cb = ctx->psk_use_session_cb;
s->job = NULL;
#ifndef OPENSSL_NO_CT
if (!SSL_set_ct_validation_callback(s, ctx->ct_validation_callback,
ctx->ct_validation_callback_arg))
goto err;
#endif
return s;
err:
SSL_free(s);
SSLerr(SSL_F_SSL_NEW, ERR_R_MALLOC_FAILURE);
return NULL;
}
int SSL_is_dtls(const SSL *s)
{
return SSL_IS_DTLS(s) ? 1 : 0;
}
int SSL_up_ref(SSL *s)
{
int i;
if (CRYPTO_UP_REF(&s->references, &i, s->lock) <= 0)
return 0;
REF_PRINT_COUNT("SSL", s);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
int SSL_CTX_set_session_id_context(SSL_CTX *ctx, const unsigned char *sid_ctx,
unsigned int sid_ctx_len)
{
if (sid_ctx_len > sizeof(ctx->sid_ctx)) {
SSLerr(SSL_F_SSL_CTX_SET_SESSION_ID_CONTEXT,
SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
ctx->sid_ctx_length = sid_ctx_len;
memcpy(ctx->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
}
int SSL_set_session_id_context(SSL *ssl, const unsigned char *sid_ctx,
unsigned int sid_ctx_len)
{
if (sid_ctx_len > SSL_MAX_SID_CTX_LENGTH) {
SSLerr(SSL_F_SSL_SET_SESSION_ID_CONTEXT,
SSL_R_SSL_SESSION_ID_CONTEXT_TOO_LONG);
return 0;
}
ssl->sid_ctx_length = sid_ctx_len;
memcpy(ssl->sid_ctx, sid_ctx, sid_ctx_len);
return 1;
}
int SSL_CTX_set_generate_session_id(SSL_CTX *ctx, GEN_SESSION_CB cb)
{
CRYPTO_THREAD_write_lock(ctx->lock);
ctx->generate_session_id = cb;
CRYPTO_THREAD_unlock(ctx->lock);
return 1;
}
int SSL_set_generate_session_id(SSL *ssl, GEN_SESSION_CB cb)
{
CRYPTO_THREAD_write_lock(ssl->lock);
ssl->generate_session_id = cb;
CRYPTO_THREAD_unlock(ssl->lock);
return 1;
}
int SSL_has_matching_session_id(const SSL *ssl, const unsigned char *id,
unsigned int id_len)
{
/*
* A quick examination of SSL_SESSION_hash and SSL_SESSION_cmp shows how
* we can "construct" a session to give us the desired check - i.e. to
* find if there's a session in the hash table that would conflict with
* any new session built out of this id/id_len and the ssl_version in use
* by this SSL.
*/
SSL_SESSION r, *p;
if (id_len > sizeof(r.session_id))
return 0;
r.ssl_version = ssl->version;
r.session_id_length = id_len;
memcpy(r.session_id, id, id_len);
CRYPTO_THREAD_read_lock(ssl->session_ctx->lock);
p = lh_SSL_SESSION_retrieve(ssl->session_ctx->sessions, &r);
CRYPTO_THREAD_unlock(ssl->session_ctx->lock);
return (p != NULL);
}
int SSL_CTX_set_purpose(SSL_CTX *s, int purpose)
{
return X509_VERIFY_PARAM_set_purpose(s->param, purpose);
}
int SSL_set_purpose(SSL *s, int purpose)
{
return X509_VERIFY_PARAM_set_purpose(s->param, purpose);
}
int SSL_CTX_set_trust(SSL_CTX *s, int trust)
{
return X509_VERIFY_PARAM_set_trust(s->param, trust);
}
int SSL_set_trust(SSL *s, int trust)
{
return X509_VERIFY_PARAM_set_trust(s->param, trust);
}
int SSL_set1_host(SSL *s, const char *hostname)
{
return X509_VERIFY_PARAM_set1_host(s->param, hostname, 0);
}
int SSL_add1_host(SSL *s, const char *hostname)
{
return X509_VERIFY_PARAM_add1_host(s->param, hostname, 0);
}
void SSL_set_hostflags(SSL *s, unsigned int flags)
{
X509_VERIFY_PARAM_set_hostflags(s->param, flags);
}
const char *SSL_get0_peername(SSL *s)
{
return X509_VERIFY_PARAM_get0_peername(s->param);
}
int SSL_CTX_dane_enable(SSL_CTX *ctx)
{
return dane_ctx_enable(&ctx->dane);
}
unsigned long SSL_CTX_dane_set_flags(SSL_CTX *ctx, unsigned long flags)
{
unsigned long orig = ctx->dane.flags;
ctx->dane.flags |= flags;
return orig;
}
unsigned long SSL_CTX_dane_clear_flags(SSL_CTX *ctx, unsigned long flags)
{
unsigned long orig = ctx->dane.flags;
ctx->dane.flags &= ~flags;
return orig;
}
int SSL_dane_enable(SSL *s, const char *basedomain)
{
SSL_DANE *dane = &s->dane;
if (s->ctx->dane.mdmax == 0) {
SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_CONTEXT_NOT_DANE_ENABLED);
return 0;
}
if (dane->trecs != NULL) {
SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_DANE_ALREADY_ENABLED);
return 0;
}
/*
* Default SNI name. This rejects empty names, while set1_host below
* accepts them and disables host name checks. To avoid side-effects with
* invalid input, set the SNI name first.
*/
if (s->ext.hostname == NULL) {
if (!SSL_set_tlsext_host_name(s, basedomain)) {
SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
return -1;
}
}
/* Primary RFC6125 reference identifier */
if (!X509_VERIFY_PARAM_set1_host(s->param, basedomain, 0)) {
SSLerr(SSL_F_SSL_DANE_ENABLE, SSL_R_ERROR_SETTING_TLSA_BASE_DOMAIN);
return -1;
}
dane->mdpth = -1;
dane->pdpth = -1;
dane->dctx = &s->ctx->dane;
dane->trecs = sk_danetls_record_new_null();
if (dane->trecs == NULL) {
SSLerr(SSL_F_SSL_DANE_ENABLE, ERR_R_MALLOC_FAILURE);
return -1;
}
return 1;
}
unsigned long SSL_dane_set_flags(SSL *ssl, unsigned long flags)
{
unsigned long orig = ssl->dane.flags;
ssl->dane.flags |= flags;
return orig;
}
unsigned long SSL_dane_clear_flags(SSL *ssl, unsigned long flags)
{
unsigned long orig = ssl->dane.flags;
ssl->dane.flags &= ~flags;
return orig;
}
int SSL_get0_dane_authority(SSL *s, X509 **mcert, EVP_PKEY **mspki)
{
SSL_DANE *dane = &s->dane;
if (!DANETLS_ENABLED(dane) || s->verify_result != X509_V_OK)
return -1;
if (dane->mtlsa) {
if (mcert)
*mcert = dane->mcert;
if (mspki)
*mspki = (dane->mcert == NULL) ? dane->mtlsa->spki : NULL;
}
return dane->mdpth;
}
int SSL_get0_dane_tlsa(SSL *s, uint8_t *usage, uint8_t *selector,
uint8_t *mtype, unsigned const char **data, size_t *dlen)
{
SSL_DANE *dane = &s->dane;
if (!DANETLS_ENABLED(dane) || s->verify_result != X509_V_OK)
return -1;
if (dane->mtlsa) {
if (usage)
*usage = dane->mtlsa->usage;
if (selector)
*selector = dane->mtlsa->selector;
if (mtype)
*mtype = dane->mtlsa->mtype;
if (data)
*data = dane->mtlsa->data;
if (dlen)
*dlen = dane->mtlsa->dlen;
}
return dane->mdpth;
}
SSL_DANE *SSL_get0_dane(SSL *s)
{
return &s->dane;
}
int SSL_dane_tlsa_add(SSL *s, uint8_t usage, uint8_t selector,
uint8_t mtype, unsigned const char *data, size_t dlen)
{
return dane_tlsa_add(&s->dane, usage, selector, mtype, data, dlen);
}
int SSL_CTX_dane_mtype_set(SSL_CTX *ctx, const EVP_MD *md, uint8_t mtype,
uint8_t ord)
{
return dane_mtype_set(&ctx->dane, md, mtype, ord);
}
int SSL_CTX_set1_param(SSL_CTX *ctx, X509_VERIFY_PARAM *vpm)
{
return X509_VERIFY_PARAM_set1(ctx->param, vpm);
}
int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
{
return X509_VERIFY_PARAM_set1(ssl->param, vpm);
}
X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx)
{
return ctx->param;
}
X509_VERIFY_PARAM *SSL_get0_param(SSL *ssl)
{
return ssl->param;
}
void SSL_certs_clear(SSL *s)
{
ssl_cert_clear_certs(s->cert);
}
void SSL_free(SSL *s)
{
int i;
if (s == NULL)
return;
CRYPTO_DOWN_REF(&s->references, &i, s->lock);
REF_PRINT_COUNT("SSL", s);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
X509_VERIFY_PARAM_free(s->param);
dane_final(&s->dane);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL, s, &s->ex_data);
/* Ignore return value */
ssl_free_wbio_buffer(s);
BIO_free_all(s->wbio);
BIO_free_all(s->rbio);
BUF_MEM_free(s->init_buf);
/* add extra stuff */
sk_SSL_CIPHER_free(s->cipher_list);
sk_SSL_CIPHER_free(s->cipher_list_by_id);
sk_SSL_CIPHER_free(s->tls13_ciphersuites);
/* Make the next call work :-) */
if (s->session != NULL) {
ssl_clear_bad_session(s);
SSL_SESSION_free(s->session);
}
SSL_SESSION_free(s->psksession);
OPENSSL_free(s->psksession_id);
clear_ciphers(s);
ssl_cert_free(s->cert);
/* Free up if allocated */
OPENSSL_free(s->ext.hostname);
SSL_CTX_free(s->session_ctx);
#ifndef OPENSSL_NO_EC
OPENSSL_free(s->ext.ecpointformats);
OPENSSL_free(s->ext.supportedgroups);
#endif /* OPENSSL_NO_EC */
sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts, X509_EXTENSION_free);
#ifndef OPENSSL_NO_OCSP
sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free);
#endif
#ifndef OPENSSL_NO_CT
SCT_LIST_free(s->scts);
OPENSSL_free(s->ext.scts);
#endif
OPENSSL_free(s->ext.ocsp.resp);
OPENSSL_free(s->ext.alpn);
OPENSSL_free(s->ext.tls13_cookie);
OPENSSL_free(s->clienthello);
OPENSSL_free(s->pha_context);
EVP_MD_CTX_free(s->pha_dgst);
sk_X509_NAME_pop_free(s->ca_names, X509_NAME_free);
sk_X509_NAME_pop_free(s->client_ca_names, X509_NAME_free);
sk_X509_pop_free(s->verified_chain, X509_free);
if (s->method != NULL)
s->method->ssl_free(s);
RECORD_LAYER_release(&s->rlayer);
SSL_CTX_free(s->ctx);
ASYNC_WAIT_CTX_free(s->waitctx);
#if !defined(OPENSSL_NO_NEXTPROTONEG)
OPENSSL_free(s->ext.npn);
#endif
#ifndef OPENSSL_NO_SRTP
sk_SRTP_PROTECTION_PROFILE_free(s->srtp_profiles);
#endif
CRYPTO_THREAD_lock_free(s->lock);
OPENSSL_free(s);
}
void SSL_set0_rbio(SSL *s, BIO *rbio)
{
BIO_free_all(s->rbio);
s->rbio = rbio;
}
void SSL_set0_wbio(SSL *s, BIO *wbio)
{
/*
* If the output buffering BIO is still in place, remove it
*/
if (s->bbio != NULL)
s->wbio = BIO_pop(s->wbio);
BIO_free_all(s->wbio);
s->wbio = wbio;
/* Re-attach |bbio| to the new |wbio|. */
if (s->bbio != NULL)
s->wbio = BIO_push(s->bbio, s->wbio);
}
void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio)
{
/*
* For historical reasons, this function has many different cases in
* ownership handling.
*/
/* If nothing has changed, do nothing */
if (rbio == SSL_get_rbio(s) && wbio == SSL_get_wbio(s))
return;
/*
* If the two arguments are equal then one fewer reference is granted by the
* caller than we want to take
*/
if (rbio != NULL && rbio == wbio)
BIO_up_ref(rbio);
/*
* If only the wbio is changed only adopt one reference.
*/
if (rbio == SSL_get_rbio(s)) {
SSL_set0_wbio(s, wbio);
return;
}
/*
* There is an asymmetry here for historical reasons. If only the rbio is
* changed AND the rbio and wbio were originally different, then we only
* adopt one reference.
*/
if (wbio == SSL_get_wbio(s) && SSL_get_rbio(s) != SSL_get_wbio(s)) {
SSL_set0_rbio(s, rbio);
return;
}
/* Otherwise, adopt both references. */
SSL_set0_rbio(s, rbio);
SSL_set0_wbio(s, wbio);
}
BIO *SSL_get_rbio(const SSL *s)
{
return s->rbio;
}
BIO *SSL_get_wbio(const SSL *s)
{
if (s->bbio != NULL) {
/*
* If |bbio| is active, the true caller-configured BIO is its
* |next_bio|.
*/
return BIO_next(s->bbio);
}
return s->wbio;
}
int SSL_get_fd(const SSL *s)
{
return SSL_get_rfd(s);
}
int SSL_get_rfd(const SSL *s)
{
int ret = -1;
BIO *b, *r;
b = SSL_get_rbio(s);
r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR);
if (r != NULL)
BIO_get_fd(r, &ret);
return ret;
}
int SSL_get_wfd(const SSL *s)
{
int ret = -1;
BIO *b, *r;
b = SSL_get_wbio(s);
r = BIO_find_type(b, BIO_TYPE_DESCRIPTOR);
if (r != NULL)
BIO_get_fd(r, &ret);
return ret;
}
#ifndef OPENSSL_NO_SOCK
int SSL_set_fd(SSL *s, int fd)
{
int ret = 0;
BIO *bio = NULL;
bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
SSLerr(SSL_F_SSL_SET_FD, ERR_R_BUF_LIB);
goto err;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set_bio(s, bio, bio);
ret = 1;
err:
return ret;
}
int SSL_set_wfd(SSL *s, int fd)
{
BIO *rbio = SSL_get_rbio(s);
if (rbio == NULL || BIO_method_type(rbio) != BIO_TYPE_SOCKET
|| (int)BIO_get_fd(rbio, NULL) != fd) {
BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
SSLerr(SSL_F_SSL_SET_WFD, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set0_wbio(s, bio);
} else {
BIO_up_ref(rbio);
SSL_set0_wbio(s, rbio);
}
return 1;
}
int SSL_set_rfd(SSL *s, int fd)
{
BIO *wbio = SSL_get_wbio(s);
if (wbio == NULL || BIO_method_type(wbio) != BIO_TYPE_SOCKET
|| ((int)BIO_get_fd(wbio, NULL) != fd)) {
BIO *bio = BIO_new(BIO_s_socket());
if (bio == NULL) {
SSLerr(SSL_F_SSL_SET_RFD, ERR_R_BUF_LIB);
return 0;
}
BIO_set_fd(bio, fd, BIO_NOCLOSE);
SSL_set0_rbio(s, bio);
} else {
BIO_up_ref(wbio);
SSL_set0_rbio(s, wbio);
}
return 1;
}
#endif
/* return length of latest Finished message we sent, copy to 'buf' */
size_t SSL_get_finished(const SSL *s, void *buf, size_t count)
{
size_t ret = 0;
if (s->s3 != NULL) {
ret = s->s3->tmp.finish_md_len;
if (count > ret)
count = ret;
memcpy(buf, s->s3->tmp.finish_md, count);
}
return ret;
}
/* return length of latest Finished message we expected, copy to 'buf' */
size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count)
{
size_t ret = 0;
if (s->s3 != NULL) {
ret = s->s3->tmp.peer_finish_md_len;
if (count > ret)
count = ret;
memcpy(buf, s->s3->tmp.peer_finish_md, count);
}
return ret;
}
int SSL_get_verify_mode(const SSL *s)
{
return s->verify_mode;
}
int SSL_get_verify_depth(const SSL *s)
{
return X509_VERIFY_PARAM_get_depth(s->param);
}
int (*SSL_get_verify_callback(const SSL *s)) (int, X509_STORE_CTX *) {
return s->verify_callback;
}
int SSL_CTX_get_verify_mode(const SSL_CTX *ctx)
{
return ctx->verify_mode;
}
int SSL_CTX_get_verify_depth(const SSL_CTX *ctx)
{
return X509_VERIFY_PARAM_get_depth(ctx->param);
}
int (*SSL_CTX_get_verify_callback(const SSL_CTX *ctx)) (int, X509_STORE_CTX *) {
return ctx->default_verify_callback;
}
void SSL_set_verify(SSL *s, int mode,
int (*callback) (int ok, X509_STORE_CTX *ctx))
{
s->verify_mode = mode;
if (callback != NULL)
s->verify_callback = callback;
}
void SSL_set_verify_depth(SSL *s, int depth)
{
X509_VERIFY_PARAM_set_depth(s->param, depth);
}
void SSL_set_read_ahead(SSL *s, int yes)
{
RECORD_LAYER_set_read_ahead(&s->rlayer, yes);
}
int SSL_get_read_ahead(const SSL *s)
{
return RECORD_LAYER_get_read_ahead(&s->rlayer);
}
int SSL_pending(const SSL *s)
{
size_t pending = s->method->ssl_pending(s);
/*
* SSL_pending cannot work properly if read-ahead is enabled
* (SSL_[CTX_]ctrl(..., SSL_CTRL_SET_READ_AHEAD, 1, NULL)), and it is
* impossible to fix since SSL_pending cannot report errors that may be
* observed while scanning the new data. (Note that SSL_pending() is
* often used as a boolean value, so we'd better not return -1.)
*
* SSL_pending also cannot work properly if the value >INT_MAX. In that case
* we just return INT_MAX.
*/
return pending < INT_MAX ? (int)pending : INT_MAX;
}
int SSL_has_pending(const SSL *s)
{
/*
* Similar to SSL_pending() but returns a 1 to indicate that we have
* unprocessed data available or 0 otherwise (as opposed to the number of
* bytes available). Unlike SSL_pending() this will take into account
* read_ahead data. A 1 return simply indicates that we have unprocessed
* data. That data may not result in any application data, or we may fail
* to parse the records for some reason.
*/
if (RECORD_LAYER_processed_read_pending(&s->rlayer))
return 1;
return RECORD_LAYER_read_pending(&s->rlayer);
}
X509 *SSL_get_peer_certificate(const SSL *s)
{
X509 *r;
if ((s == NULL) || (s->session == NULL))
r = NULL;
else
r = s->session->peer;
if (r == NULL)
return r;
X509_up_ref(r);
return r;
}
STACK_OF(X509) *SSL_get_peer_cert_chain(const SSL *s)
{
STACK_OF(X509) *r;
if ((s == NULL) || (s->session == NULL))
r = NULL;
else
r = s->session->peer_chain;
/*
* If we are a client, cert_chain includes the peer's own certificate; if
* we are a server, it does not.
*/
return r;
}
/*
* Now in theory, since the calling process own 't' it should be safe to
* modify. We need to be able to read f without being hassled
*/
int SSL_copy_session_id(SSL *t, const SSL *f)
{
int i;
/* Do we need to to SSL locking? */
if (!SSL_set_session(t, SSL_get_session(f))) {
return 0;
}
/*
* what if we are setup for one protocol version but want to talk another
*/
if (t->method != f->method) {
t->method->ssl_free(t);
t->method = f->method;
if (t->method->ssl_new(t) == 0)
return 0;
}
CRYPTO_UP_REF(&f->cert->references, &i, f->cert->lock);
ssl_cert_free(t->cert);
t->cert = f->cert;
if (!SSL_set_session_id_context(t, f->sid_ctx, (int)f->sid_ctx_length)) {
return 0;
}
return 1;
}
/* Fix this so it checks all the valid key/cert options */
int SSL_CTX_check_private_key(const SSL_CTX *ctx)
{
if ((ctx == NULL) || (ctx->cert->key->x509 == NULL)) {
SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED);
return 0;
}
if (ctx->cert->key->privatekey == NULL) {
SSLerr(SSL_F_SSL_CTX_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
return 0;
}
return X509_check_private_key
(ctx->cert->key->x509, ctx->cert->key->privatekey);
}
/* Fix this function so that it takes an optional type parameter */
int SSL_check_private_key(const SSL *ssl)
{
if (ssl == NULL) {
SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if (ssl->cert->key->x509 == NULL) {
SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, SSL_R_NO_CERTIFICATE_ASSIGNED);
return 0;
}
if (ssl->cert->key->privatekey == NULL) {
SSLerr(SSL_F_SSL_CHECK_PRIVATE_KEY, SSL_R_NO_PRIVATE_KEY_ASSIGNED);
return 0;
}
return X509_check_private_key(ssl->cert->key->x509,
ssl->cert->key->privatekey);
}
int SSL_waiting_for_async(SSL *s)
{
if (s->job)
return 1;
return 0;
}
int SSL_get_all_async_fds(SSL *s, OSSL_ASYNC_FD *fds, size_t *numfds)
{
ASYNC_WAIT_CTX *ctx = s->waitctx;
if (ctx == NULL)
return 0;
return ASYNC_WAIT_CTX_get_all_fds(ctx, fds, numfds);
}
int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd, size_t *numaddfds,
OSSL_ASYNC_FD *delfd, size_t *numdelfds)
{
ASYNC_WAIT_CTX *ctx = s->waitctx;
if (ctx == NULL)
return 0;
return ASYNC_WAIT_CTX_get_changed_fds(ctx, addfd, numaddfds, delfd,
numdelfds);
}
int SSL_accept(SSL *s)
{
if (s->handshake_func == NULL) {
/* Not properly initialized yet */
SSL_set_accept_state(s);
}
return SSL_do_handshake(s);
}
int SSL_connect(SSL *s)
{
if (s->handshake_func == NULL) {
/* Not properly initialized yet */
SSL_set_connect_state(s);
}
return SSL_do_handshake(s);
}
long SSL_get_default_timeout(const SSL *s)
{
return s->method->get_timeout();
}
static int ssl_start_async_job(SSL *s, struct ssl_async_args *args,
int (*func) (void *))
{
int ret;
if (s->waitctx == NULL) {
s->waitctx = ASYNC_WAIT_CTX_new();
if (s->waitctx == NULL)
return -1;
}
switch (ASYNC_start_job(&s->job, s->waitctx, &ret, func, args,
sizeof(struct ssl_async_args))) {
case ASYNC_ERR:
s->rwstate = SSL_NOTHING;
SSLerr(SSL_F_SSL_START_ASYNC_JOB, SSL_R_FAILED_TO_INIT_ASYNC);
return -1;
case ASYNC_PAUSE:
s->rwstate = SSL_ASYNC_PAUSED;
return -1;
case ASYNC_NO_JOBS:
s->rwstate = SSL_ASYNC_NO_JOBS;
return -1;
case ASYNC_FINISH:
s->job = NULL;
return ret;
default:
s->rwstate = SSL_NOTHING;
SSLerr(SSL_F_SSL_START_ASYNC_JOB, ERR_R_INTERNAL_ERROR);
/* Shouldn't happen */
return -1;
}
}
static int ssl_io_intern(void *vargs)
{
struct ssl_async_args *args;
SSL *s;
void *buf;
size_t num;
args = (struct ssl_async_args *)vargs;
s = args->s;
buf = args->buf;
num = args->num;
switch (args->type) {
case READFUNC:
return args->f.func_read(s, buf, num, &s->asyncrw);
case WRITEFUNC:
return args->f.func_write(s, buf, num, &s->asyncrw);
case OTHERFUNC:
return args->f.func_other(s);
}
return -1;
}
int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
{
if (s->handshake_func == NULL) {
SSLerr(SSL_F_SSL_READ_INTERNAL, SSL_R_UNINITIALIZED);
return -1;
}
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
return 0;
}
if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
|| s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY) {
SSLerr(SSL_F_SSL_READ_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
/*
* If we are a client and haven't received the ServerHello etc then we
* better do that
*/
ossl_statem_check_finish_init(s, 0);
if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
int ret;
args.s = s;
args.buf = buf;
args.num = num;
args.type = READFUNC;
args.f.func_read = s->method->ssl_read;
ret = ssl_start_async_job(s, &args, ssl_io_intern);
*readbytes = s->asyncrw;
return ret;
} else {
return s->method->ssl_read(s, buf, num, readbytes);
}
}
int SSL_read(SSL *s, void *buf, int num)
{
int ret;
size_t readbytes;
if (num < 0) {
SSLerr(SSL_F_SSL_READ, SSL_R_BAD_LENGTH);
return -1;
}
ret = ssl_read_internal(s, buf, (size_t)num, &readbytes);
/*
* The cast is safe here because ret should be <= INT_MAX because num is
* <= INT_MAX
*/
if (ret > 0)
ret = (int)readbytes;
return ret;
}
int SSL_read_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
{
int ret = ssl_read_internal(s, buf, num, readbytes);
if (ret < 0)
ret = 0;
return ret;
}
int SSL_read_early_data(SSL *s, void *buf, size_t num, size_t *readbytes)
{
int ret;
if (!s->server) {
SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return SSL_READ_EARLY_DATA_ERROR;
}
switch (s->early_data_state) {
case SSL_EARLY_DATA_NONE:
if (!SSL_in_before(s)) {
SSLerr(SSL_F_SSL_READ_EARLY_DATA,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return SSL_READ_EARLY_DATA_ERROR;
}
/* fall through */
case SSL_EARLY_DATA_ACCEPT_RETRY:
s->early_data_state = SSL_EARLY_DATA_ACCEPTING;
ret = SSL_accept(s);
if (ret <= 0) {
/* NBIO or error */
s->early_data_state = SSL_EARLY_DATA_ACCEPT_RETRY;
return SSL_READ_EARLY_DATA_ERROR;
}
/* fall through */
case SSL_EARLY_DATA_READ_RETRY:
if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
s->early_data_state = SSL_EARLY_DATA_READING;
ret = SSL_read_ex(s, buf, num, readbytes);
/*
* State machine will update early_data_state to
* SSL_EARLY_DATA_FINISHED_READING if we get an EndOfEarlyData
* message
*/
if (ret > 0 || (ret <= 0 && s->early_data_state
!= SSL_EARLY_DATA_FINISHED_READING)) {
s->early_data_state = SSL_EARLY_DATA_READ_RETRY;
return ret > 0 ? SSL_READ_EARLY_DATA_SUCCESS
: SSL_READ_EARLY_DATA_ERROR;
}
} else {
s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
}
*readbytes = 0;
return SSL_READ_EARLY_DATA_FINISH;
default:
SSLerr(SSL_F_SSL_READ_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return SSL_READ_EARLY_DATA_ERROR;
}
}
int SSL_get_early_data_status(const SSL *s)
{
return s->ext.early_data;
}
static int ssl_peek_internal(SSL *s, void *buf, size_t num, size_t *readbytes)
{
if (s->handshake_func == NULL) {
SSLerr(SSL_F_SSL_PEEK_INTERNAL, SSL_R_UNINITIALIZED);
return -1;
}
if (s->shutdown & SSL_RECEIVED_SHUTDOWN) {
return 0;
}
if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
int ret;
args.s = s;
args.buf = buf;
args.num = num;
args.type = READFUNC;
args.f.func_read = s->method->ssl_peek;
ret = ssl_start_async_job(s, &args, ssl_io_intern);
*readbytes = s->asyncrw;
return ret;
} else {
return s->method->ssl_peek(s, buf, num, readbytes);
}
}
int SSL_peek(SSL *s, void *buf, int num)
{
int ret;
size_t readbytes;
if (num < 0) {
SSLerr(SSL_F_SSL_PEEK, SSL_R_BAD_LENGTH);
return -1;
}
ret = ssl_peek_internal(s, buf, (size_t)num, &readbytes);
/*
* The cast is safe here because ret should be <= INT_MAX because num is
* <= INT_MAX
*/
if (ret > 0)
ret = (int)readbytes;
return ret;
}
int SSL_peek_ex(SSL *s, void *buf, size_t num, size_t *readbytes)
{
int ret = ssl_peek_internal(s, buf, num, readbytes);
if (ret < 0)
ret = 0;
return ret;
}
int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written)
{
if (s->handshake_func == NULL) {
SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_UNINITIALIZED);
return -1;
}
if (s->shutdown & SSL_SENT_SHUTDOWN) {
s->rwstate = SSL_NOTHING;
SSLerr(SSL_F_SSL_WRITE_INTERNAL, SSL_R_PROTOCOL_IS_SHUTDOWN);
return -1;
}
if (s->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY
|| s->early_data_state == SSL_EARLY_DATA_ACCEPT_RETRY
|| s->early_data_state == SSL_EARLY_DATA_READ_RETRY) {
SSLerr(SSL_F_SSL_WRITE_INTERNAL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
/* If we are a client and haven't sent the Finished we better do that */
ossl_statem_check_finish_init(s, 1);
if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
int ret;
struct ssl_async_args args;
args.s = s;
args.buf = (void *)buf;
args.num = num;
args.type = WRITEFUNC;
args.f.func_write = s->method->ssl_write;
ret = ssl_start_async_job(s, &args, ssl_io_intern);
*written = s->asyncrw;
return ret;
} else {
return s->method->ssl_write(s, buf, num, written);
}
}
int SSL_write(SSL *s, const void *buf, int num)
{
int ret;
size_t written;
if (num < 0) {
SSLerr(SSL_F_SSL_WRITE, SSL_R_BAD_LENGTH);
return -1;
}
ret = ssl_write_internal(s, buf, (size_t)num, &written);
/*
* The cast is safe here because ret should be <= INT_MAX because num is
* <= INT_MAX
*/
if (ret > 0)
ret = (int)written;
return ret;
}
int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written)
{
int ret = ssl_write_internal(s, buf, num, written);
if (ret < 0)
ret = 0;
return ret;
}
int SSL_write_early_data(SSL *s, const void *buf, size_t num, size_t *written)
{
int ret, early_data_state;
size_t writtmp;
uint32_t partialwrite;
switch (s->early_data_state) {
case SSL_EARLY_DATA_NONE:
if (s->server
|| !SSL_in_before(s)
|| ((s->session == NULL || s->session->ext.max_early_data == 0)
&& (s->psk_use_session_cb == NULL))) {
SSLerr(SSL_F_SSL_WRITE_EARLY_DATA,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
/* fall through */
case SSL_EARLY_DATA_CONNECT_RETRY:
s->early_data_state = SSL_EARLY_DATA_CONNECTING;
ret = SSL_connect(s);
if (ret <= 0) {
/* NBIO or error */
s->early_data_state = SSL_EARLY_DATA_CONNECT_RETRY;
return 0;
}
/* fall through */
case SSL_EARLY_DATA_WRITE_RETRY:
s->early_data_state = SSL_EARLY_DATA_WRITING;
/*
* We disable partial write for early data because we don't keep track
* of how many bytes we've written between the SSL_write_ex() call and
* the flush if the flush needs to be retried)
*/
partialwrite = s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE;
s->mode &= ~SSL_MODE_ENABLE_PARTIAL_WRITE;
ret = SSL_write_ex(s, buf, num, &writtmp);
s->mode |= partialwrite;
if (!ret) {
s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
return ret;
}
s->early_data_state = SSL_EARLY_DATA_WRITE_FLUSH;
/* fall through */
case SSL_EARLY_DATA_WRITE_FLUSH:
/* The buffering BIO is still in place so we need to flush it */
if (statem_flush(s) != 1)
return 0;
*written = num;
s->early_data_state = SSL_EARLY_DATA_WRITE_RETRY;
return 1;
case SSL_EARLY_DATA_FINISHED_READING:
case SSL_EARLY_DATA_READ_RETRY:
early_data_state = s->early_data_state;
/* We are a server writing to an unauthenticated client */
s->early_data_state = SSL_EARLY_DATA_UNAUTH_WRITING;
ret = SSL_write_ex(s, buf, num, written);
/* The buffering BIO is still in place */
if (ret)
(void)BIO_flush(s->wbio);
s->early_data_state = early_data_state;
return ret;
default:
SSLerr(SSL_F_SSL_WRITE_EARLY_DATA, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
}
int SSL_shutdown(SSL *s)
{
/*
* Note that this function behaves differently from what one might
* expect. Return values are 0 for no success (yet), 1 for success; but
* calling it once is usually not enough, even if blocking I/O is used
* (see ssl3_shutdown).
*/
if (s->handshake_func == NULL) {
SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_UNINITIALIZED);
return -1;
}
if (!SSL_in_init(s)) {
if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
args.s = s;
args.type = OTHERFUNC;
args.f.func_other = s->method->ssl_shutdown;
return ssl_start_async_job(s, &args, ssl_io_intern);
} else {
return s->method->ssl_shutdown(s);
}
} else {
SSLerr(SSL_F_SSL_SHUTDOWN, SSL_R_SHUTDOWN_WHILE_IN_INIT);
return -1;
}
}
int SSL_key_update(SSL *s, int updatetype)
{
/*
* TODO(TLS1.3): How will applications know whether TLSv1.3 has been
* negotiated, and that it is appropriate to call SSL_key_update() instead
* of SSL_renegotiate().
*/
if (!SSL_IS_TLS13(s)) {
SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_WRONG_SSL_VERSION);
return 0;
}
if (updatetype != SSL_KEY_UPDATE_NOT_REQUESTED
&& updatetype != SSL_KEY_UPDATE_REQUESTED) {
SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_INVALID_KEY_UPDATE_TYPE);
return 0;
}
if (!SSL_is_init_finished(s)) {
SSLerr(SSL_F_SSL_KEY_UPDATE, SSL_R_STILL_IN_INIT);
return 0;
}
ossl_statem_set_in_init(s, 1);
s->key_update = updatetype;
return 1;
}
int SSL_get_key_update_type(const SSL *s)
{
return s->key_update;
}
int SSL_renegotiate(SSL *s)
{
if (SSL_IS_TLS13(s)) {
SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_WRONG_SSL_VERSION);
return 0;
}
if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
SSLerr(SSL_F_SSL_RENEGOTIATE, SSL_R_NO_RENEGOTIATION);
return 0;
}
s->renegotiate = 1;
s->new_session = 1;
return s->method->ssl_renegotiate(s);
}
int SSL_renegotiate_abbreviated(SSL *s)
{
if (SSL_IS_TLS13(s)) {
SSLerr(SSL_F_SSL_RENEGOTIATE_ABBREVIATED, SSL_R_WRONG_SSL_VERSION);
return 0;
}
if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
SSLerr(SSL_F_SSL_RENEGOTIATE_ABBREVIATED, SSL_R_NO_RENEGOTIATION);
return 0;
}
s->renegotiate = 1;
s->new_session = 0;
return s->method->ssl_renegotiate(s);
}
int SSL_renegotiate_pending(const SSL *s)
{
/*
* becomes true when negotiation is requested; false again once a
* handshake has finished
*/
return (s->renegotiate != 0);
}
long SSL_ctrl(SSL *s, int cmd, long larg, void *parg)
{
long l;
switch (cmd) {
case SSL_CTRL_GET_READ_AHEAD:
return RECORD_LAYER_get_read_ahead(&s->rlayer);
case SSL_CTRL_SET_READ_AHEAD:
l = RECORD_LAYER_get_read_ahead(&s->rlayer);
RECORD_LAYER_set_read_ahead(&s->rlayer, larg);
return l;
case SSL_CTRL_SET_MSG_CALLBACK_ARG:
s->msg_callback_arg = parg;
return 1;
case SSL_CTRL_MODE:
return (s->mode |= larg);
case SSL_CTRL_CLEAR_MODE:
return (s->mode &= ~larg);
case SSL_CTRL_GET_MAX_CERT_LIST:
return (long)s->max_cert_list;
case SSL_CTRL_SET_MAX_CERT_LIST:
if (larg < 0)
return 0;
l = (long)s->max_cert_list;
s->max_cert_list = (size_t)larg;
return l;
case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
return 0;
s->max_send_fragment = larg;
if (s->max_send_fragment < s->split_send_fragment)
s->split_send_fragment = s->max_send_fragment;
return 1;
case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT:
if ((size_t)larg > s->max_send_fragment || larg == 0)
return 0;
s->split_send_fragment = larg;
return 1;
case SSL_CTRL_SET_MAX_PIPELINES:
if (larg < 1 || larg > SSL_MAX_PIPELINES)
return 0;
s->max_pipelines = larg;
if (larg > 1)
RECORD_LAYER_set_read_ahead(&s->rlayer, 1);
return 1;
case SSL_CTRL_GET_RI_SUPPORT:
if (s->s3)
return s->s3->send_connection_binding;
else
return 0;
case SSL_CTRL_CERT_FLAGS:
return (s->cert->cert_flags |= larg);
case SSL_CTRL_CLEAR_CERT_FLAGS:
return (s->cert->cert_flags &= ~larg);
case SSL_CTRL_GET_RAW_CIPHERLIST:
if (parg) {
if (s->s3->tmp.ciphers_raw == NULL)
return 0;
*(unsigned char **)parg = s->s3->tmp.ciphers_raw;
return (int)s->s3->tmp.ciphers_rawlen;
} else {
return TLS_CIPHER_LEN;
}
case SSL_CTRL_GET_EXTMS_SUPPORT:
if (!s->session || SSL_in_init(s) || ossl_statem_get_in_handshake(s))
return -1;
if (s->session->flags & SSL_SESS_FLAG_EXTMS)
return 1;
else
return 0;
case SSL_CTRL_SET_MIN_PROTO_VERSION:
return ssl_check_allowed_versions(larg, s->max_proto_version)
&& ssl_set_version_bound(s->ctx->method->version, (int)larg,
&s->min_proto_version);
case SSL_CTRL_GET_MIN_PROTO_VERSION:
return s->min_proto_version;
case SSL_CTRL_SET_MAX_PROTO_VERSION:
return ssl_check_allowed_versions(s->min_proto_version, larg)
&& ssl_set_version_bound(s->ctx->method->version, (int)larg,
&s->max_proto_version);
case SSL_CTRL_GET_MAX_PROTO_VERSION:
return s->max_proto_version;
default:
return s->method->ssl_ctrl(s, cmd, larg, parg);
}
}
long SSL_callback_ctrl(SSL *s, int cmd, void (*fp) (void))
{
switch (cmd) {
case SSL_CTRL_SET_MSG_CALLBACK:
s->msg_callback = (void (*)
(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl,
void *arg))(fp);
return 1;
default:
return s->method->ssl_callback_ctrl(s, cmd, fp);
}
}
LHASH_OF(SSL_SESSION) *SSL_CTX_sessions(SSL_CTX *ctx)
{
return ctx->sessions;
}
long SSL_CTX_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
{
long l;
/* For some cases with ctx == NULL perform syntax checks */
if (ctx == NULL) {
switch (cmd) {
#ifndef OPENSSL_NO_EC
case SSL_CTRL_SET_GROUPS_LIST:
return tls1_set_groups_list(NULL, NULL, parg);
#endif
case SSL_CTRL_SET_SIGALGS_LIST:
case SSL_CTRL_SET_CLIENT_SIGALGS_LIST:
return tls1_set_sigalgs_list(NULL, parg, 0);
default:
return 0;
}
}
switch (cmd) {
case SSL_CTRL_GET_READ_AHEAD:
return ctx->read_ahead;
case SSL_CTRL_SET_READ_AHEAD:
l = ctx->read_ahead;
ctx->read_ahead = larg;
return l;
case SSL_CTRL_SET_MSG_CALLBACK_ARG:
ctx->msg_callback_arg = parg;
return 1;
case SSL_CTRL_GET_MAX_CERT_LIST:
return (long)ctx->max_cert_list;
case SSL_CTRL_SET_MAX_CERT_LIST:
if (larg < 0)
return 0;
l = (long)ctx->max_cert_list;
ctx->max_cert_list = (size_t)larg;
return l;
case SSL_CTRL_SET_SESS_CACHE_SIZE:
if (larg < 0)
return 0;
l = (long)ctx->session_cache_size;
ctx->session_cache_size = (size_t)larg;
return l;
case SSL_CTRL_GET_SESS_CACHE_SIZE:
return (long)ctx->session_cache_size;
case SSL_CTRL_SET_SESS_CACHE_MODE:
l = ctx->session_cache_mode;
ctx->session_cache_mode = larg;
return l;
case SSL_CTRL_GET_SESS_CACHE_MODE:
return ctx->session_cache_mode;
case SSL_CTRL_SESS_NUMBER:
return lh_SSL_SESSION_num_items(ctx->sessions);
case SSL_CTRL_SESS_CONNECT:
return tsan_load(&ctx->stats.sess_connect);
case SSL_CTRL_SESS_CONNECT_GOOD:
return tsan_load(&ctx->stats.sess_connect_good);
case SSL_CTRL_SESS_CONNECT_RENEGOTIATE:
return tsan_load(&ctx->stats.sess_connect_renegotiate);
case SSL_CTRL_SESS_ACCEPT:
return tsan_load(&ctx->stats.sess_accept);
case SSL_CTRL_SESS_ACCEPT_GOOD:
return tsan_load(&ctx->stats.sess_accept_good);
case SSL_CTRL_SESS_ACCEPT_RENEGOTIATE:
return tsan_load(&ctx->stats.sess_accept_renegotiate);
case SSL_CTRL_SESS_HIT:
return tsan_load(&ctx->stats.sess_hit);
case SSL_CTRL_SESS_CB_HIT:
return tsan_load(&ctx->stats.sess_cb_hit);
case SSL_CTRL_SESS_MISSES:
return tsan_load(&ctx->stats.sess_miss);
case SSL_CTRL_SESS_TIMEOUTS:
return tsan_load(&ctx->stats.sess_timeout);
case SSL_CTRL_SESS_CACHE_FULL:
return tsan_load(&ctx->stats.sess_cache_full);
case SSL_CTRL_MODE:
return (ctx->mode |= larg);
case SSL_CTRL_CLEAR_MODE:
return (ctx->mode &= ~larg);
case SSL_CTRL_SET_MAX_SEND_FRAGMENT:
if (larg < 512 || larg > SSL3_RT_MAX_PLAIN_LENGTH)
return 0;
ctx->max_send_fragment = larg;
if (ctx->max_send_fragment < ctx->split_send_fragment)
ctx->split_send_fragment = ctx->max_send_fragment;
return 1;
case SSL_CTRL_SET_SPLIT_SEND_FRAGMENT:
if ((size_t)larg > ctx->max_send_fragment || larg == 0)
return 0;
ctx->split_send_fragment = larg;
return 1;
case SSL_CTRL_SET_MAX_PIPELINES:
if (larg < 1 || larg > SSL_MAX_PIPELINES)
return 0;
ctx->max_pipelines = larg;
return 1;
case SSL_CTRL_CERT_FLAGS:
return (ctx->cert->cert_flags |= larg);
case SSL_CTRL_CLEAR_CERT_FLAGS:
return (ctx->cert->cert_flags &= ~larg);
case SSL_CTRL_SET_MIN_PROTO_VERSION:
return ssl_check_allowed_versions(larg, ctx->max_proto_version)
&& ssl_set_version_bound(ctx->method->version, (int)larg,
&ctx->min_proto_version);
case SSL_CTRL_GET_MIN_PROTO_VERSION:
return ctx->min_proto_version;
case SSL_CTRL_SET_MAX_PROTO_VERSION:
return ssl_check_allowed_versions(ctx->min_proto_version, larg)
&& ssl_set_version_bound(ctx->method->version, (int)larg,
&ctx->max_proto_version);
case SSL_CTRL_GET_MAX_PROTO_VERSION:
return ctx->max_proto_version;
default:
return ctx->method->ssl_ctx_ctrl(ctx, cmd, larg, parg);
}
}
long SSL_CTX_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp) (void))
{
switch (cmd) {
case SSL_CTRL_SET_MSG_CALLBACK:
ctx->msg_callback = (void (*)
(int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl,
void *arg))(fp);
return 1;
default:
return ctx->method->ssl_ctx_callback_ctrl(ctx, cmd, fp);
}
}
int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b)
{
if (a->id > b->id)
return 1;
if (a->id < b->id)
return -1;
return 0;
}
int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
const SSL_CIPHER *const *bp)
{
if ((*ap)->id > (*bp)->id)
return 1;
if ((*ap)->id < (*bp)->id)
return -1;
return 0;
}
/** return a STACK of the ciphers available for the SSL and in order of
* preference */
STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s)
{
if (s != NULL) {
if (s->cipher_list != NULL) {
return s->cipher_list;
} else if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL)) {
return s->ctx->cipher_list;
}
}
return NULL;
}
STACK_OF(SSL_CIPHER) *SSL_get_client_ciphers(const SSL *s)
{
if ((s == NULL) || (s->session == NULL) || !s->server)
return NULL;
return s->session->ciphers;
}
STACK_OF(SSL_CIPHER) *SSL_get1_supported_ciphers(SSL *s)
{
STACK_OF(SSL_CIPHER) *sk = NULL, *ciphers;
int i;
ciphers = SSL_get_ciphers(s);
if (!ciphers)
return NULL;
if (!ssl_set_client_disabled(s))
return NULL;
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
const SSL_CIPHER *c = sk_SSL_CIPHER_value(ciphers, i);
if (!ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0)) {
if (!sk)
sk = sk_SSL_CIPHER_new_null();
if (!sk)
return NULL;
if (!sk_SSL_CIPHER_push(sk, c)) {
sk_SSL_CIPHER_free(sk);
return NULL;
}
}
}
return sk;
}
/** return a STACK of the ciphers available for the SSL and in order of
* algorithm id */
STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s)
{
if (s != NULL) {
if (s->cipher_list_by_id != NULL) {
return s->cipher_list_by_id;
} else if ((s->ctx != NULL) && (s->ctx->cipher_list_by_id != NULL)) {
return s->ctx->cipher_list_by_id;
}
}
return NULL;
}
/** The old interface to get the same thing as SSL_get_ciphers() */
const char *SSL_get_cipher_list(const SSL *s, int n)
{
const SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *sk;
if (s == NULL)
return NULL;
sk = SSL_get_ciphers(s);
if ((sk == NULL) || (sk_SSL_CIPHER_num(sk) <= n))
return NULL;
c = sk_SSL_CIPHER_value(sk, n);
if (c == NULL)
return NULL;
return c->name;
}
/** return a STACK of the ciphers available for the SSL_CTX and in order of
* preference */
STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx)
{
if (ctx != NULL)
return ctx->cipher_list;
return NULL;
}
/*
* Distinguish between ciphers controlled by set_ciphersuite() and
* set_cipher_list() when counting.
*/
static int cipher_list_tls12_num(STACK_OF(SSL_CIPHER) *sk)
{
int i, num = 0;
const SSL_CIPHER *c;
if (sk == NULL)
return 0;
for (i = 0; i < sk_SSL_CIPHER_num(sk); ++i) {
c = sk_SSL_CIPHER_value(sk, i);
if (c->min_tls >= TLS1_3_VERSION)
continue;
num++;
}
return num;
}
/** specify the ciphers to be used by default by the SSL_CTX */
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
{
STACK_OF(SSL_CIPHER) *sk;
sk = ssl_create_cipher_list(ctx->method, ctx->tls13_ciphersuites,
&ctx->cipher_list, &ctx->cipher_list_by_id, str,
ctx->cert);
/*
* ssl_create_cipher_list may return an empty stack if it was unable to
* find a cipher matching the given rule string (for example if the rule
* string specifies a cipher which has been disabled). This is not an
* error as far as ssl_create_cipher_list is concerned, and hence
* ctx->cipher_list and ctx->cipher_list_by_id has been updated.
*/
if (sk == NULL)
return 0;
else if (cipher_list_tls12_num(sk) == 0) {
SSLerr(SSL_F_SSL_CTX_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
return 0;
}
return 1;
}
/** specify the ciphers to be used by the SSL */
int SSL_set_cipher_list(SSL *s, const char *str)
{
STACK_OF(SSL_CIPHER) *sk;
sk = ssl_create_cipher_list(s->ctx->method, s->tls13_ciphersuites,
&s->cipher_list, &s->cipher_list_by_id, str,
s->cert);
/* see comment in SSL_CTX_set_cipher_list */
if (sk == NULL)
return 0;
else if (cipher_list_tls12_num(sk) == 0) {
SSLerr(SSL_F_SSL_SET_CIPHER_LIST, SSL_R_NO_CIPHER_MATCH);
return 0;
}
return 1;
}
char *SSL_get_shared_ciphers(const SSL *s, char *buf, int size)
{
char *p;
STACK_OF(SSL_CIPHER) *clntsk, *srvrsk;
const SSL_CIPHER *c;
int i;
if (!s->server
|| s->session == NULL
|| s->session->ciphers == NULL
|| size < 2)
return NULL;
p = buf;
clntsk = s->session->ciphers;
srvrsk = SSL_get_ciphers(s);
if (clntsk == NULL || srvrsk == NULL)
return NULL;
if (sk_SSL_CIPHER_num(clntsk) == 0 || sk_SSL_CIPHER_num(srvrsk) == 0)
return NULL;
for (i = 0; i < sk_SSL_CIPHER_num(clntsk); i++) {
int n;
c = sk_SSL_CIPHER_value(clntsk, i);
if (sk_SSL_CIPHER_find(srvrsk, c) < 0)
continue;
n = strlen(c->name);
if (n + 1 > size) {
if (p != buf)
--p;
*p = '\0';
return buf;
}
strcpy(p, c->name);
p += n;
*(p++) = ':';
size -= n + 1;
}
p[-1] = '\0';
return buf;
}
/** return a servername extension value if provided in Client Hello, or NULL.
* So far, only host_name types are defined (RFC 3546).
*/
const char *SSL_get_servername(const SSL *s, const int type)
{
if (type != TLSEXT_NAMETYPE_host_name)
return NULL;
/*
* SNI is not negotiated in pre-TLS-1.3 resumption flows, so fake up an
* SNI value to return if we are resuming/resumed. N.B. that we still
* call the relevant callbacks for such resumption flows, and callbacks
* might error out if there is not a SNI value available.
*/
if (s->hit)
return s->session->ext.hostname;
return s->ext.hostname;
}
int SSL_get_servername_type(const SSL *s)
{
if (s->session
&& (!s->ext.hostname ? s->session->
ext.hostname : s->ext.hostname))
return TLSEXT_NAMETYPE_host_name;
return -1;
}
/*
* SSL_select_next_proto implements the standard protocol selection. It is
* expected that this function is called from the callback set by
* SSL_CTX_set_next_proto_select_cb. The protocol data is assumed to be a
* vector of 8-bit, length prefixed byte strings. The length byte itself is
* not included in the length. A byte string of length 0 is invalid. No byte
* string may be truncated. The current, but experimental algorithm for
* selecting the protocol is: 1) If the server doesn't support NPN then this
* is indicated to the callback. In this case, the client application has to
* abort the connection or have a default application level protocol. 2) If
* the server supports NPN, but advertises an empty list then the client
* selects the first protocol in its list, but indicates via the API that this
* fallback case was enacted. 3) Otherwise, the client finds the first
* protocol in the server's list that it supports and selects this protocol.
* This is because it's assumed that the server has better information about
* which protocol a client should use. 4) If the client doesn't support any
* of the server's advertised protocols, then this is treated the same as
* case 2. It returns either OPENSSL_NPN_NEGOTIATED if a common protocol was
* found, or OPENSSL_NPN_NO_OVERLAP if the fallback case was reached.
*/
int SSL_select_next_proto(unsigned char **out, unsigned char *outlen,
const unsigned char *server,
unsigned int server_len,
const unsigned char *client, unsigned int client_len)
{
unsigned int i, j;
const unsigned char *result;
int status = OPENSSL_NPN_UNSUPPORTED;
/*
* For each protocol in server preference order, see if we support it.
*/
for (i = 0; i < server_len;) {
for (j = 0; j < client_len;) {
if (server[i] == client[j] &&
memcmp(&server[i + 1], &client[j + 1], server[i]) == 0) {
/* We found a match */
result = &server[i];
status = OPENSSL_NPN_NEGOTIATED;
goto found;
}
j += client[j];
j++;
}
i += server[i];
i++;
}
/* There's no overlap between our protocols and the server's list. */
result = client;
status = OPENSSL_NPN_NO_OVERLAP;
found:
*out = (unsigned char *)result + 1;
*outlen = result[0];
return status;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* SSL_get0_next_proto_negotiated sets *data and *len to point to the
* client's requested protocol for this connection and returns 0. If the
* client didn't request any protocol, then *data is set to NULL. Note that
* the client can request any protocol it chooses. The value returned from
* this function need not be a member of the list of supported protocols
* provided by the callback.
*/
void SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data,
unsigned *len)
{
*data = s->ext.npn;
if (!*data) {
*len = 0;
} else {
*len = (unsigned int)s->ext.npn_len;
}
}
/*
* SSL_CTX_set_npn_advertised_cb sets a callback that is called when
* a TLS server needs a list of supported protocols for Next Protocol
* Negotiation. The returned list must be in wire format. The list is
* returned by setting |out| to point to it and |outlen| to its length. This
* memory will not be modified, but one should assume that the SSL* keeps a
* reference to it. The callback should return SSL_TLSEXT_ERR_OK if it
* wishes to advertise. Otherwise, no such extension will be included in the
* ServerHello.
*/
void SSL_CTX_set_npn_advertised_cb(SSL_CTX *ctx,
SSL_CTX_npn_advertised_cb_func cb,
void *arg)
{
ctx->ext.npn_advertised_cb = cb;
ctx->ext.npn_advertised_cb_arg = arg;
}
/*
* SSL_CTX_set_next_proto_select_cb sets a callback that is called when a
* client needs to select a protocol from the server's provided list. |out|
* must be set to point to the selected protocol (which may be within |in|).
* The length of the protocol name must be written into |outlen|. The
* server's advertised protocols are provided in |in| and |inlen|. The
* callback can assume that |in| is syntactically valid. The client must
* select a protocol. It is fatal to the connection if this callback returns
* a value other than SSL_TLSEXT_ERR_OK.
*/
void SSL_CTX_set_npn_select_cb(SSL_CTX *ctx,
SSL_CTX_npn_select_cb_func cb,
void *arg)
{
ctx->ext.npn_select_cb = cb;
ctx->ext.npn_select_cb_arg = arg;
}
#endif
/*
* SSL_CTX_set_alpn_protos sets the ALPN protocol list on |ctx| to |protos|.
* |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
* length-prefixed strings). Returns 0 on success.
*/
int SSL_CTX_set_alpn_protos(SSL_CTX *ctx, const unsigned char *protos,
unsigned int protos_len)
{
OPENSSL_free(ctx->ext.alpn);
ctx->ext.alpn = OPENSSL_memdup(protos, protos_len);
if (ctx->ext.alpn == NULL) {
SSLerr(SSL_F_SSL_CTX_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
return 1;
}
ctx->ext.alpn_len = protos_len;
return 0;
}
/*
* SSL_set_alpn_protos sets the ALPN protocol list on |ssl| to |protos|.
* |protos| must be in wire-format (i.e. a series of non-empty, 8-bit
* length-prefixed strings). Returns 0 on success.
*/
int SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos,
unsigned int protos_len)
{
OPENSSL_free(ssl->ext.alpn);
ssl->ext.alpn = OPENSSL_memdup(protos, protos_len);
if (ssl->ext.alpn == NULL) {
SSLerr(SSL_F_SSL_SET_ALPN_PROTOS, ERR_R_MALLOC_FAILURE);
return 1;
}
ssl->ext.alpn_len = protos_len;
return 0;
}
/*
* SSL_CTX_set_alpn_select_cb sets a callback function on |ctx| that is
* called during ClientHello processing in order to select an ALPN protocol
* from the client's list of offered protocols.
*/
void SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx,
SSL_CTX_alpn_select_cb_func cb,
void *arg)
{
ctx->ext.alpn_select_cb = cb;
ctx->ext.alpn_select_cb_arg = arg;
}
/*
* SSL_get0_alpn_selected gets the selected ALPN protocol (if any) from |ssl|.
* On return it sets |*data| to point to |*len| bytes of protocol name
* (not including the leading length-prefix byte). If the server didn't
* respond with a negotiated protocol then |*len| will be zero.
*/
void SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data,
unsigned int *len)
{
*data = NULL;
if (ssl->s3)
*data = ssl->s3->alpn_selected;
if (*data == NULL)
*len = 0;
else
*len = (unsigned int)ssl->s3->alpn_selected_len;
}
int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen,
const unsigned char *context, size_t contextlen,
int use_context)
{
if (s->version < TLS1_VERSION && s->version != DTLS1_BAD_VER)
return -1;
return s->method->ssl3_enc->export_keying_material(s, out, olen, label,
llen, context,
contextlen, use_context);
}
int SSL_export_keying_material_early(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen,
const unsigned char *context,
size_t contextlen)
{
if (s->version != TLS1_3_VERSION)
return 0;
return tls13_export_keying_material_early(s, out, olen, label, llen,
context, contextlen);
}
static unsigned long ssl_session_hash(const SSL_SESSION *a)
{
const unsigned char *session_id = a->session_id;
unsigned long l;
unsigned char tmp_storage[4];
if (a->session_id_length < sizeof(tmp_storage)) {
memset(tmp_storage, 0, sizeof(tmp_storage));
memcpy(tmp_storage, a->session_id, a->session_id_length);
session_id = tmp_storage;
}
l = (unsigned long)
((unsigned long)session_id[0]) |
((unsigned long)session_id[1] << 8L) |
((unsigned long)session_id[2] << 16L) |
((unsigned long)session_id[3] << 24L);
return l;
}
/*
* NB: If this function (or indeed the hash function which uses a sort of
* coarser function than this one) is changed, ensure
* SSL_CTX_has_matching_session_id() is checked accordingly. It relies on
* being able to construct an SSL_SESSION that will collide with any existing
* session with a matching session ID.
*/
static int ssl_session_cmp(const SSL_SESSION *a, const SSL_SESSION *b)
{
if (a->ssl_version != b->ssl_version)
return 1;
if (a->session_id_length != b->session_id_length)
return 1;
return memcmp(a->session_id, b->session_id, a->session_id_length);
}
/*
* These wrapper functions should remain rather than redeclaring
* SSL_SESSION_hash and SSL_SESSION_cmp for void* types and casting each
* variable. The reason is that the functions aren't static, they're exposed
* via ssl.h.
*/
SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
{
SSL_CTX *ret = NULL;
if (meth == NULL) {
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_NULL_SSL_METHOD_PASSED);
return NULL;
}
if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS, NULL))
return NULL;
if (SSL_get_ex_data_X509_STORE_CTX_idx() < 0) {
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_X509_VERIFICATION_SETUP_PROBLEMS);
goto err;
}
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL)
goto err;
ret->method = meth;
ret->min_proto_version = 0;
ret->max_proto_version = 0;
ret->mode = SSL_MODE_AUTO_RETRY;
ret->session_cache_mode = SSL_SESS_CACHE_SERVER;
ret->session_cache_size = SSL_SESSION_CACHE_MAX_SIZE_DEFAULT;
/* We take the system default. */
ret->session_timeout = meth->get_timeout();
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
ret->max_cert_list = SSL_MAX_CERT_LIST_DEFAULT;
ret->verify_mode = SSL_VERIFY_NONE;
if ((ret->cert = ssl_cert_new()) == NULL)
goto err;
ret->sessions = lh_SSL_SESSION_new(ssl_session_hash, ssl_session_cmp);
if (ret->sessions == NULL)
goto err;
ret->cert_store = X509_STORE_new();
if (ret->cert_store == NULL)
goto err;
#ifndef OPENSSL_NO_CT
ret->ctlog_store = CTLOG_STORE_new();
if (ret->ctlog_store == NULL)
goto err;
#endif
if (!SSL_CTX_set_ciphersuites(ret, TLS_DEFAULT_CIPHERSUITES))
goto err;
if (!ssl_create_cipher_list(ret->method,
ret->tls13_ciphersuites,
&ret->cipher_list, &ret->cipher_list_by_id,
SSL_DEFAULT_CIPHER_LIST, ret->cert)
|| sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS);
goto err2;
}
ret->param = X509_VERIFY_PARAM_new();
if (ret->param == NULL)
goto err;
if ((ret->md5 = EVP_get_digestbyname("ssl3-md5")) == NULL) {
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES);
goto err2;
}
if ((ret->sha1 = EVP_get_digestbyname("ssl3-sha1")) == NULL) {
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES);
goto err2;
}
if ((ret->ca_names = sk_X509_NAME_new_null()) == NULL)
goto err;
if ((ret->client_ca_names = sk_X509_NAME_new_null()) == NULL)
goto err;
if (!CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_CTX, ret, &ret->ex_data))
goto err;
if ((ret->ext.secure = OPENSSL_secure_zalloc(sizeof(*ret->ext.secure))) == NULL)
goto err;
/* No compression for DTLS */
if (!(meth->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS))
ret->comp_methods = SSL_COMP_get_compression_methods();
ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
ret->split_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
/* Setup RFC5077 ticket keys */
if ((RAND_bytes(ret->ext.tick_key_name,
sizeof(ret->ext.tick_key_name)) <= 0)
|| (RAND_priv_bytes(ret->ext.secure->tick_hmac_key,
sizeof(ret->ext.secure->tick_hmac_key)) <= 0)
|| (RAND_priv_bytes(ret->ext.secure->tick_aes_key,
sizeof(ret->ext.secure->tick_aes_key)) <= 0))
ret->options |= SSL_OP_NO_TICKET;
if (RAND_priv_bytes(ret->ext.cookie_hmac_key,
sizeof(ret->ext.cookie_hmac_key)) <= 0)
goto err;
#ifndef OPENSSL_NO_SRP
if (!SSL_CTX_SRP_CTX_init(ret))
goto err;
#endif
#ifndef OPENSSL_NO_ENGINE
# ifdef OPENSSL_SSL_CLIENT_ENGINE_AUTO
# define eng_strx(x) #x
# define eng_str(x) eng_strx(x)
/* Use specific client engine automatically... ignore errors */
{
ENGINE *eng;
eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
if (!eng) {
ERR_clear_error();
ENGINE_load_builtin_engines();
eng = ENGINE_by_id(eng_str(OPENSSL_SSL_CLIENT_ENGINE_AUTO));
}
if (!eng || !SSL_CTX_set_client_cert_engine(ret, eng))
ERR_clear_error();
}
# endif
#endif
/*
* Default is to connect to non-RI servers. When RI is more widely
* deployed might change this.
*/
ret->options |= SSL_OP_LEGACY_SERVER_CONNECT;
/*
* Disable compression by default to prevent CRIME. Applications can
* re-enable compression by configuring
* SSL_CTX_clear_options(ctx, SSL_OP_NO_COMPRESSION);
* or by using the SSL_CONF library. Similarly we also enable TLSv1.3
* middlebox compatibility by default. This may be disabled by default in
* a later OpenSSL version.
*/
ret->options |= SSL_OP_NO_COMPRESSION | SSL_OP_ENABLE_MIDDLEBOX_COMPAT;
ret->ext.status_type = TLSEXT_STATUSTYPE_nothing;
/*
* We cannot usefully set a default max_early_data here (which gets
* propagated in SSL_new(), for the following reason: setting the
* SSL field causes tls_construct_stoc_early_data() to tell the
* client that early data will be accepted when constructing a TLS 1.3
* session ticket, and the client will accordingly send us early data
* when using that ticket (if the client has early data to send).
* However, in order for the early data to actually be consumed by
* the application, the application must also have calls to
* SSL_read_early_data(); otherwise we'll just skip past the early data
* and ignore it. So, since the application must add calls to
* SSL_read_early_data(), we also require them to add
* calls to SSL_CTX_set_max_early_data() in order to use early data,
* eliminating the bandwidth-wasting early data in the case described
* above.
*/
ret->max_early_data = 0;
/*
* Default recv_max_early_data is a fully loaded single record. Could be
* split across multiple records in practice. We set this differently to
* max_early_data so that, in the default case, we do not advertise any
* support for early_data, but if a client were to send us some (e.g.
* because of an old, stale ticket) then we will tolerate it and skip over
* it.
*/
ret->recv_max_early_data = SSL3_RT_MAX_PLAIN_LENGTH;
/* By default we send two session tickets automatically in TLSv1.3 */
ret->num_tickets = 2;
ssl_ctx_system_config(ret);
return ret;
err:
SSLerr(SSL_F_SSL_CTX_NEW, ERR_R_MALLOC_FAILURE);
err2:
SSL_CTX_free(ret);
return NULL;
}
int SSL_CTX_up_ref(SSL_CTX *ctx)
{
int i;
if (CRYPTO_UP_REF(&ctx->references, &i, ctx->lock) <= 0)
return 0;
REF_PRINT_COUNT("SSL_CTX", ctx);
REF_ASSERT_ISNT(i < 2);
return ((i > 1) ? 1 : 0);
}
void SSL_CTX_free(SSL_CTX *a)
{
int i;
if (a == NULL)
return;
CRYPTO_DOWN_REF(&a->references, &i, a->lock);
REF_PRINT_COUNT("SSL_CTX", a);
if (i > 0)
return;
REF_ASSERT_ISNT(i < 0);
X509_VERIFY_PARAM_free(a->param);
dane_ctx_final(&a->dane);
/*
* Free internal session cache. However: the remove_cb() may reference
* the ex_data of SSL_CTX, thus the ex_data store can only be removed
* after the sessions were flushed.
* As the ex_data handling routines might also touch the session cache,
* the most secure solution seems to be: empty (flush) the cache, then
* free ex_data, then finally free the cache.
* (See ticket [openssl.org #212].)
*/
if (a->sessions != NULL)
SSL_CTX_flush_sessions(a, 0);
CRYPTO_free_ex_data(CRYPTO_EX_INDEX_SSL_CTX, a, &a->ex_data);
lh_SSL_SESSION_free(a->sessions);
X509_STORE_free(a->cert_store);
#ifndef OPENSSL_NO_CT
CTLOG_STORE_free(a->ctlog_store);
#endif
sk_SSL_CIPHER_free(a->cipher_list);
sk_SSL_CIPHER_free(a->cipher_list_by_id);
sk_SSL_CIPHER_free(a->tls13_ciphersuites);
ssl_cert_free(a->cert);
sk_X509_NAME_pop_free(a->ca_names, X509_NAME_free);
sk_X509_NAME_pop_free(a->client_ca_names, X509_NAME_free);
sk_X509_pop_free(a->extra_certs, X509_free);
a->comp_methods = NULL;
#ifndef OPENSSL_NO_SRTP
sk_SRTP_PROTECTION_PROFILE_free(a->srtp_profiles);
#endif
#ifndef OPENSSL_NO_SRP
SSL_CTX_SRP_CTX_free(a);
#endif
#ifndef OPENSSL_NO_ENGINE
ENGINE_finish(a->client_cert_engine);
#endif
#ifndef OPENSSL_NO_EC
OPENSSL_free(a->ext.ecpointformats);
OPENSSL_free(a->ext.supportedgroups);
#endif
OPENSSL_free(a->ext.alpn);
OPENSSL_secure_free(a->ext.secure);
CRYPTO_THREAD_lock_free(a->lock);
OPENSSL_free(a);
}
void SSL_CTX_set_default_passwd_cb(SSL_CTX *ctx, pem_password_cb *cb)
{
ctx->default_passwd_callback = cb;
}
void SSL_CTX_set_default_passwd_cb_userdata(SSL_CTX *ctx, void *u)
{
ctx->default_passwd_callback_userdata = u;
}
pem_password_cb *SSL_CTX_get_default_passwd_cb(SSL_CTX *ctx)
{
return ctx->default_passwd_callback;
}
void *SSL_CTX_get_default_passwd_cb_userdata(SSL_CTX *ctx)
{
return ctx->default_passwd_callback_userdata;
}
void SSL_set_default_passwd_cb(SSL *s, pem_password_cb *cb)
{
s->default_passwd_callback = cb;
}
void SSL_set_default_passwd_cb_userdata(SSL *s, void *u)
{
s->default_passwd_callback_userdata = u;
}
pem_password_cb *SSL_get_default_passwd_cb(SSL *s)
{
return s->default_passwd_callback;
}
void *SSL_get_default_passwd_cb_userdata(SSL *s)
{
return s->default_passwd_callback_userdata;
}
void SSL_CTX_set_cert_verify_callback(SSL_CTX *ctx,
int (*cb) (X509_STORE_CTX *, void *),
void *arg)
{
ctx->app_verify_callback = cb;
ctx->app_verify_arg = arg;
}
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode,
int (*cb) (int, X509_STORE_CTX *))
{
ctx->verify_mode = mode;
ctx->default_verify_callback = cb;
}
void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth)
{
X509_VERIFY_PARAM_set_depth(ctx->param, depth);
}
void SSL_CTX_set_cert_cb(SSL_CTX *c, int (*cb) (SSL *ssl, void *arg), void *arg)
{
ssl_cert_set_cert_cb(c->cert, cb, arg);
}
void SSL_set_cert_cb(SSL *s, int (*cb) (SSL *ssl, void *arg), void *arg)
{
ssl_cert_set_cert_cb(s->cert, cb, arg);
}
void ssl_set_masks(SSL *s)
{
CERT *c = s->cert;
uint32_t *pvalid = s->s3->tmp.valid_flags;
int rsa_enc, rsa_sign, dh_tmp, dsa_sign;
unsigned long mask_k, mask_a;
#ifndef OPENSSL_NO_EC
int have_ecc_cert, ecdsa_ok;
#endif
if (c == NULL)
return;
#ifndef OPENSSL_NO_DH
dh_tmp = (c->dh_tmp != NULL || c->dh_tmp_cb != NULL || c->dh_tmp_auto);
#else
dh_tmp = 0;
#endif
rsa_enc = pvalid[SSL_PKEY_RSA] & CERT_PKEY_VALID;
rsa_sign = pvalid[SSL_PKEY_RSA] & CERT_PKEY_VALID;
dsa_sign = pvalid[SSL_PKEY_DSA_SIGN] & CERT_PKEY_VALID;
#ifndef OPENSSL_NO_EC
have_ecc_cert = pvalid[SSL_PKEY_ECC] & CERT_PKEY_VALID;
#endif
mask_k = 0;
mask_a = 0;
#ifdef CIPHER_DEBUG
fprintf(stderr, "dht=%d re=%d rs=%d ds=%d\n",
dh_tmp, rsa_enc, rsa_sign, dsa_sign);
#endif
#ifndef OPENSSL_NO_GOST
if (ssl_has_cert(s, SSL_PKEY_GOST12_512)) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST12;
}
if (ssl_has_cert(s, SSL_PKEY_GOST12_256)) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST12;
}
if (ssl_has_cert(s, SSL_PKEY_GOST01)) {
mask_k |= SSL_kGOST;
mask_a |= SSL_aGOST01;
}
#endif
if (rsa_enc)
mask_k |= SSL_kRSA;
if (dh_tmp)
mask_k |= SSL_kDHE;
/*
* If we only have an RSA-PSS certificate allow RSA authentication
* if TLS 1.2 and peer supports it.
*/
if (rsa_enc || rsa_sign || (ssl_has_cert(s, SSL_PKEY_RSA_PSS_SIGN)
&& pvalid[SSL_PKEY_RSA_PSS_SIGN] & CERT_PKEY_EXPLICIT_SIGN
&& TLS1_get_version(s) == TLS1_2_VERSION))
mask_a |= SSL_aRSA;
if (dsa_sign) {
mask_a |= SSL_aDSS;
}
mask_a |= SSL_aNULL;
/*
* An ECC certificate may be usable for ECDH and/or ECDSA cipher suites
* depending on the key usage extension.
*/
#ifndef OPENSSL_NO_EC
if (have_ecc_cert) {
uint32_t ex_kusage;
ex_kusage = X509_get_key_usage(c->pkeys[SSL_PKEY_ECC].x509);
ecdsa_ok = ex_kusage & X509v3_KU_DIGITAL_SIGNATURE;
if (!(pvalid[SSL_PKEY_ECC] & CERT_PKEY_SIGN))
ecdsa_ok = 0;
if (ecdsa_ok)
mask_a |= SSL_aECDSA;
}
/* Allow Ed25519 for TLS 1.2 if peer supports it */
if (!(mask_a & SSL_aECDSA) && ssl_has_cert(s, SSL_PKEY_ED25519)
&& pvalid[SSL_PKEY_ED25519] & CERT_PKEY_EXPLICIT_SIGN
&& TLS1_get_version(s) == TLS1_2_VERSION)
mask_a |= SSL_aECDSA;
/* Allow Ed448 for TLS 1.2 if peer supports it */
if (!(mask_a & SSL_aECDSA) && ssl_has_cert(s, SSL_PKEY_ED448)
&& pvalid[SSL_PKEY_ED448] & CERT_PKEY_EXPLICIT_SIGN
&& TLS1_get_version(s) == TLS1_2_VERSION)
mask_a |= SSL_aECDSA;
#endif
#ifndef OPENSSL_NO_EC
mask_k |= SSL_kECDHE;
#endif
#ifndef OPENSSL_NO_PSK
mask_k |= SSL_kPSK;
mask_a |= SSL_aPSK;
if (mask_k & SSL_kRSA)
mask_k |= SSL_kRSAPSK;
if (mask_k & SSL_kDHE)
mask_k |= SSL_kDHEPSK;
if (mask_k & SSL_kECDHE)
mask_k |= SSL_kECDHEPSK;
#endif
s->s3->tmp.mask_k = mask_k;
s->s3->tmp.mask_a = mask_a;
}
#ifndef OPENSSL_NO_EC
int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s)
{
if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA) {
/* key usage, if present, must allow signing */
if (!(X509_get_key_usage(x) & X509v3_KU_DIGITAL_SIGNATURE)) {
SSLerr(SSL_F_SSL_CHECK_SRVR_ECC_CERT_AND_ALG,
SSL_R_ECC_CERT_NOT_FOR_SIGNING);
return 0;
}
}
return 1; /* all checks are ok */
}
#endif
int ssl_get_server_cert_serverinfo(SSL *s, const unsigned char **serverinfo,
size_t *serverinfo_length)
{
CERT_PKEY *cpk = s->s3->tmp.cert;
*serverinfo_length = 0;
if (cpk == NULL || cpk->serverinfo == NULL)
return 0;
*serverinfo = cpk->serverinfo;
*serverinfo_length = cpk->serverinfo_length;
return 1;
}
void ssl_update_cache(SSL *s, int mode)
{
int i;
/*
* If the session_id_length is 0, we are not supposed to cache it, and it
* would be rather hard to do anyway :-)
*/
if (s->session->session_id_length == 0)
return;
/*
* If sid_ctx_length is 0 there is no specific application context
* associated with this session, so when we try to resume it and
* SSL_VERIFY_PEER is requested to verify the client identity, we have no
* indication that this is actually a session for the proper application
* context, and the *handshake* will fail, not just the resumption attempt.
* Do not cache (on the server) these sessions that are not resumable
* (clients can set SSL_VERIFY_PEER without needing a sid_ctx set).
*/
if (s->server && s->session->sid_ctx_length == 0
&& (s->verify_mode & SSL_VERIFY_PEER) != 0)
return;
i = s->session_ctx->session_cache_mode;
if ((i & mode) != 0
&& (!s->hit || SSL_IS_TLS13(s))) {
/*
* Add the session to the internal cache. In server side TLSv1.3 we
* normally don't do this because by default it's a full stateless ticket
* with only a dummy session id so there is no reason to cache it,
* unless:
* - we are doing early_data, in which case we cache so that we can
* detect replays
* - the application has set a remove_session_cb so needs to know about
* session timeout events
* - SSL_OP_NO_TICKET is set in which case it is a stateful ticket
*/
if ((i & SSL_SESS_CACHE_NO_INTERNAL_STORE) == 0
&& (!SSL_IS_TLS13(s)
|| !s->server
|| (s->max_early_data > 0
&& (s->options & SSL_OP_NO_ANTI_REPLAY) == 0)
|| s->session_ctx->remove_session_cb != NULL
|| (s->options & SSL_OP_NO_TICKET) != 0))
SSL_CTX_add_session(s->session_ctx, s->session);
/*
* Add the session to the external cache. We do this even in server side
* TLSv1.3 without early data because some applications just want to
* know about the creation of a session and aren't doing a full cache.
*/
if (s->session_ctx->new_session_cb != NULL) {
SSL_SESSION_up_ref(s->session);
if (!s->session_ctx->new_session_cb(s, s->session))
SSL_SESSION_free(s->session);
}
}
/* auto flush every 255 connections */
if ((!(i & SSL_SESS_CACHE_NO_AUTO_CLEAR)) && ((i & mode) == mode)) {
TSAN_QUALIFIER int *stat;
if (mode & SSL_SESS_CACHE_CLIENT)
stat = &s->session_ctx->stats.sess_connect_good;
else
stat = &s->session_ctx->stats.sess_accept_good;
if ((tsan_load(stat) & 0xff) == 0xff)
SSL_CTX_flush_sessions(s->session_ctx, (unsigned long)time(NULL));
}
}
const SSL_METHOD *SSL_CTX_get_ssl_method(const SSL_CTX *ctx)
{
return ctx->method;
}
const SSL_METHOD *SSL_get_ssl_method(const SSL *s)
{
return s->method;
}
int SSL_set_ssl_method(SSL *s, const SSL_METHOD *meth)
{
int ret = 1;
if (s->method != meth) {
const SSL_METHOD *sm = s->method;
int (*hf) (SSL *) = s->handshake_func;
if (sm->version == meth->version)
s->method = meth;
else {
sm->ssl_free(s);
s->method = meth;
ret = s->method->ssl_new(s);
}
if (hf == sm->ssl_connect)
s->handshake_func = meth->ssl_connect;
else if (hf == sm->ssl_accept)
s->handshake_func = meth->ssl_accept;
}
return ret;
}
int SSL_get_error(const SSL *s, int i)
{
int reason;
unsigned long l;
BIO *bio;
if (i > 0)
return SSL_ERROR_NONE;
/*
* Make things return SSL_ERROR_SYSCALL when doing SSL_do_handshake etc,
* where we do encode the error
*/
if ((l = ERR_peek_error()) != 0) {
if (ERR_GET_LIB(l) == ERR_LIB_SYS)
return SSL_ERROR_SYSCALL;
else
return SSL_ERROR_SSL;
}
if (SSL_want_read(s)) {
bio = SSL_get_rbio(s);
if (BIO_should_read(bio))
return SSL_ERROR_WANT_READ;
else if (BIO_should_write(bio))
/*
* This one doesn't make too much sense ... We never try to write
* to the rbio, and an application program where rbio and wbio
* are separate couldn't even know what it should wait for.
* However if we ever set s->rwstate incorrectly (so that we have
* SSL_want_read(s) instead of SSL_want_write(s)) and rbio and
* wbio *are* the same, this test works around that bug; so it
* might be safer to keep it.
*/
return SSL_ERROR_WANT_WRITE;
else if (BIO_should_io_special(bio)) {
reason = BIO_get_retry_reason(bio);
if (reason == BIO_RR_CONNECT)
return SSL_ERROR_WANT_CONNECT;
else if (reason == BIO_RR_ACCEPT)
return SSL_ERROR_WANT_ACCEPT;
else
return SSL_ERROR_SYSCALL; /* unknown */
}
}
if (SSL_want_write(s)) {
/* Access wbio directly - in order to use the buffered bio if present */
bio = s->wbio;
if (BIO_should_write(bio))
return SSL_ERROR_WANT_WRITE;
else if (BIO_should_read(bio))
/*
* See above (SSL_want_read(s) with BIO_should_write(bio))
*/
return SSL_ERROR_WANT_READ;
else if (BIO_should_io_special(bio)) {
reason = BIO_get_retry_reason(bio);
if (reason == BIO_RR_CONNECT)
return SSL_ERROR_WANT_CONNECT;
else if (reason == BIO_RR_ACCEPT)
return SSL_ERROR_WANT_ACCEPT;
else
return SSL_ERROR_SYSCALL;
}
}
if (SSL_want_x509_lookup(s))
return SSL_ERROR_WANT_X509_LOOKUP;
if (SSL_want_async(s))
return SSL_ERROR_WANT_ASYNC;
if (SSL_want_async_job(s))
return SSL_ERROR_WANT_ASYNC_JOB;
if (SSL_want_client_hello_cb(s))
return SSL_ERROR_WANT_CLIENT_HELLO_CB;
if ((s->shutdown & SSL_RECEIVED_SHUTDOWN) &&
(s->s3->warn_alert == SSL_AD_CLOSE_NOTIFY))
return SSL_ERROR_ZERO_RETURN;
return SSL_ERROR_SYSCALL;
}
static int ssl_do_handshake_intern(void *vargs)
{
struct ssl_async_args *args;
SSL *s;
args = (struct ssl_async_args *)vargs;
s = args->s;
return s->handshake_func(s);
}
int SSL_do_handshake(SSL *s)
{
int ret = 1;
if (s->handshake_func == NULL) {
SSLerr(SSL_F_SSL_DO_HANDSHAKE, SSL_R_CONNECTION_TYPE_NOT_SET);
return -1;
}
ossl_statem_check_finish_init(s, -1);
s->method->ssl_renegotiate_check(s, 0);
if (SSL_in_init(s) || SSL_in_before(s)) {
if ((s->mode & SSL_MODE_ASYNC) && ASYNC_get_current_job() == NULL) {
struct ssl_async_args args;
args.s = s;
ret = ssl_start_async_job(s, &args, ssl_do_handshake_intern);
} else {
ret = s->handshake_func(s);
}
}
return ret;
}
void SSL_set_accept_state(SSL *s)
{
s->server = 1;
s->shutdown = 0;
ossl_statem_clear(s);
s->handshake_func = s->method->ssl_accept;
clear_ciphers(s);
}
void SSL_set_connect_state(SSL *s)
{
s->server = 0;
s->shutdown = 0;
ossl_statem_clear(s);
s->handshake_func = s->method->ssl_connect;
clear_ciphers(s);
}
int ssl_undefined_function(SSL *s)
{
SSLerr(SSL_F_SSL_UNDEFINED_FUNCTION, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
int ssl_undefined_void_function(void)
{
SSLerr(SSL_F_SSL_UNDEFINED_VOID_FUNCTION,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
int ssl_undefined_const_function(const SSL *s)
{
return 0;
}
const SSL_METHOD *ssl_bad_method(int ver)
{
SSLerr(SSL_F_SSL_BAD_METHOD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return NULL;
}
const char *ssl_protocol_to_string(int version)
{
switch(version)
{
case TLS1_3_VERSION:
return "TLSv1.3";
case TLS1_2_VERSION:
return "TLSv1.2";
case TLS1_1_VERSION:
return "TLSv1.1";
case TLS1_VERSION:
return "TLSv1";
case SSL3_VERSION:
return "SSLv3";
case DTLS1_BAD_VER:
return "DTLSv0.9";
case DTLS1_VERSION:
return "DTLSv1";
case DTLS1_2_VERSION:
return "DTLSv1.2";
default:
return "unknown";
}
}
const char *SSL_get_version(const SSL *s)
{
return ssl_protocol_to_string(s->version);
}
static int dup_ca_names(STACK_OF(X509_NAME) **dst, STACK_OF(X509_NAME) *src)
{
STACK_OF(X509_NAME) *sk;
X509_NAME *xn;
int i;
if (src == NULL) {
*dst = NULL;
return 1;
}
if ((sk = sk_X509_NAME_new_null()) == NULL)
return 0;
for (i = 0; i < sk_X509_NAME_num(src); i++) {
xn = X509_NAME_dup(sk_X509_NAME_value(src, i));
if (xn == NULL) {
sk_X509_NAME_pop_free(sk, X509_NAME_free);
return 0;
}
if (sk_X509_NAME_insert(sk, xn, i) == 0) {
X509_NAME_free(xn);
sk_X509_NAME_pop_free(sk, X509_NAME_free);
return 0;
}
}
*dst = sk;
return 1;
}
SSL *SSL_dup(SSL *s)
{
SSL *ret;
int i;
/* If we're not quiescent, just up_ref! */
if (!SSL_in_init(s) || !SSL_in_before(s)) {
CRYPTO_UP_REF(&s->references, &i, s->lock);
return s;
}
/*
* Otherwise, copy configuration state, and session if set.
*/
if ((ret = SSL_new(SSL_get_SSL_CTX(s))) == NULL)
return NULL;
if (s->session != NULL) {
/*
* Arranges to share the same session via up_ref. This "copies"
* session-id, SSL_METHOD, sid_ctx, and 'cert'
*/
if (!SSL_copy_session_id(ret, s))
goto err;
} else {
/*
* No session has been established yet, so we have to expect that
* s->cert or ret->cert will be changed later -- they should not both
* point to the same object, and thus we can't use
* SSL_copy_session_id.
*/
if (!SSL_set_ssl_method(ret, s->method))
goto err;
if (s->cert != NULL) {
ssl_cert_free(ret->cert);
ret->cert = ssl_cert_dup(s->cert);
if (ret->cert == NULL)
goto err;
}
if (!SSL_set_session_id_context(ret, s->sid_ctx,
(int)s->sid_ctx_length))
goto err;
}
if (!ssl_dane_dup(ret, s))
goto err;
ret->version = s->version;
ret->options = s->options;
ret->mode = s->mode;
SSL_set_max_cert_list(ret, SSL_get_max_cert_list(s));
SSL_set_read_ahead(ret, SSL_get_read_ahead(s));
ret->msg_callback = s->msg_callback;
ret->msg_callback_arg = s->msg_callback_arg;
SSL_set_verify(ret, SSL_get_verify_mode(s), SSL_get_verify_callback(s));
SSL_set_verify_depth(ret, SSL_get_verify_depth(s));
ret->generate_session_id = s->generate_session_id;
SSL_set_info_callback(ret, SSL_get_info_callback(s));
/* copy app data, a little dangerous perhaps */
if (!CRYPTO_dup_ex_data(CRYPTO_EX_INDEX_SSL, &ret->ex_data, &s->ex_data))
goto err;
/* setup rbio, and wbio */
if (s->rbio != NULL) {
if (!BIO_dup_state(s->rbio, (char *)&ret->rbio))
goto err;
}
if (s->wbio != NULL) {
if (s->wbio != s->rbio) {
if (!BIO_dup_state(s->wbio, (char *)&ret->wbio))
goto err;
} else {
BIO_up_ref(ret->rbio);
ret->wbio = ret->rbio;
}
}
ret->server = s->server;
if (s->handshake_func) {
if (s->server)
SSL_set_accept_state(ret);
else
SSL_set_connect_state(ret);
}
ret->shutdown = s->shutdown;
ret->hit = s->hit;
ret->default_passwd_callback = s->default_passwd_callback;
ret->default_passwd_callback_userdata = s->default_passwd_callback_userdata;
X509_VERIFY_PARAM_inherit(ret->param, s->param);
/* dup the cipher_list and cipher_list_by_id stacks */
if (s->cipher_list != NULL) {
if ((ret->cipher_list = sk_SSL_CIPHER_dup(s->cipher_list)) == NULL)
goto err;
}
if (s->cipher_list_by_id != NULL)
if ((ret->cipher_list_by_id = sk_SSL_CIPHER_dup(s->cipher_list_by_id))
== NULL)
goto err;
/* Dup the client_CA list */
if (!dup_ca_names(&ret->ca_names, s->ca_names)
|| !dup_ca_names(&ret->client_ca_names, s->client_ca_names))
goto err;
return ret;
err:
SSL_free(ret);
return NULL;
}
void ssl_clear_cipher_ctx(SSL *s)
{
if (s->enc_read_ctx != NULL) {
EVP_CIPHER_CTX_free(s->enc_read_ctx);
s->enc_read_ctx = NULL;
}
if (s->enc_write_ctx != NULL) {
EVP_CIPHER_CTX_free(s->enc_write_ctx);
s->enc_write_ctx = NULL;
}
#ifndef OPENSSL_NO_COMP
COMP_CTX_free(s->expand);
s->expand = NULL;
COMP_CTX_free(s->compress);
s->compress = NULL;
#endif
}
X509 *SSL_get_certificate(const SSL *s)
{
if (s->cert != NULL)
return s->cert->key->x509;
else
return NULL;
}
EVP_PKEY *SSL_get_privatekey(const SSL *s)
{
if (s->cert != NULL)
return s->cert->key->privatekey;
else
return NULL;
}
X509 *SSL_CTX_get0_certificate(const SSL_CTX *ctx)
{
if (ctx->cert != NULL)
return ctx->cert->key->x509;
else
return NULL;
}
EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx)
{
if (ctx->cert != NULL)
return ctx->cert->key->privatekey;
else
return NULL;
}
const SSL_CIPHER *SSL_get_current_cipher(const SSL *s)
{
if ((s->session != NULL) && (s->session->cipher != NULL))
return s->session->cipher;
return NULL;
}
const SSL_CIPHER *SSL_get_pending_cipher(const SSL *s)
{
return s->s3->tmp.new_cipher;
}
const COMP_METHOD *SSL_get_current_compression(const SSL *s)
{
#ifndef OPENSSL_NO_COMP
return s->compress ? COMP_CTX_get_method(s->compress) : NULL;
#else
return NULL;
#endif
}
const COMP_METHOD *SSL_get_current_expansion(const SSL *s)
{
#ifndef OPENSSL_NO_COMP
return s->expand ? COMP_CTX_get_method(s->expand) : NULL;
#else
return NULL;
#endif
}
int ssl_init_wbio_buffer(SSL *s)
{
BIO *bbio;
if (s->bbio != NULL) {
/* Already buffered. */
return 1;
}
bbio = BIO_new(BIO_f_buffer());
if (bbio == NULL || !BIO_set_read_buffer_size(bbio, 1)) {
BIO_free(bbio);
SSLerr(SSL_F_SSL_INIT_WBIO_BUFFER, ERR_R_BUF_LIB);
return 0;
}
s->bbio = bbio;
s->wbio = BIO_push(bbio, s->wbio);
return 1;
}
int ssl_free_wbio_buffer(SSL *s)
{
/* callers ensure s is never null */
if (s->bbio == NULL)
return 1;
s->wbio = BIO_pop(s->wbio);
BIO_free(s->bbio);
s->bbio = NULL;
return 1;
}
void SSL_CTX_set_quiet_shutdown(SSL_CTX *ctx, int mode)
{
ctx->quiet_shutdown = mode;
}
int SSL_CTX_get_quiet_shutdown(const SSL_CTX *ctx)
{
return ctx->quiet_shutdown;
}
void SSL_set_quiet_shutdown(SSL *s, int mode)
{
s->quiet_shutdown = mode;
}
int SSL_get_quiet_shutdown(const SSL *s)
{
return s->quiet_shutdown;
}
void SSL_set_shutdown(SSL *s, int mode)
{
s->shutdown = mode;
}
int SSL_get_shutdown(const SSL *s)
{
return s->shutdown;
}
int SSL_version(const SSL *s)
{
return s->version;
}
int SSL_client_version(const SSL *s)
{
return s->client_version;
}
SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl)
{
return ssl->ctx;
}
SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX *ctx)
{
CERT *new_cert;
if (ssl->ctx == ctx)
return ssl->ctx;
if (ctx == NULL)
ctx = ssl->session_ctx;
new_cert = ssl_cert_dup(ctx->cert);
if (new_cert == NULL) {
return NULL;
}
if (!custom_exts_copy_flags(&new_cert->custext, &ssl->cert->custext)) {
ssl_cert_free(new_cert);
return NULL;
}
ssl_cert_free(ssl->cert);
ssl->cert = new_cert;
/*
* Program invariant: |sid_ctx| has fixed size (SSL_MAX_SID_CTX_LENGTH),
* so setter APIs must prevent invalid lengths from entering the system.
*/
if (!ossl_assert(ssl->sid_ctx_length <= sizeof(ssl->sid_ctx)))
return NULL;
/*
* If the session ID context matches that of the parent SSL_CTX,
* inherit it from the new SSL_CTX as well. If however the context does
* not match (i.e., it was set per-ssl with SSL_set_session_id_context),
* leave it unchanged.
*/
if ((ssl->ctx != NULL) &&
(ssl->sid_ctx_length == ssl->ctx->sid_ctx_length) &&
(memcmp(ssl->sid_ctx, ssl->ctx->sid_ctx, ssl->sid_ctx_length) == 0)) {
ssl->sid_ctx_length = ctx->sid_ctx_length;
memcpy(&ssl->sid_ctx, &ctx->sid_ctx, sizeof(ssl->sid_ctx));
}
SSL_CTX_up_ref(ctx);
SSL_CTX_free(ssl->ctx); /* decrement reference count */
ssl->ctx = ctx;
return ssl->ctx;
}
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
{
return X509_STORE_set_default_paths(ctx->cert_store);
}
int SSL_CTX_set_default_verify_dir(SSL_CTX *ctx)
{
X509_LOOKUP *lookup;
lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_hash_dir());
if (lookup == NULL)
return 0;
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
/* Clear any errors if the default directory does not exist */
ERR_clear_error();
return 1;
}
int SSL_CTX_set_default_verify_file(SSL_CTX *ctx)
{
X509_LOOKUP *lookup;
lookup = X509_STORE_add_lookup(ctx->cert_store, X509_LOOKUP_file());
if (lookup == NULL)
return 0;
X509_LOOKUP_load_file(lookup, NULL, X509_FILETYPE_DEFAULT);
/* Clear any errors if the default file does not exist */
ERR_clear_error();
return 1;
}
int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
const char *CApath)
{
return X509_STORE_load_locations(ctx->cert_store, CAfile, CApath);
}
void SSL_set_info_callback(SSL *ssl,
void (*cb) (const SSL *ssl, int type, int val))
{
ssl->info_callback = cb;
}
/*
* One compiler (Diab DCC) doesn't like argument names in returned function
* pointer.
*/
void (*SSL_get_info_callback(const SSL *ssl)) (const SSL * /* ssl */ ,
int /* type */ ,
int /* val */ ) {
return ssl->info_callback;
}
void SSL_set_verify_result(SSL *ssl, long arg)
{
ssl->verify_result = arg;
}
long SSL_get_verify_result(const SSL *ssl)
{
return ssl->verify_result;
}
size_t SSL_get_client_random(const SSL *ssl, unsigned char *out, size_t outlen)
{
if (outlen == 0)
return sizeof(ssl->s3->client_random);
if (outlen > sizeof(ssl->s3->client_random))
outlen = sizeof(ssl->s3->client_random);
memcpy(out, ssl->s3->client_random, outlen);
return outlen;
}
size_t SSL_get_server_random(const SSL *ssl, unsigned char *out, size_t outlen)
{
if (outlen == 0)
return sizeof(ssl->s3->server_random);
if (outlen > sizeof(ssl->s3->server_random))
outlen = sizeof(ssl->s3->server_random);
memcpy(out, ssl->s3->server_random, outlen);
return outlen;
}
size_t SSL_SESSION_get_master_key(const SSL_SESSION *session,
unsigned char *out, size_t outlen)
{
if (outlen == 0)
return session->master_key_length;
if (outlen > session->master_key_length)
outlen = session->master_key_length;
memcpy(out, session->master_key, outlen);
return outlen;
}
int SSL_SESSION_set1_master_key(SSL_SESSION *sess, const unsigned char *in,
size_t len)
{
if (len > sizeof(sess->master_key))
return 0;
memcpy(sess->master_key, in, len);
sess->master_key_length = len;
return 1;
}
int SSL_set_ex_data(SSL *s, int idx, void *arg)
{
return CRYPTO_set_ex_data(&s->ex_data, idx, arg);
}
void *SSL_get_ex_data(const SSL *s, int idx)
{
return CRYPTO_get_ex_data(&s->ex_data, idx);
}
int SSL_CTX_set_ex_data(SSL_CTX *s, int idx, void *arg)
{
return CRYPTO_set_ex_data(&s->ex_data, idx, arg);
}
void *SSL_CTX_get_ex_data(const SSL_CTX *s, int idx)
{
return CRYPTO_get_ex_data(&s->ex_data, idx);
}
X509_STORE *SSL_CTX_get_cert_store(const SSL_CTX *ctx)
{
return ctx->cert_store;
}
void SSL_CTX_set_cert_store(SSL_CTX *ctx, X509_STORE *store)
{
X509_STORE_free(ctx->cert_store);
ctx->cert_store = store;
}
void SSL_CTX_set1_cert_store(SSL_CTX *ctx, X509_STORE *store)
{
if (store != NULL)
X509_STORE_up_ref(store);
SSL_CTX_set_cert_store(ctx, store);
}
int SSL_want(const SSL *s)
{
return s->rwstate;
}
/**
* \brief Set the callback for generating temporary DH keys.
* \param ctx the SSL context.
* \param dh the callback
*/
#ifndef OPENSSL_NO_DH
void SSL_CTX_set_tmp_dh_callback(SSL_CTX *ctx,
DH *(*dh) (SSL *ssl, int is_export,
int keylength))
{
SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
}
void SSL_set_tmp_dh_callback(SSL *ssl, DH *(*dh) (SSL *ssl, int is_export,
int keylength))
{
SSL_callback_ctrl(ssl, SSL_CTRL_SET_TMP_DH_CB, (void (*)(void))dh);
}
#endif
#ifndef OPENSSL_NO_PSK
int SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *identity_hint)
{
if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
SSLerr(SSL_F_SSL_CTX_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
OPENSSL_free(ctx->cert->psk_identity_hint);
if (identity_hint != NULL) {
ctx->cert->psk_identity_hint = OPENSSL_strdup(identity_hint);
if (ctx->cert->psk_identity_hint == NULL)
return 0;
} else
ctx->cert->psk_identity_hint = NULL;
return 1;
}
int SSL_use_psk_identity_hint(SSL *s, const char *identity_hint)
{
if (s == NULL)
return 0;
if (identity_hint != NULL && strlen(identity_hint) > PSK_MAX_IDENTITY_LEN) {
SSLerr(SSL_F_SSL_USE_PSK_IDENTITY_HINT, SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
OPENSSL_free(s->cert->psk_identity_hint);
if (identity_hint != NULL) {
s->cert->psk_identity_hint = OPENSSL_strdup(identity_hint);
if (s->cert->psk_identity_hint == NULL)
return 0;
} else
s->cert->psk_identity_hint = NULL;
return 1;
}
const char *SSL_get_psk_identity_hint(const SSL *s)
{
if (s == NULL || s->session == NULL)
return NULL;
return s->session->psk_identity_hint;
}
const char *SSL_get_psk_identity(const SSL *s)
{
if (s == NULL || s->session == NULL)
return NULL;
return s->session->psk_identity;
}
void SSL_set_psk_client_callback(SSL *s, SSL_psk_client_cb_func cb)
{
s->psk_client_callback = cb;
}
void SSL_CTX_set_psk_client_callback(SSL_CTX *ctx, SSL_psk_client_cb_func cb)
{
ctx->psk_client_callback = cb;
}
void SSL_set_psk_server_callback(SSL *s, SSL_psk_server_cb_func cb)
{
s->psk_server_callback = cb;
}
void SSL_CTX_set_psk_server_callback(SSL_CTX *ctx, SSL_psk_server_cb_func cb)
{
ctx->psk_server_callback = cb;
}
#endif
void SSL_set_psk_find_session_callback(SSL *s, SSL_psk_find_session_cb_func cb)
{
s->psk_find_session_cb = cb;
}
void SSL_CTX_set_psk_find_session_callback(SSL_CTX *ctx,
SSL_psk_find_session_cb_func cb)
{
ctx->psk_find_session_cb = cb;
}
void SSL_set_psk_use_session_callback(SSL *s, SSL_psk_use_session_cb_func cb)
{
s->psk_use_session_cb = cb;
}
void SSL_CTX_set_psk_use_session_callback(SSL_CTX *ctx,
SSL_psk_use_session_cb_func cb)
{
ctx->psk_use_session_cb = cb;
}
void SSL_CTX_set_msg_callback(SSL_CTX *ctx,
void (*cb) (int write_p, int version,
int content_type, const void *buf,
size_t len, SSL *ssl, void *arg))
{
SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
}
void SSL_set_msg_callback(SSL *ssl,
void (*cb) (int write_p, int version,
int content_type, const void *buf,
size_t len, SSL *ssl, void *arg))
{
SSL_callback_ctrl(ssl, SSL_CTRL_SET_MSG_CALLBACK, (void (*)(void))cb);
}
void SSL_CTX_set_not_resumable_session_callback(SSL_CTX *ctx,
int (*cb) (SSL *ssl,
int
is_forward_secure))
{
SSL_CTX_callback_ctrl(ctx, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB,
(void (*)(void))cb);
}
void SSL_set_not_resumable_session_callback(SSL *ssl,
int (*cb) (SSL *ssl,
int is_forward_secure))
{
SSL_callback_ctrl(ssl, SSL_CTRL_SET_NOT_RESUMABLE_SESS_CB,
(void (*)(void))cb);
}
void SSL_CTX_set_record_padding_callback(SSL_CTX *ctx,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg))
{
ctx->record_padding_cb = cb;
}
void SSL_CTX_set_record_padding_callback_arg(SSL_CTX *ctx, void *arg)
{
ctx->record_padding_arg = arg;
}
void *SSL_CTX_get_record_padding_callback_arg(const SSL_CTX *ctx)
{
return ctx->record_padding_arg;
}
int SSL_CTX_set_block_padding(SSL_CTX *ctx, size_t block_size)
{
/* block size of 0 or 1 is basically no padding */
if (block_size == 1)
ctx->block_padding = 0;
else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH)
ctx->block_padding = block_size;
else
return 0;
return 1;
}
void SSL_set_record_padding_callback(SSL *ssl,
size_t (*cb) (SSL *ssl, int type,
size_t len, void *arg))
{
ssl->record_padding_cb = cb;
}
void SSL_set_record_padding_callback_arg(SSL *ssl, void *arg)
{
ssl->record_padding_arg = arg;
}
void *SSL_get_record_padding_callback_arg(const SSL *ssl)
{
return ssl->record_padding_arg;
}
int SSL_set_block_padding(SSL *ssl, size_t block_size)
{
/* block size of 0 or 1 is basically no padding */
if (block_size == 1)
ssl->block_padding = 0;
else if (block_size <= SSL3_RT_MAX_PLAIN_LENGTH)
ssl->block_padding = block_size;
else
return 0;
return 1;
}
int SSL_set_num_tickets(SSL *s, size_t num_tickets)
{
s->num_tickets = num_tickets;
return 1;
}
size_t SSL_get_num_tickets(const SSL *s)
{
return s->num_tickets;
}
int SSL_CTX_set_num_tickets(SSL_CTX *ctx, size_t num_tickets)
{
ctx->num_tickets = num_tickets;
return 1;
}
size_t SSL_CTX_get_num_tickets(const SSL_CTX *ctx)
{
return ctx->num_tickets;
}
/*
* Allocates new EVP_MD_CTX and sets pointer to it into given pointer
* variable, freeing EVP_MD_CTX previously stored in that variable, if any.
* If EVP_MD pointer is passed, initializes ctx with this |md|.
* Returns the newly allocated ctx;
*/
EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md)
{
ssl_clear_hash_ctx(hash);
*hash = EVP_MD_CTX_new();
if (*hash == NULL || (md && EVP_DigestInit_ex(*hash, md, NULL) <= 0)) {
EVP_MD_CTX_free(*hash);
*hash = NULL;
return NULL;
}
return *hash;
}
void ssl_clear_hash_ctx(EVP_MD_CTX **hash)
{
EVP_MD_CTX_free(*hash);
*hash = NULL;
}
/* Retrieve handshake hashes */
int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,
size_t *hashlen)
{
EVP_MD_CTX *ctx = NULL;
EVP_MD_CTX *hdgst = s->s3->handshake_dgst;
int hashleni = EVP_MD_CTX_size(hdgst);
int ret = 0;
if (hashleni < 0 || (size_t)hashleni > outlen) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH,
ERR_R_INTERNAL_ERROR);
goto err;
}
ctx = EVP_MD_CTX_new();
if (ctx == NULL)
goto err;
if (!EVP_MD_CTX_copy_ex(ctx, hdgst)
|| EVP_DigestFinal_ex(ctx, out, NULL) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_HANDSHAKE_HASH,
ERR_R_INTERNAL_ERROR);
goto err;
}
*hashlen = hashleni;
ret = 1;
err:
EVP_MD_CTX_free(ctx);
return ret;
}
-int SSL_session_reused(SSL *s)
+int SSL_session_reused(const SSL *s)
{
return s->hit;
}
int SSL_is_server(const SSL *s)
{
return s->server;
}
#if OPENSSL_API_COMPAT < 0x10100000L
void SSL_set_debug(SSL *s, int debug)
{
/* Old function was do-nothing anyway... */
(void)s;
(void)debug;
}
#endif
void SSL_set_security_level(SSL *s, int level)
{
s->cert->sec_level = level;
}
int SSL_get_security_level(const SSL *s)
{
return s->cert->sec_level;
}
void SSL_set_security_callback(SSL *s,
int (*cb) (const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid,
void *other, void *ex))
{
s->cert->sec_cb = cb;
}
int (*SSL_get_security_callback(const SSL *s)) (const SSL *s,
const SSL_CTX *ctx, int op,
int bits, int nid, void *other,
void *ex) {
return s->cert->sec_cb;
}
void SSL_set0_security_ex_data(SSL *s, void *ex)
{
s->cert->sec_ex = ex;
}
void *SSL_get0_security_ex_data(const SSL *s)
{
return s->cert->sec_ex;
}
void SSL_CTX_set_security_level(SSL_CTX *ctx, int level)
{
ctx->cert->sec_level = level;
}
int SSL_CTX_get_security_level(const SSL_CTX *ctx)
{
return ctx->cert->sec_level;
}
void SSL_CTX_set_security_callback(SSL_CTX *ctx,
int (*cb) (const SSL *s, const SSL_CTX *ctx,
int op, int bits, int nid,
void *other, void *ex))
{
ctx->cert->sec_cb = cb;
}
int (*SSL_CTX_get_security_callback(const SSL_CTX *ctx)) (const SSL *s,
const SSL_CTX *ctx,
int op, int bits,
int nid,
void *other,
void *ex) {
return ctx->cert->sec_cb;
}
void SSL_CTX_set0_security_ex_data(SSL_CTX *ctx, void *ex)
{
ctx->cert->sec_ex = ex;
}
void *SSL_CTX_get0_security_ex_data(const SSL_CTX *ctx)
{
return ctx->cert->sec_ex;
}
/*
* Get/Set/Clear options in SSL_CTX or SSL, formerly macros, now functions that
* can return unsigned long, instead of the generic long return value from the
* control interface.
*/
unsigned long SSL_CTX_get_options(const SSL_CTX *ctx)
{
return ctx->options;
}
unsigned long SSL_get_options(const SSL *s)
{
return s->options;
}
unsigned long SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op)
{
return ctx->options |= op;
}
unsigned long SSL_set_options(SSL *s, unsigned long op)
{
return s->options |= op;
}
unsigned long SSL_CTX_clear_options(SSL_CTX *ctx, unsigned long op)
{
return ctx->options &= ~op;
}
unsigned long SSL_clear_options(SSL *s, unsigned long op)
{
return s->options &= ~op;
}
STACK_OF(X509) *SSL_get0_verified_chain(const SSL *s)
{
return s->verified_chain;
}
IMPLEMENT_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id);
#ifndef OPENSSL_NO_CT
/*
* Moves SCTs from the |src| stack to the |dst| stack.
* The source of each SCT will be set to |origin|.
* If |dst| points to a NULL pointer, a new stack will be created and owned by
* the caller.
* Returns the number of SCTs moved, or a negative integer if an error occurs.
*/
static int ct_move_scts(STACK_OF(SCT) **dst, STACK_OF(SCT) *src,
sct_source_t origin)
{
int scts_moved = 0;
SCT *sct = NULL;
if (*dst == NULL) {
*dst = sk_SCT_new_null();
if (*dst == NULL) {
SSLerr(SSL_F_CT_MOVE_SCTS, ERR_R_MALLOC_FAILURE);
goto err;
}
}
while ((sct = sk_SCT_pop(src)) != NULL) {
if (SCT_set_source(sct, origin) != 1)
goto err;
if (sk_SCT_push(*dst, sct) <= 0)
goto err;
scts_moved += 1;
}
return scts_moved;
err:
if (sct != NULL)
sk_SCT_push(src, sct); /* Put the SCT back */
return -1;
}
/*
* Look for data collected during ServerHello and parse if found.
* Returns the number of SCTs extracted.
*/
static int ct_extract_tls_extension_scts(SSL *s)
{
int scts_extracted = 0;
if (s->ext.scts != NULL) {
const unsigned char *p = s->ext.scts;
STACK_OF(SCT) *scts = o2i_SCT_LIST(NULL, &p, s->ext.scts_len);
scts_extracted = ct_move_scts(&s->scts, scts, SCT_SOURCE_TLS_EXTENSION);
SCT_LIST_free(scts);
}
return scts_extracted;
}
/*
* Checks for an OCSP response and then attempts to extract any SCTs found if it
* contains an SCT X509 extension. They will be stored in |s->scts|.
* Returns:
* - The number of SCTs extracted, assuming an OCSP response exists.
* - 0 if no OCSP response exists or it contains no SCTs.
* - A negative integer if an error occurs.
*/
static int ct_extract_ocsp_response_scts(SSL *s)
{
# ifndef OPENSSL_NO_OCSP
int scts_extracted = 0;
const unsigned char *p;
OCSP_BASICRESP *br = NULL;
OCSP_RESPONSE *rsp = NULL;
STACK_OF(SCT) *scts = NULL;
int i;
if (s->ext.ocsp.resp == NULL || s->ext.ocsp.resp_len == 0)
goto err;
p = s->ext.ocsp.resp;
rsp = d2i_OCSP_RESPONSE(NULL, &p, (int)s->ext.ocsp.resp_len);
if (rsp == NULL)
goto err;
br = OCSP_response_get1_basic(rsp);
if (br == NULL)
goto err;
for (i = 0; i < OCSP_resp_count(br); ++i) {
OCSP_SINGLERESP *single = OCSP_resp_get0(br, i);
if (single == NULL)
continue;
scts =
OCSP_SINGLERESP_get1_ext_d2i(single, NID_ct_cert_scts, NULL, NULL);
scts_extracted =
ct_move_scts(&s->scts, scts, SCT_SOURCE_OCSP_STAPLED_RESPONSE);
if (scts_extracted < 0)
goto err;
}
err:
SCT_LIST_free(scts);
OCSP_BASICRESP_free(br);
OCSP_RESPONSE_free(rsp);
return scts_extracted;
# else
/* Behave as if no OCSP response exists */
return 0;
# endif
}
/*
* Attempts to extract SCTs from the peer certificate.
* Return the number of SCTs extracted, or a negative integer if an error
* occurs.
*/
static int ct_extract_x509v3_extension_scts(SSL *s)
{
int scts_extracted = 0;
X509 *cert = s->session != NULL ? s->session->peer : NULL;
if (cert != NULL) {
STACK_OF(SCT) *scts =
X509_get_ext_d2i(cert, NID_ct_precert_scts, NULL, NULL);
scts_extracted =
ct_move_scts(&s->scts, scts, SCT_SOURCE_X509V3_EXTENSION);
SCT_LIST_free(scts);
}
return scts_extracted;
}
/*
* Attempts to find all received SCTs by checking TLS extensions, the OCSP
* response (if it exists) and X509v3 extensions in the certificate.
* Returns NULL if an error occurs.
*/
const STACK_OF(SCT) *SSL_get0_peer_scts(SSL *s)
{
if (!s->scts_parsed) {
if (ct_extract_tls_extension_scts(s) < 0 ||
ct_extract_ocsp_response_scts(s) < 0 ||
ct_extract_x509v3_extension_scts(s) < 0)
goto err;
s->scts_parsed = 1;
}
return s->scts;
err:
return NULL;
}
static int ct_permissive(const CT_POLICY_EVAL_CTX * ctx,
const STACK_OF(SCT) *scts, void *unused_arg)
{
return 1;
}
static int ct_strict(const CT_POLICY_EVAL_CTX * ctx,
const STACK_OF(SCT) *scts, void *unused_arg)
{
int count = scts != NULL ? sk_SCT_num(scts) : 0;
int i;
for (i = 0; i < count; ++i) {
SCT *sct = sk_SCT_value(scts, i);
int status = SCT_get_validation_status(sct);
if (status == SCT_VALIDATION_STATUS_VALID)
return 1;
}
SSLerr(SSL_F_CT_STRICT, SSL_R_NO_VALID_SCTS);
return 0;
}
int SSL_set_ct_validation_callback(SSL *s, ssl_ct_validation_cb callback,
void *arg)
{
/*
* Since code exists that uses the custom extension handler for CT, look
* for this and throw an error if they have already registered to use CT.
*/
if (callback != NULL && SSL_CTX_has_client_custom_ext(s->ctx,
TLSEXT_TYPE_signed_certificate_timestamp))
{
SSLerr(SSL_F_SSL_SET_CT_VALIDATION_CALLBACK,
SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
return 0;
}
if (callback != NULL) {
/*
* If we are validating CT, then we MUST accept SCTs served via OCSP
*/
if (!SSL_set_tlsext_status_type(s, TLSEXT_STATUSTYPE_ocsp))
return 0;
}
s->ct_validation_callback = callback;
s->ct_validation_callback_arg = arg;
return 1;
}
int SSL_CTX_set_ct_validation_callback(SSL_CTX *ctx,
ssl_ct_validation_cb callback, void *arg)
{
/*
* Since code exists that uses the custom extension handler for CT, look for
* this and throw an error if they have already registered to use CT.
*/
if (callback != NULL && SSL_CTX_has_client_custom_ext(ctx,
TLSEXT_TYPE_signed_certificate_timestamp))
{
SSLerr(SSL_F_SSL_CTX_SET_CT_VALIDATION_CALLBACK,
SSL_R_CUSTOM_EXT_HANDLER_ALREADY_INSTALLED);
return 0;
}
ctx->ct_validation_callback = callback;
ctx->ct_validation_callback_arg = arg;
return 1;
}
int SSL_ct_is_enabled(const SSL *s)
{
return s->ct_validation_callback != NULL;
}
int SSL_CTX_ct_is_enabled(const SSL_CTX *ctx)
{
return ctx->ct_validation_callback != NULL;
}
int ssl_validate_ct(SSL *s)
{
int ret = 0;
X509 *cert = s->session != NULL ? s->session->peer : NULL;
X509 *issuer;
SSL_DANE *dane = &s->dane;
CT_POLICY_EVAL_CTX *ctx = NULL;
const STACK_OF(SCT) *scts;
/*
* If no callback is set, the peer is anonymous, or its chain is invalid,
* skip SCT validation - just return success. Applications that continue
* handshakes without certificates, with unverified chains, or pinned leaf
* certificates are outside the scope of the WebPKI and CT.
*
* The above exclusions notwithstanding the vast majority of peers will
* have rather ordinary certificate chains validated by typical
* applications that perform certificate verification and therefore will
* process SCTs when enabled.
*/
if (s->ct_validation_callback == NULL || cert == NULL ||
s->verify_result != X509_V_OK ||
s->verified_chain == NULL || sk_X509_num(s->verified_chain) <= 1)
return 1;
/*
* CT not applicable for chains validated via DANE-TA(2) or DANE-EE(3)
* trust-anchors. See https://tools.ietf.org/html/rfc7671#section-4.2
*/
if (DANETLS_ENABLED(dane) && dane->mtlsa != NULL) {
switch (dane->mtlsa->usage) {
case DANETLS_USAGE_DANE_TA:
case DANETLS_USAGE_DANE_EE:
return 1;
}
}
ctx = CT_POLICY_EVAL_CTX_new();
if (ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_VALIDATE_CT,
ERR_R_MALLOC_FAILURE);
goto end;
}
issuer = sk_X509_value(s->verified_chain, 1);
CT_POLICY_EVAL_CTX_set1_cert(ctx, cert);
CT_POLICY_EVAL_CTX_set1_issuer(ctx, issuer);
CT_POLICY_EVAL_CTX_set_shared_CTLOG_STORE(ctx, s->ctx->ctlog_store);
CT_POLICY_EVAL_CTX_set_time(
ctx, (uint64_t)SSL_SESSION_get_time(SSL_get0_session(s)) * 1000);
scts = SSL_get0_peer_scts(s);
/*
* This function returns success (> 0) only when all the SCTs are valid, 0
* when some are invalid, and < 0 on various internal errors (out of
* memory, etc.). Having some, or even all, invalid SCTs is not sufficient
* reason to abort the handshake, that decision is up to the callback.
* Therefore, we error out only in the unexpected case that the return
* value is negative.
*
* XXX: One might well argue that the return value of this function is an
* unfortunate design choice. Its job is only to determine the validation
* status of each of the provided SCTs. So long as it correctly separates
* the wheat from the chaff it should return success. Failure in this case
* ought to correspond to an inability to carry out its duties.
*/
if (SCT_LIST_validate(scts, ctx) < 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL_VALIDATE_CT,
SSL_R_SCT_VERIFICATION_FAILED);
goto end;
}
ret = s->ct_validation_callback(ctx, scts, s->ct_validation_callback_arg);
if (ret < 0)
ret = 0; /* This function returns 0 on failure */
if (!ret)
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_SSL_VALIDATE_CT,
SSL_R_CALLBACK_FAILED);
end:
CT_POLICY_EVAL_CTX_free(ctx);
/*
* With SSL_VERIFY_NONE the session may be cached and re-used despite a
* failure return code here. Also the application may wish the complete
* the handshake, and then disconnect cleanly at a higher layer, after
* checking the verification status of the completed connection.
*
* We therefore force a certificate verification failure which will be
* visible via SSL_get_verify_result() and cached as part of any resumed
* session.
*
* Note: the permissive callback is for information gathering only, always
* returns success, and does not affect verification status. Only the
* strict callback or a custom application-specified callback can trigger
* connection failure or record a verification error.
*/
if (ret <= 0)
s->verify_result = X509_V_ERR_NO_VALID_SCTS;
return ret;
}
int SSL_CTX_enable_ct(SSL_CTX *ctx, int validation_mode)
{
switch (validation_mode) {
default:
SSLerr(SSL_F_SSL_CTX_ENABLE_CT, SSL_R_INVALID_CT_VALIDATION_TYPE);
return 0;
case SSL_CT_VALIDATION_PERMISSIVE:
return SSL_CTX_set_ct_validation_callback(ctx, ct_permissive, NULL);
case SSL_CT_VALIDATION_STRICT:
return SSL_CTX_set_ct_validation_callback(ctx, ct_strict, NULL);
}
}
int SSL_enable_ct(SSL *s, int validation_mode)
{
switch (validation_mode) {
default:
SSLerr(SSL_F_SSL_ENABLE_CT, SSL_R_INVALID_CT_VALIDATION_TYPE);
return 0;
case SSL_CT_VALIDATION_PERMISSIVE:
return SSL_set_ct_validation_callback(s, ct_permissive, NULL);
case SSL_CT_VALIDATION_STRICT:
return SSL_set_ct_validation_callback(s, ct_strict, NULL);
}
}
int SSL_CTX_set_default_ctlog_list_file(SSL_CTX *ctx)
{
return CTLOG_STORE_load_default_file(ctx->ctlog_store);
}
int SSL_CTX_set_ctlog_list_file(SSL_CTX *ctx, const char *path)
{
return CTLOG_STORE_load_file(ctx->ctlog_store, path);
}
void SSL_CTX_set0_ctlog_store(SSL_CTX *ctx, CTLOG_STORE * logs)
{
CTLOG_STORE_free(ctx->ctlog_store);
ctx->ctlog_store = logs;
}
const CTLOG_STORE *SSL_CTX_get0_ctlog_store(const SSL_CTX *ctx)
{
return ctx->ctlog_store;
}
#endif /* OPENSSL_NO_CT */
void SSL_CTX_set_client_hello_cb(SSL_CTX *c, SSL_client_hello_cb_fn cb,
void *arg)
{
c->client_hello_cb = cb;
c->client_hello_cb_arg = arg;
}
int SSL_client_hello_isv2(SSL *s)
{
if (s->clienthello == NULL)
return 0;
return s->clienthello->isv2;
}
unsigned int SSL_client_hello_get0_legacy_version(SSL *s)
{
if (s->clienthello == NULL)
return 0;
return s->clienthello->legacy_version;
}
size_t SSL_client_hello_get0_random(SSL *s, const unsigned char **out)
{
if (s->clienthello == NULL)
return 0;
if (out != NULL)
*out = s->clienthello->random;
return SSL3_RANDOM_SIZE;
}
size_t SSL_client_hello_get0_session_id(SSL *s, const unsigned char **out)
{
if (s->clienthello == NULL)
return 0;
if (out != NULL)
*out = s->clienthello->session_id;
return s->clienthello->session_id_len;
}
size_t SSL_client_hello_get0_ciphers(SSL *s, const unsigned char **out)
{
if (s->clienthello == NULL)
return 0;
if (out != NULL)
*out = PACKET_data(&s->clienthello->ciphersuites);
return PACKET_remaining(&s->clienthello->ciphersuites);
}
size_t SSL_client_hello_get0_compression_methods(SSL *s, const unsigned char **out)
{
if (s->clienthello == NULL)
return 0;
if (out != NULL)
*out = s->clienthello->compressions;
return s->clienthello->compressions_len;
}
int SSL_client_hello_get1_extensions_present(SSL *s, int **out, size_t *outlen)
{
RAW_EXTENSION *ext;
int *present;
size_t num = 0, i;
if (s->clienthello == NULL || out == NULL || outlen == NULL)
return 0;
for (i = 0; i < s->clienthello->pre_proc_exts_len; i++) {
ext = s->clienthello->pre_proc_exts + i;
if (ext->present)
num++;
}
+ if (num == 0) {
+ *out = NULL;
+ *outlen = 0;
+ return 1;
+ }
if ((present = OPENSSL_malloc(sizeof(*present) * num)) == NULL) {
SSLerr(SSL_F_SSL_CLIENT_HELLO_GET1_EXTENSIONS_PRESENT,
ERR_R_MALLOC_FAILURE);
return 0;
}
for (i = 0; i < s->clienthello->pre_proc_exts_len; i++) {
ext = s->clienthello->pre_proc_exts + i;
if (ext->present) {
if (ext->received_order >= num)
goto err;
present[ext->received_order] = ext->type;
}
}
*out = present;
*outlen = num;
return 1;
err:
OPENSSL_free(present);
return 0;
}
int SSL_client_hello_get0_ext(SSL *s, unsigned int type, const unsigned char **out,
size_t *outlen)
{
size_t i;
RAW_EXTENSION *r;
if (s->clienthello == NULL)
return 0;
for (i = 0; i < s->clienthello->pre_proc_exts_len; ++i) {
r = s->clienthello->pre_proc_exts + i;
if (r->present && r->type == type) {
if (out != NULL)
*out = PACKET_data(&r->data);
if (outlen != NULL)
*outlen = PACKET_remaining(&r->data);
return 1;
}
}
return 0;
}
int SSL_free_buffers(SSL *ssl)
{
RECORD_LAYER *rl = &ssl->rlayer;
if (RECORD_LAYER_read_pending(rl) || RECORD_LAYER_write_pending(rl))
return 0;
RECORD_LAYER_release(rl);
return 1;
}
int SSL_alloc_buffers(SSL *ssl)
{
return ssl3_setup_buffers(ssl);
}
void SSL_CTX_set_keylog_callback(SSL_CTX *ctx, SSL_CTX_keylog_cb_func cb)
{
ctx->keylog_callback = cb;
}
SSL_CTX_keylog_cb_func SSL_CTX_get_keylog_callback(const SSL_CTX *ctx)
{
return ctx->keylog_callback;
}
static int nss_keylog_int(const char *prefix,
SSL *ssl,
const uint8_t *parameter_1,
size_t parameter_1_len,
const uint8_t *parameter_2,
size_t parameter_2_len)
{
char *out = NULL;
char *cursor = NULL;
size_t out_len = 0;
size_t i;
size_t prefix_len;
if (ssl->ctx->keylog_callback == NULL)
return 1;
/*
* Our output buffer will contain the following strings, rendered with
* space characters in between, terminated by a NULL character: first the
* prefix, then the first parameter, then the second parameter. The
* meaning of each parameter depends on the specific key material being
* logged. Note that the first and second parameters are encoded in
* hexadecimal, so we need a buffer that is twice their lengths.
*/
prefix_len = strlen(prefix);
out_len = prefix_len + (2 * parameter_1_len) + (2 * parameter_2_len) + 3;
if ((out = cursor = OPENSSL_malloc(out_len)) == NULL) {
SSLfatal(ssl, SSL_AD_INTERNAL_ERROR, SSL_F_NSS_KEYLOG_INT,
ERR_R_MALLOC_FAILURE);
return 0;
}
strcpy(cursor, prefix);
cursor += prefix_len;
*cursor++ = ' ';
for (i = 0; i < parameter_1_len; i++) {
sprintf(cursor, "%02x", parameter_1[i]);
cursor += 2;
}
*cursor++ = ' ';
for (i = 0; i < parameter_2_len; i++) {
sprintf(cursor, "%02x", parameter_2[i]);
cursor += 2;
}
*cursor = '\0';
ssl->ctx->keylog_callback(ssl, (const char *)out);
OPENSSL_clear_free(out, out_len);
return 1;
}
int ssl_log_rsa_client_key_exchange(SSL *ssl,
const uint8_t *encrypted_premaster,
size_t encrypted_premaster_len,
const uint8_t *premaster,
size_t premaster_len)
{
if (encrypted_premaster_len < 8) {
SSLfatal(ssl, SSL_AD_INTERNAL_ERROR,
SSL_F_SSL_LOG_RSA_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
return 0;
}
/* We only want the first 8 bytes of the encrypted premaster as a tag. */
return nss_keylog_int("RSA",
ssl,
encrypted_premaster,
8,
premaster,
premaster_len);
}
int ssl_log_secret(SSL *ssl,
const char *label,
const uint8_t *secret,
size_t secret_len)
{
return nss_keylog_int(label,
ssl,
ssl->s3->client_random,
SSL3_RANDOM_SIZE,
secret,
secret_len);
}
#define SSLV2_CIPHER_LEN 3
int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format)
{
int n;
n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
if (PACKET_remaining(cipher_suites) == 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SSL_CACHE_CIPHERLIST,
SSL_R_NO_CIPHERS_SPECIFIED);
return 0;
}
if (PACKET_remaining(cipher_suites) % n != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
return 0;
}
OPENSSL_free(s->s3->tmp.ciphers_raw);
s->s3->tmp.ciphers_raw = NULL;
s->s3->tmp.ciphers_rawlen = 0;
if (sslv2format) {
size_t numciphers = PACKET_remaining(cipher_suites) / n;
PACKET sslv2ciphers = *cipher_suites;
unsigned int leadbyte;
unsigned char *raw;
/*
* We store the raw ciphers list in SSLv3+ format so we need to do some
* preprocessing to convert the list first. If there are any SSLv2 only
* ciphersuites with a non-zero leading byte then we are going to
* slightly over allocate because we won't store those. But that isn't a
* problem.
*/
raw = OPENSSL_malloc(numciphers * TLS_CIPHER_LEN);
s->s3->tmp.ciphers_raw = raw;
if (raw == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
ERR_R_MALLOC_FAILURE);
return 0;
}
for (s->s3->tmp.ciphers_rawlen = 0;
PACKET_remaining(&sslv2ciphers) > 0;
raw += TLS_CIPHER_LEN) {
if (!PACKET_get_1(&sslv2ciphers, &leadbyte)
|| (leadbyte == 0
&& !PACKET_copy_bytes(&sslv2ciphers, raw,
TLS_CIPHER_LEN))
|| (leadbyte != 0
&& !PACKET_forward(&sslv2ciphers, TLS_CIPHER_LEN))) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
SSL_R_BAD_PACKET);
OPENSSL_free(s->s3->tmp.ciphers_raw);
s->s3->tmp.ciphers_raw = NULL;
s->s3->tmp.ciphers_rawlen = 0;
return 0;
}
if (leadbyte == 0)
s->s3->tmp.ciphers_rawlen += TLS_CIPHER_LEN;
}
} else if (!PACKET_memdup(cipher_suites, &s->s3->tmp.ciphers_raw,
&s->s3->tmp.ciphers_rawlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CACHE_CIPHERLIST,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int SSL_bytes_to_cipher_list(SSL *s, const unsigned char *bytes, size_t len,
int isv2format, STACK_OF(SSL_CIPHER) **sk,
STACK_OF(SSL_CIPHER) **scsvs)
{
PACKET pkt;
if (!PACKET_buf_init(&pkt, bytes, len))
return 0;
return bytes_to_cipher_list(s, &pkt, sk, scsvs, isv2format, 0);
}
int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
STACK_OF(SSL_CIPHER) **skp,
STACK_OF(SSL_CIPHER) **scsvs_out,
int sslv2format, int fatal)
{
const SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *sk = NULL;
STACK_OF(SSL_CIPHER) *scsvs = NULL;
int n;
/* 3 = SSLV2_CIPHER_LEN > TLS_CIPHER_LEN = 2. */
unsigned char cipher[SSLV2_CIPHER_LEN];
n = sslv2format ? SSLV2_CIPHER_LEN : TLS_CIPHER_LEN;
if (PACKET_remaining(cipher_suites) == 0) {
if (fatal)
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_BYTES_TO_CIPHER_LIST,
SSL_R_NO_CIPHERS_SPECIFIED);
else
SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_NO_CIPHERS_SPECIFIED);
return 0;
}
if (PACKET_remaining(cipher_suites) % n != 0) {
if (fatal)
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
else
SSLerr(SSL_F_BYTES_TO_CIPHER_LIST,
SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST);
return 0;
}
sk = sk_SSL_CIPHER_new_null();
scsvs = sk_SSL_CIPHER_new_null();
if (sk == NULL || scsvs == NULL) {
if (fatal)
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
ERR_R_MALLOC_FAILURE);
else
SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
goto err;
}
while (PACKET_copy_bytes(cipher_suites, cipher, n)) {
/*
* SSLv3 ciphers wrapped in an SSLv2-compatible ClientHello have the
* first byte set to zero, while true SSLv2 ciphers have a non-zero
* first byte. We don't support any true SSLv2 ciphers, so skip them.
*/
if (sslv2format && cipher[0] != '\0')
continue;
/* For SSLv2-compat, ignore leading 0-byte. */
c = ssl_get_cipher_by_char(s, sslv2format ? &cipher[1] : cipher, 1);
if (c != NULL) {
if ((c->valid && !sk_SSL_CIPHER_push(sk, c)) ||
(!c->valid && !sk_SSL_CIPHER_push(scsvs, c))) {
if (fatal)
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
else
SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
goto err;
}
}
}
if (PACKET_remaining(cipher_suites) > 0) {
if (fatal)
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_BYTES_TO_CIPHER_LIST,
SSL_R_BAD_LENGTH);
else
SSLerr(SSL_F_BYTES_TO_CIPHER_LIST, SSL_R_BAD_LENGTH);
goto err;
}
if (skp != NULL)
*skp = sk;
else
sk_SSL_CIPHER_free(sk);
if (scsvs_out != NULL)
*scsvs_out = scsvs;
else
sk_SSL_CIPHER_free(scsvs);
return 1;
err:
sk_SSL_CIPHER_free(sk);
sk_SSL_CIPHER_free(scsvs);
return 0;
}
int SSL_CTX_set_max_early_data(SSL_CTX *ctx, uint32_t max_early_data)
{
ctx->max_early_data = max_early_data;
return 1;
}
uint32_t SSL_CTX_get_max_early_data(const SSL_CTX *ctx)
{
return ctx->max_early_data;
}
int SSL_set_max_early_data(SSL *s, uint32_t max_early_data)
{
s->max_early_data = max_early_data;
return 1;
}
uint32_t SSL_get_max_early_data(const SSL *s)
{
return s->max_early_data;
}
int SSL_CTX_set_recv_max_early_data(SSL_CTX *ctx, uint32_t recv_max_early_data)
{
ctx->recv_max_early_data = recv_max_early_data;
return 1;
}
uint32_t SSL_CTX_get_recv_max_early_data(const SSL_CTX *ctx)
{
return ctx->recv_max_early_data;
}
int SSL_set_recv_max_early_data(SSL *s, uint32_t recv_max_early_data)
{
s->recv_max_early_data = recv_max_early_data;
return 1;
}
uint32_t SSL_get_recv_max_early_data(const SSL *s)
{
return s->recv_max_early_data;
}
__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl)
{
/* Return any active Max Fragment Len extension */
if (ssl->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session))
return GET_MAX_FRAGMENT_LENGTH(ssl->session);
/* return current SSL connection setting */
return ssl->max_send_fragment;
}
__owur unsigned int ssl_get_split_send_fragment(const SSL *ssl)
{
/* Return a value regarding an active Max Fragment Len extension */
if (ssl->session != NULL && USE_MAX_FRAGMENT_LENGTH_EXT(ssl->session)
&& ssl->split_send_fragment > GET_MAX_FRAGMENT_LENGTH(ssl->session))
return GET_MAX_FRAGMENT_LENGTH(ssl->session);
/* else limit |split_send_fragment| to current |max_send_fragment| */
if (ssl->split_send_fragment > ssl->max_send_fragment)
return ssl->max_send_fragment;
/* return current SSL connection setting */
return ssl->split_send_fragment;
}
int SSL_stateless(SSL *s)
{
int ret;
/* Ensure there is no state left over from a previous invocation */
if (!SSL_clear(s))
return 0;
ERR_clear_error();
s->s3->flags |= TLS1_FLAGS_STATELESS;
ret = SSL_accept(s);
s->s3->flags &= ~TLS1_FLAGS_STATELESS;
if (ret > 0 && s->ext.cookieok)
return 1;
if (s->hello_retry_request == SSL_HRR_PENDING && !ossl_statem_in_error(s))
return 0;
return -1;
}
void SSL_CTX_set_post_handshake_auth(SSL_CTX *ctx, int val)
{
ctx->pha_enabled = val;
}
void SSL_set_post_handshake_auth(SSL *ssl, int val)
{
ssl->pha_enabled = val;
}
int SSL_verify_client_post_handshake(SSL *ssl)
{
if (!SSL_IS_TLS13(ssl)) {
SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_WRONG_SSL_VERSION);
return 0;
}
if (!ssl->server) {
SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_NOT_SERVER);
return 0;
}
if (!SSL_is_init_finished(ssl)) {
SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_STILL_IN_INIT);
return 0;
}
switch (ssl->post_handshake_auth) {
case SSL_PHA_NONE:
SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_EXTENSION_NOT_RECEIVED);
return 0;
default:
case SSL_PHA_EXT_SENT:
SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, ERR_R_INTERNAL_ERROR);
return 0;
case SSL_PHA_EXT_RECEIVED:
break;
case SSL_PHA_REQUEST_PENDING:
SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_REQUEST_PENDING);
return 0;
case SSL_PHA_REQUESTED:
SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_REQUEST_SENT);
return 0;
}
ssl->post_handshake_auth = SSL_PHA_REQUEST_PENDING;
/* checks verify_mode and algorithm_auth */
if (!send_certificate_request(ssl)) {
ssl->post_handshake_auth = SSL_PHA_EXT_RECEIVED; /* restore on error */
SSLerr(SSL_F_SSL_VERIFY_CLIENT_POST_HANDSHAKE, SSL_R_INVALID_CONFIG);
return 0;
}
ossl_statem_set_in_init(ssl, 1);
return 1;
}
int SSL_CTX_set_session_ticket_cb(SSL_CTX *ctx,
SSL_CTX_generate_session_ticket_fn gen_cb,
SSL_CTX_decrypt_session_ticket_fn dec_cb,
void *arg)
{
ctx->generate_ticket_cb = gen_cb;
ctx->decrypt_ticket_cb = dec_cb;
ctx->ticket_cb_data = arg;
return 1;
}
void SSL_CTX_set_allow_early_data_cb(SSL_CTX *ctx,
SSL_allow_early_data_cb_fn cb,
void *arg)
{
ctx->allow_early_data_cb = cb;
ctx->allow_early_data_cb_data = arg;
}
void SSL_set_allow_early_data_cb(SSL *s,
SSL_allow_early_data_cb_fn cb,
void *arg)
{
s->allow_early_data_cb = cb;
s->allow_early_data_cb_data = arg;
}
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index f326399e03a0..0cf3893e0648 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -1,2666 +1,2669 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#ifndef HEADER_SSL_LOCL_H
# define HEADER_SSL_LOCL_H
# include "e_os.h" /* struct timeval for DTLS */
# include <stdlib.h>
# include <time.h>
# include <string.h>
# include <errno.h>
# include <openssl/buffer.h>
# include <openssl/comp.h>
# include <openssl/bio.h>
# include <openssl/rsa.h>
# include <openssl/dsa.h>
# include <openssl/err.h>
# include <openssl/ssl.h>
# include <openssl/async.h>
# include <openssl/symhacks.h>
# include <openssl/ct.h>
# include "record/record.h"
# include "statem/statem.h"
# include "packet_locl.h"
# include "internal/dane.h"
# include "internal/refcount.h"
# include "internal/tsan_assist.h"
# ifdef OPENSSL_BUILD_SHLIBSSL
# undef OPENSSL_EXTERN
# define OPENSSL_EXTERN OPENSSL_EXPORT
# endif
# define c2l(c,l) (l = ((unsigned long)(*((c)++))) , \
l|=(((unsigned long)(*((c)++)))<< 8), \
l|=(((unsigned long)(*((c)++)))<<16), \
l|=(((unsigned long)(*((c)++)))<<24))
/* NOTE - c is not incremented as per c2l */
# define c2ln(c,l1,l2,n) { \
c+=n; \
l1=l2=0; \
switch (n) { \
case 8: l2 =((unsigned long)(*(--(c))))<<24; \
case 7: l2|=((unsigned long)(*(--(c))))<<16; \
case 6: l2|=((unsigned long)(*(--(c))))<< 8; \
case 5: l2|=((unsigned long)(*(--(c)))); \
case 4: l1 =((unsigned long)(*(--(c))))<<24; \
case 3: l1|=((unsigned long)(*(--(c))))<<16; \
case 2: l1|=((unsigned long)(*(--(c))))<< 8; \
case 1: l1|=((unsigned long)(*(--(c)))); \
} \
}
# define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff))
# define n2l(c,l) (l =((unsigned long)(*((c)++)))<<24, \
l|=((unsigned long)(*((c)++)))<<16, \
l|=((unsigned long)(*((c)++)))<< 8, \
l|=((unsigned long)(*((c)++))))
# define n2l8(c,l) (l =((uint64_t)(*((c)++)))<<56, \
l|=((uint64_t)(*((c)++)))<<48, \
l|=((uint64_t)(*((c)++)))<<40, \
l|=((uint64_t)(*((c)++)))<<32, \
l|=((uint64_t)(*((c)++)))<<24, \
l|=((uint64_t)(*((c)++)))<<16, \
l|=((uint64_t)(*((c)++)))<< 8, \
l|=((uint64_t)(*((c)++))))
# define l2n(l,c) (*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff))
# define l2n6(l,c) (*((c)++)=(unsigned char)(((l)>>40)&0xff), \
*((c)++)=(unsigned char)(((l)>>32)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff))
# define l2n8(l,c) (*((c)++)=(unsigned char)(((l)>>56)&0xff), \
*((c)++)=(unsigned char)(((l)>>48)&0xff), \
*((c)++)=(unsigned char)(((l)>>40)&0xff), \
*((c)++)=(unsigned char)(((l)>>32)&0xff), \
*((c)++)=(unsigned char)(((l)>>24)&0xff), \
*((c)++)=(unsigned char)(((l)>>16)&0xff), \
*((c)++)=(unsigned char)(((l)>> 8)&0xff), \
*((c)++)=(unsigned char)(((l) )&0xff))
/* NOTE - c is not incremented as per l2c */
# define l2cn(l1,l2,c,n) { \
c+=n; \
switch (n) { \
case 8: *(--(c))=(unsigned char)(((l2)>>24)&0xff); \
case 7: *(--(c))=(unsigned char)(((l2)>>16)&0xff); \
case 6: *(--(c))=(unsigned char)(((l2)>> 8)&0xff); \
case 5: *(--(c))=(unsigned char)(((l2) )&0xff); \
case 4: *(--(c))=(unsigned char)(((l1)>>24)&0xff); \
case 3: *(--(c))=(unsigned char)(((l1)>>16)&0xff); \
case 2: *(--(c))=(unsigned char)(((l1)>> 8)&0xff); \
case 1: *(--(c))=(unsigned char)(((l1) )&0xff); \
} \
}
# define n2s(c,s) ((s=(((unsigned int)((c)[0]))<< 8)| \
(((unsigned int)((c)[1])) )),(c)+=2)
# define s2n(s,c) (((c)[0]=(unsigned char)(((s)>> 8)&0xff), \
(c)[1]=(unsigned char)(((s) )&0xff)),(c)+=2)
# define n2l3(c,l) ((l =(((unsigned long)((c)[0]))<<16)| \
(((unsigned long)((c)[1]))<< 8)| \
(((unsigned long)((c)[2])) )),(c)+=3)
# define l2n3(l,c) (((c)[0]=(unsigned char)(((l)>>16)&0xff), \
(c)[1]=(unsigned char)(((l)>> 8)&0xff), \
(c)[2]=(unsigned char)(((l) )&0xff)),(c)+=3)
/*
* DTLS version numbers are strange because they're inverted. Except for
* DTLS1_BAD_VER, which should be considered "lower" than the rest.
*/
# define dtls_ver_ordinal(v1) (((v1) == DTLS1_BAD_VER) ? 0xff00 : (v1))
# define DTLS_VERSION_GT(v1, v2) (dtls_ver_ordinal(v1) < dtls_ver_ordinal(v2))
# define DTLS_VERSION_GE(v1, v2) (dtls_ver_ordinal(v1) <= dtls_ver_ordinal(v2))
# define DTLS_VERSION_LT(v1, v2) (dtls_ver_ordinal(v1) > dtls_ver_ordinal(v2))
# define DTLS_VERSION_LE(v1, v2) (dtls_ver_ordinal(v1) >= dtls_ver_ordinal(v2))
/*
* Define the Bitmasks for SSL_CIPHER.algorithms.
* This bits are used packed as dense as possible. If new methods/ciphers
* etc will be added, the bits a likely to change, so this information
* is for internal library use only, even though SSL_CIPHER.algorithms
* can be publicly accessed.
* Use the according functions for cipher management instead.
*
* The bit mask handling in the selection and sorting scheme in
* ssl_create_cipher_list() has only limited capabilities, reflecting
* that the different entities within are mutually exclusive:
* ONLY ONE BIT PER MASK CAN BE SET AT A TIME.
*/
/* Bits for algorithm_mkey (key exchange algorithm) */
/* RSA key exchange */
# define SSL_kRSA 0x00000001U
/* tmp DH key no DH cert */
# define SSL_kDHE 0x00000002U
/* synonym */
# define SSL_kEDH SSL_kDHE
/* ephemeral ECDH */
# define SSL_kECDHE 0x00000004U
/* synonym */
# define SSL_kEECDH SSL_kECDHE
/* PSK */
# define SSL_kPSK 0x00000008U
/* GOST key exchange */
# define SSL_kGOST 0x00000010U
/* SRP */
# define SSL_kSRP 0x00000020U
# define SSL_kRSAPSK 0x00000040U
# define SSL_kECDHEPSK 0x00000080U
# define SSL_kDHEPSK 0x00000100U
/* all PSK */
# define SSL_PSK (SSL_kPSK | SSL_kRSAPSK | SSL_kECDHEPSK | SSL_kDHEPSK)
/* Any appropriate key exchange algorithm (for TLS 1.3 ciphersuites) */
# define SSL_kANY 0x00000000U
/* Bits for algorithm_auth (server authentication) */
/* RSA auth */
# define SSL_aRSA 0x00000001U
/* DSS auth */
# define SSL_aDSS 0x00000002U
/* no auth (i.e. use ADH or AECDH) */
# define SSL_aNULL 0x00000004U
/* ECDSA auth*/
# define SSL_aECDSA 0x00000008U
/* PSK auth */
# define SSL_aPSK 0x00000010U
/* GOST R 34.10-2001 signature auth */
# define SSL_aGOST01 0x00000020U
/* SRP auth */
# define SSL_aSRP 0x00000040U
/* GOST R 34.10-2012 signature auth */
# define SSL_aGOST12 0x00000080U
/* Any appropriate signature auth (for TLS 1.3 ciphersuites) */
# define SSL_aANY 0x00000000U
/* All bits requiring a certificate */
#define SSL_aCERT \
(SSL_aRSA | SSL_aDSS | SSL_aECDSA | SSL_aGOST01 | SSL_aGOST12)
/* Bits for algorithm_enc (symmetric encryption) */
# define SSL_DES 0x00000001U
# define SSL_3DES 0x00000002U
# define SSL_RC4 0x00000004U
# define SSL_RC2 0x00000008U
# define SSL_IDEA 0x00000010U
# define SSL_eNULL 0x00000020U
# define SSL_AES128 0x00000040U
# define SSL_AES256 0x00000080U
# define SSL_CAMELLIA128 0x00000100U
# define SSL_CAMELLIA256 0x00000200U
# define SSL_eGOST2814789CNT 0x00000400U
# define SSL_SEED 0x00000800U
# define SSL_AES128GCM 0x00001000U
# define SSL_AES256GCM 0x00002000U
# define SSL_AES128CCM 0x00004000U
# define SSL_AES256CCM 0x00008000U
# define SSL_AES128CCM8 0x00010000U
# define SSL_AES256CCM8 0x00020000U
# define SSL_eGOST2814789CNT12 0x00040000U
# define SSL_CHACHA20POLY1305 0x00080000U
# define SSL_ARIA128GCM 0x00100000U
# define SSL_ARIA256GCM 0x00200000U
# define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM)
# define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8)
# define SSL_AES (SSL_AES128|SSL_AES256|SSL_AESGCM|SSL_AESCCM)
# define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256)
# define SSL_CHACHA20 (SSL_CHACHA20POLY1305)
# define SSL_ARIAGCM (SSL_ARIA128GCM | SSL_ARIA256GCM)
# define SSL_ARIA (SSL_ARIAGCM)
/* Bits for algorithm_mac (symmetric authentication) */
# define SSL_MD5 0x00000001U
# define SSL_SHA1 0x00000002U
# define SSL_GOST94 0x00000004U
# define SSL_GOST89MAC 0x00000008U
# define SSL_SHA256 0x00000010U
# define SSL_SHA384 0x00000020U
/* Not a real MAC, just an indication it is part of cipher */
# define SSL_AEAD 0x00000040U
# define SSL_GOST12_256 0x00000080U
# define SSL_GOST89MAC12 0x00000100U
# define SSL_GOST12_512 0x00000200U
/*
* When adding new digest in the ssl_ciph.c and increment SSL_MD_NUM_IDX make
* sure to update this constant too
*/
# define SSL_MD_MD5_IDX 0
# define SSL_MD_SHA1_IDX 1
# define SSL_MD_GOST94_IDX 2
# define SSL_MD_GOST89MAC_IDX 3
# define SSL_MD_SHA256_IDX 4
# define SSL_MD_SHA384_IDX 5
# define SSL_MD_GOST12_256_IDX 6
# define SSL_MD_GOST89MAC12_IDX 7
# define SSL_MD_GOST12_512_IDX 8
# define SSL_MD_MD5_SHA1_IDX 9
# define SSL_MD_SHA224_IDX 10
# define SSL_MD_SHA512_IDX 11
# define SSL_MAX_DIGEST 12
/* Bits for algorithm2 (handshake digests and other extra flags) */
/* Bits 0-7 are handshake MAC */
# define SSL_HANDSHAKE_MAC_MASK 0xFF
# define SSL_HANDSHAKE_MAC_MD5_SHA1 SSL_MD_MD5_SHA1_IDX
# define SSL_HANDSHAKE_MAC_SHA256 SSL_MD_SHA256_IDX
# define SSL_HANDSHAKE_MAC_SHA384 SSL_MD_SHA384_IDX
# define SSL_HANDSHAKE_MAC_GOST94 SSL_MD_GOST94_IDX
# define SSL_HANDSHAKE_MAC_GOST12_256 SSL_MD_GOST12_256_IDX
# define SSL_HANDSHAKE_MAC_GOST12_512 SSL_MD_GOST12_512_IDX
# define SSL_HANDSHAKE_MAC_DEFAULT SSL_HANDSHAKE_MAC_MD5_SHA1
/* Bits 8-15 bits are PRF */
# define TLS1_PRF_DGST_SHIFT 8
# define TLS1_PRF_SHA1_MD5 (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF_SHA256 (SSL_MD_SHA256_IDX << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF_SHA384 (SSL_MD_SHA384_IDX << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF_GOST94 (SSL_MD_GOST94_IDX << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF_GOST12_256 (SSL_MD_GOST12_256_IDX << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF_GOST12_512 (SSL_MD_GOST12_512_IDX << TLS1_PRF_DGST_SHIFT)
# define TLS1_PRF (SSL_MD_MD5_SHA1_IDX << TLS1_PRF_DGST_SHIFT)
/*
* Stream MAC for GOST ciphersuites from cryptopro draft (currently this also
* goes into algorithm2)
*/
# define TLS1_STREAM_MAC 0x10000
# define SSL_STRONG_MASK 0x0000001FU
# define SSL_DEFAULT_MASK 0X00000020U
# define SSL_STRONG_NONE 0x00000001U
# define SSL_LOW 0x00000002U
# define SSL_MEDIUM 0x00000004U
# define SSL_HIGH 0x00000008U
# define SSL_FIPS 0x00000010U
# define SSL_NOT_DEFAULT 0x00000020U
/* we have used 0000003f - 26 bits left to go */
/* Flag used on OpenSSL ciphersuite ids to indicate they are for SSLv3+ */
# define SSL3_CK_CIPHERSUITE_FLAG 0x03000000
/* Check if an SSL structure is using DTLS */
# define SSL_IS_DTLS(s) (s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_DTLS)
/* Check if we are using TLSv1.3 */
# define SSL_IS_TLS13(s) (!SSL_IS_DTLS(s) \
&& (s)->method->version >= TLS1_3_VERSION \
&& (s)->method->version != TLS_ANY_VERSION)
# define SSL_TREAT_AS_TLS13(s) \
(SSL_IS_TLS13(s) || (s)->early_data_state == SSL_EARLY_DATA_CONNECTING \
|| (s)->early_data_state == SSL_EARLY_DATA_CONNECT_RETRY \
|| (s)->early_data_state == SSL_EARLY_DATA_WRITING \
|| (s)->early_data_state == SSL_EARLY_DATA_WRITE_RETRY \
|| (s)->hello_retry_request == SSL_HRR_PENDING)
# define SSL_IS_FIRST_HANDSHAKE(S) ((s)->s3->tmp.finish_md_len == 0 \
|| (s)->s3->tmp.peer_finish_md_len == 0)
/* See if we need explicit IV */
# define SSL_USE_EXPLICIT_IV(s) \
(s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_EXPLICIT_IV)
/*
* See if we use signature algorithms extension and signature algorithm
* before signatures.
*/
# define SSL_USE_SIGALGS(s) \
(s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_SIGALGS)
/*
* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may
* apply to others in future.
*/
# define SSL_USE_TLS1_2_CIPHERS(s) \
(s->method->ssl3_enc->enc_flags & SSL_ENC_FLAG_TLS1_2_CIPHERS)
/*
* Determine if a client can use TLS 1.2 ciphersuites: can't rely on method
* flags because it may not be set to correct version yet.
*/
# define SSL_CLIENT_USE_TLS1_2_CIPHERS(s) \
((!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION) || \
(SSL_IS_DTLS(s) && DTLS_VERSION_GE(s->client_version, DTLS1_2_VERSION)))
/*
* Determine if a client should send signature algorithms extension:
* as with TLS1.2 cipher we can't rely on method flags.
*/
# define SSL_CLIENT_USE_SIGALGS(s) \
SSL_CLIENT_USE_TLS1_2_CIPHERS(s)
# define IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value) \
(((value) >= TLSEXT_max_fragment_length_512) && \
((value) <= TLSEXT_max_fragment_length_4096))
# define USE_MAX_FRAGMENT_LENGTH_EXT(session) \
IS_MAX_FRAGMENT_LENGTH_EXT_VALID(session->ext.max_fragment_len_mode)
# define GET_MAX_FRAGMENT_LENGTH(session) \
(512U << (session->ext.max_fragment_len_mode - 1))
# define SSL_READ_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_READ)
# define SSL_WRITE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC_WRITE)
/* Mostly for SSLv3 */
# define SSL_PKEY_RSA 0
# define SSL_PKEY_RSA_PSS_SIGN 1
# define SSL_PKEY_DSA_SIGN 2
# define SSL_PKEY_ECC 3
# define SSL_PKEY_GOST01 4
# define SSL_PKEY_GOST12_256 5
# define SSL_PKEY_GOST12_512 6
# define SSL_PKEY_ED25519 7
# define SSL_PKEY_ED448 8
# define SSL_PKEY_NUM 9
/*-
* SSL_kRSA <- RSA_ENC
* SSL_kDH <- DH_ENC & (RSA_ENC | RSA_SIGN | DSA_SIGN)
* SSL_kDHE <- RSA_ENC | RSA_SIGN | DSA_SIGN
* SSL_aRSA <- RSA_ENC | RSA_SIGN
* SSL_aDSS <- DSA_SIGN
*/
/*-
#define CERT_INVALID 0
#define CERT_PUBLIC_KEY 1
#define CERT_PRIVATE_KEY 2
*/
/* Post-Handshake Authentication state */
typedef enum {
SSL_PHA_NONE = 0,
SSL_PHA_EXT_SENT, /* client-side only: extension sent */
SSL_PHA_EXT_RECEIVED, /* server-side only: extension received */
SSL_PHA_REQUEST_PENDING, /* server-side only: request pending */
SSL_PHA_REQUESTED /* request received by client, or sent by server */
} SSL_PHA_STATE;
/* CipherSuite length. SSLv3 and all TLS versions. */
# define TLS_CIPHER_LEN 2
/* used to hold info on the particular ciphers used */
struct ssl_cipher_st {
uint32_t valid;
const char *name; /* text name */
const char *stdname; /* RFC name */
uint32_t id; /* id, 4 bytes, first is version */
/*
* changed in 1.0.0: these four used to be portions of a single value
* 'algorithms'
*/
uint32_t algorithm_mkey; /* key exchange algorithm */
uint32_t algorithm_auth; /* server authentication */
uint32_t algorithm_enc; /* symmetric encryption */
uint32_t algorithm_mac; /* symmetric authentication */
int min_tls; /* minimum SSL/TLS protocol version */
int max_tls; /* maximum SSL/TLS protocol version */
int min_dtls; /* minimum DTLS protocol version */
int max_dtls; /* maximum DTLS protocol version */
uint32_t algo_strength; /* strength and export flags */
uint32_t algorithm2; /* Extra flags */
int32_t strength_bits; /* Number of bits really used */
uint32_t alg_bits; /* Number of bits for algorithm */
};
/* Used to hold SSL/TLS functions */
struct ssl_method_st {
int version;
unsigned flags;
unsigned long mask;
int (*ssl_new) (SSL *s);
int (*ssl_clear) (SSL *s);
void (*ssl_free) (SSL *s);
int (*ssl_accept) (SSL *s);
int (*ssl_connect) (SSL *s);
int (*ssl_read) (SSL *s, void *buf, size_t len, size_t *readbytes);
int (*ssl_peek) (SSL *s, void *buf, size_t len, size_t *readbytes);
int (*ssl_write) (SSL *s, const void *buf, size_t len, size_t *written);
int (*ssl_shutdown) (SSL *s);
int (*ssl_renegotiate) (SSL *s);
int (*ssl_renegotiate_check) (SSL *s, int);
int (*ssl_read_bytes) (SSL *s, int type, int *recvd_type,
unsigned char *buf, size_t len, int peek,
size_t *readbytes);
int (*ssl_write_bytes) (SSL *s, int type, const void *buf_, size_t len,
size_t *written);
int (*ssl_dispatch_alert) (SSL *s);
long (*ssl_ctrl) (SSL *s, int cmd, long larg, void *parg);
long (*ssl_ctx_ctrl) (SSL_CTX *ctx, int cmd, long larg, void *parg);
const SSL_CIPHER *(*get_cipher_by_char) (const unsigned char *ptr);
int (*put_cipher_by_char) (const SSL_CIPHER *cipher, WPACKET *pkt,
size_t *len);
size_t (*ssl_pending) (const SSL *s);
int (*num_ciphers) (void);
const SSL_CIPHER *(*get_cipher) (unsigned ncipher);
long (*get_timeout) (void);
const struct ssl3_enc_method *ssl3_enc; /* Extra SSLv3/TLS stuff */
int (*ssl_version) (void);
long (*ssl_callback_ctrl) (SSL *s, int cb_id, void (*fp) (void));
long (*ssl_ctx_callback_ctrl) (SSL_CTX *s, int cb_id, void (*fp) (void));
};
/*
* Matches the length of PSK_MAX_PSK_LEN. We keep it the same value for
* consistency, even in the event of OPENSSL_NO_PSK being defined.
*/
# define TLS13_MAX_RESUMPTION_PSK_LENGTH 256
/*-
* Lets make this into an ASN.1 type structure as follows
* SSL_SESSION_ID ::= SEQUENCE {
* version INTEGER, -- structure version number
* SSLversion INTEGER, -- SSL version number
* Cipher OCTET STRING, -- the 3 byte cipher ID
* Session_ID OCTET STRING, -- the Session ID
* Master_key OCTET STRING, -- the master key
* Key_Arg [ 0 ] IMPLICIT OCTET STRING, -- the optional Key argument
* Time [ 1 ] EXPLICIT INTEGER, -- optional Start Time
* Timeout [ 2 ] EXPLICIT INTEGER, -- optional Timeout ins seconds
* Peer [ 3 ] EXPLICIT X509, -- optional Peer Certificate
* Session_ID_context [ 4 ] EXPLICIT OCTET STRING, -- the Session ID context
* Verify_result [ 5 ] EXPLICIT INTEGER, -- X509_V_... code for `Peer'
* HostName [ 6 ] EXPLICIT OCTET STRING, -- optional HostName from servername TLS extension
* PSK_identity_hint [ 7 ] EXPLICIT OCTET STRING, -- optional PSK identity hint
* PSK_identity [ 8 ] EXPLICIT OCTET STRING, -- optional PSK identity
* Ticket_lifetime_hint [9] EXPLICIT INTEGER, -- server's lifetime hint for session ticket
* Ticket [10] EXPLICIT OCTET STRING, -- session ticket (clients only)
* Compression_meth [11] EXPLICIT OCTET STRING, -- optional compression method
* SRP_username [ 12 ] EXPLICIT OCTET STRING -- optional SRP username
* flags [ 13 ] EXPLICIT INTEGER -- optional flags
* }
* Look in ssl/ssl_asn1.c for more details
* I'm using EXPLICIT tags so I can read the damn things using asn1parse :-).
*/
struct ssl_session_st {
int ssl_version; /* what ssl version session info is being kept
* in here? */
size_t master_key_length;
/* TLSv1.3 early_secret used for external PSKs */
unsigned char early_secret[EVP_MAX_MD_SIZE];
/*
* For <=TLS1.2 this is the master_key. For TLS1.3 this is the resumption
* PSK
*/
unsigned char master_key[TLS13_MAX_RESUMPTION_PSK_LENGTH];
/* session_id - valid? */
size_t session_id_length;
unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
/*
* this is used to determine whether the session is being reused in the
* appropriate context. It is up to the application to set this, via
* SSL_new
*/
size_t sid_ctx_length;
unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
# ifndef OPENSSL_NO_PSK
char *psk_identity_hint;
char *psk_identity;
# endif
/*
* Used to indicate that session resumption is not allowed. Applications
* can also set this bit for a new session via not_resumable_session_cb
* to disable session caching and tickets.
*/
int not_resumable;
/* This is the cert and type for the other end. */
X509 *peer;
int peer_type;
/* Certificate chain peer sent. */
STACK_OF(X509) *peer_chain;
/*
* when app_verify_callback accepts a session where the peer's
* certificate is not ok, we must remember the error for session reuse:
*/
long verify_result; /* only for servers */
CRYPTO_REF_COUNT references;
long timeout;
long time;
unsigned int compress_meth; /* Need to lookup the method */
const SSL_CIPHER *cipher;
unsigned long cipher_id; /* when ASN.1 loaded, this needs to be used to
* load the 'cipher' structure */
STACK_OF(SSL_CIPHER) *ciphers; /* ciphers offered by the client */
CRYPTO_EX_DATA ex_data; /* application specific data */
/*
* These are used to make removal of session-ids more efficient and to
* implement a maximum cache size.
*/
struct ssl_session_st *prev, *next;
struct {
char *hostname;
# ifndef OPENSSL_NO_EC
size_t ecpointformats_len;
unsigned char *ecpointformats; /* peer's list */
# endif /* OPENSSL_NO_EC */
size_t supportedgroups_len;
uint16_t *supportedgroups; /* peer's list */
/* RFC4507 info */
unsigned char *tick; /* Session ticket */
size_t ticklen; /* Session ticket length */
/* Session lifetime hint in seconds */
unsigned long tick_lifetime_hint;
uint32_t tick_age_add;
- int tick_identity;
/* Max number of bytes that can be sent as early data */
uint32_t max_early_data;
/* The ALPN protocol selected for this session */
unsigned char *alpn_selected;
size_t alpn_selected_len;
/*
* Maximum Fragment Length as per RFC 4366.
* If this value does not contain RFC 4366 allowed values (1-4) then
* either the Maximum Fragment Length Negotiation failed or was not
* performed at all.
*/
uint8_t max_fragment_len_mode;
} ext;
# ifndef OPENSSL_NO_SRP
char *srp_username;
# endif
unsigned char *ticket_appdata;
size_t ticket_appdata_len;
uint32_t flags;
CRYPTO_RWLOCK *lock;
};
/* Extended master secret support */
# define SSL_SESS_FLAG_EXTMS 0x1
# ifndef OPENSSL_NO_SRP
typedef struct srp_ctx_st {
/* param for all the callbacks */
void *SRP_cb_arg;
/* set client Hello login callback */
int (*TLS_ext_srp_username_callback) (SSL *, int *, void *);
/* set SRP N/g param callback for verification */
int (*SRP_verify_param_callback) (SSL *, void *);
/* set SRP client passwd callback */
char *(*SRP_give_srp_client_pwd_callback) (SSL *, void *);
char *login;
BIGNUM *N, *g, *s, *B, *A;
BIGNUM *a, *b, *v;
char *info;
int strength;
unsigned long srp_Mask;
} SRP_CTX;
# endif
typedef enum {
SSL_EARLY_DATA_NONE = 0,
SSL_EARLY_DATA_CONNECT_RETRY,
SSL_EARLY_DATA_CONNECTING,
SSL_EARLY_DATA_WRITE_RETRY,
SSL_EARLY_DATA_WRITING,
SSL_EARLY_DATA_WRITE_FLUSH,
SSL_EARLY_DATA_UNAUTH_WRITING,
SSL_EARLY_DATA_FINISHED_WRITING,
SSL_EARLY_DATA_ACCEPT_RETRY,
SSL_EARLY_DATA_ACCEPTING,
SSL_EARLY_DATA_READ_RETRY,
SSL_EARLY_DATA_READING,
SSL_EARLY_DATA_FINISHED_READING
} SSL_EARLY_DATA_STATE;
/*
* We check that the amount of unreadable early data doesn't exceed
* max_early_data. max_early_data is given in plaintext bytes. However if it is
* unreadable then we only know the number of ciphertext bytes. We also don't
* know how much the overhead should be because it depends on the ciphersuite.
* We make a small allowance. We assume 5 records of actual data plus the end
* of early data alert record. Each record has a tag and a content type byte.
* The longest tag length we know of is EVP_GCM_TLS_TAG_LEN. We don't count the
* content of the alert record either which is 2 bytes.
*/
# define EARLY_DATA_CIPHERTEXT_OVERHEAD ((6 * (EVP_GCM_TLS_TAG_LEN + 1)) + 2)
/*
* The allowance we have between the client's calculated ticket age and our own.
* We allow for 10 seconds (units are in ms). If a ticket is presented and the
* client's age calculation is different by more than this than our own then we
* do not allow that ticket for early_data.
*/
# define TICKET_AGE_ALLOWANCE (10 * 1000)
#define MAX_COMPRESSIONS_SIZE 255
struct ssl_comp_st {
int id;
const char *name;
COMP_METHOD *method;
};
typedef struct raw_extension_st {
/* Raw packet data for the extension */
PACKET data;
/* Set to 1 if the extension is present or 0 otherwise */
int present;
/* Set to 1 if we have already parsed the extension or 0 otherwise */
int parsed;
/* The type of this extension, i.e. a TLSEXT_TYPE_* value */
unsigned int type;
/* Track what order extensions are received in (0-based). */
size_t received_order;
} RAW_EXTENSION;
typedef struct {
unsigned int isv2;
unsigned int legacy_version;
unsigned char random[SSL3_RANDOM_SIZE];
size_t session_id_len;
unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
size_t dtls_cookie_len;
unsigned char dtls_cookie[DTLS1_COOKIE_LENGTH];
PACKET ciphersuites;
size_t compressions_len;
unsigned char compressions[MAX_COMPRESSIONS_SIZE];
PACKET extensions;
size_t pre_proc_exts_len;
RAW_EXTENSION *pre_proc_exts;
} CLIENTHELLO_MSG;
/*
* Extension index values NOTE: Any updates to these defines should be mirrored
* with equivalent updates to ext_defs in extensions.c
*/
typedef enum tlsext_index_en {
TLSEXT_IDX_renegotiate,
TLSEXT_IDX_server_name,
TLSEXT_IDX_max_fragment_length,
TLSEXT_IDX_srp,
TLSEXT_IDX_ec_point_formats,
TLSEXT_IDX_supported_groups,
TLSEXT_IDX_session_ticket,
TLSEXT_IDX_status_request,
TLSEXT_IDX_next_proto_neg,
TLSEXT_IDX_application_layer_protocol_negotiation,
TLSEXT_IDX_use_srtp,
TLSEXT_IDX_encrypt_then_mac,
TLSEXT_IDX_signed_certificate_timestamp,
TLSEXT_IDX_extended_master_secret,
TLSEXT_IDX_signature_algorithms_cert,
TLSEXT_IDX_post_handshake_auth,
TLSEXT_IDX_signature_algorithms,
TLSEXT_IDX_supported_versions,
TLSEXT_IDX_psk_kex_modes,
TLSEXT_IDX_key_share,
TLSEXT_IDX_cookie,
TLSEXT_IDX_cryptopro_bug,
TLSEXT_IDX_early_data,
TLSEXT_IDX_certificate_authorities,
TLSEXT_IDX_padding,
TLSEXT_IDX_psk,
/* Dummy index - must always be the last entry */
TLSEXT_IDX_num_builtins
} TLSEXT_INDEX;
DEFINE_LHASH_OF(SSL_SESSION);
/* Needed in ssl_cert.c */
DEFINE_LHASH_OF(X509_NAME);
# define TLSEXT_KEYNAME_LENGTH 16
# define TLSEXT_TICK_KEY_LENGTH 32
typedef struct ssl_ctx_ext_secure_st {
unsigned char tick_hmac_key[TLSEXT_TICK_KEY_LENGTH];
unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH];
} SSL_CTX_EXT_SECURE;
struct ssl_ctx_st {
const SSL_METHOD *method;
STACK_OF(SSL_CIPHER) *cipher_list;
/* same as above but sorted for lookup */
STACK_OF(SSL_CIPHER) *cipher_list_by_id;
/* TLSv1.3 specific ciphersuites */
STACK_OF(SSL_CIPHER) *tls13_ciphersuites;
struct x509_store_st /* X509_STORE */ *cert_store;
LHASH_OF(SSL_SESSION) *sessions;
/*
* Most session-ids that will be cached, default is
* SSL_SESSION_CACHE_MAX_SIZE_DEFAULT. 0 is unlimited.
*/
size_t session_cache_size;
struct ssl_session_st *session_cache_head;
struct ssl_session_st *session_cache_tail;
/*
* This can have one of 2 values, ored together, SSL_SESS_CACHE_CLIENT,
* SSL_SESS_CACHE_SERVER, Default is SSL_SESSION_CACHE_SERVER, which
* means only SSL_accept will cache SSL_SESSIONS.
*/
uint32_t session_cache_mode;
/*
* If timeout is not 0, it is the default timeout value set when
* SSL_new() is called. This has been put in to make life easier to set
* things up
*/
long session_timeout;
/*
* If this callback is not null, it will be called each time a session id
* is added to the cache. If this function returns 1, it means that the
* callback will do a SSL_SESSION_free() when it has finished using it.
* Otherwise, on 0, it means the callback has finished with it. If
* remove_session_cb is not null, it will be called when a session-id is
* removed from the cache. After the call, OpenSSL will
* SSL_SESSION_free() it.
*/
int (*new_session_cb) (struct ssl_st *ssl, SSL_SESSION *sess);
void (*remove_session_cb) (struct ssl_ctx_st *ctx, SSL_SESSION *sess);
SSL_SESSION *(*get_session_cb) (struct ssl_st *ssl,
const unsigned char *data, int len,
int *copy);
struct {
TSAN_QUALIFIER int sess_connect; /* SSL new conn - started */
TSAN_QUALIFIER int sess_connect_renegotiate; /* SSL reneg - requested */
TSAN_QUALIFIER int sess_connect_good; /* SSL new conne/reneg - finished */
TSAN_QUALIFIER int sess_accept; /* SSL new accept - started */
TSAN_QUALIFIER int sess_accept_renegotiate; /* SSL reneg - requested */
TSAN_QUALIFIER int sess_accept_good; /* SSL accept/reneg - finished */
TSAN_QUALIFIER int sess_miss; /* session lookup misses */
TSAN_QUALIFIER int sess_timeout; /* reuse attempt on timeouted session */
TSAN_QUALIFIER int sess_cache_full; /* session removed due to full cache */
TSAN_QUALIFIER int sess_hit; /* session reuse actually done */
TSAN_QUALIFIER int sess_cb_hit; /* session-id that was not in
* the cache was passed back via
* the callback. This indicates
* that the application is
* supplying session-id's from
* other processes - spooky
* :-) */
} stats;
CRYPTO_REF_COUNT references;
/* if defined, these override the X509_verify_cert() calls */
int (*app_verify_callback) (X509_STORE_CTX *, void *);
void *app_verify_arg;
/*
* before OpenSSL 0.9.7, 'app_verify_arg' was ignored
* ('app_verify_callback' was called with just one argument)
*/
/* Default password callback. */
pem_password_cb *default_passwd_callback;
/* Default password callback user data. */
void *default_passwd_callback_userdata;
/* get client cert callback */
int (*client_cert_cb) (SSL *ssl, X509 **x509, EVP_PKEY **pkey);
/* cookie generate callback */
int (*app_gen_cookie_cb) (SSL *ssl, unsigned char *cookie,
unsigned int *cookie_len);
/* verify cookie callback */
int (*app_verify_cookie_cb) (SSL *ssl, const unsigned char *cookie,
unsigned int cookie_len);
/* TLS1.3 app-controlled cookie generate callback */
int (*gen_stateless_cookie_cb) (SSL *ssl, unsigned char *cookie,
size_t *cookie_len);
/* TLS1.3 verify app-controlled cookie callback */
int (*verify_stateless_cookie_cb) (SSL *ssl, const unsigned char *cookie,
size_t cookie_len);
CRYPTO_EX_DATA ex_data;
const EVP_MD *md5; /* For SSLv3/TLSv1 'ssl3-md5' */
const EVP_MD *sha1; /* For SSLv3/TLSv1 'ssl3->sha1' */
STACK_OF(X509) *extra_certs;
STACK_OF(SSL_COMP) *comp_methods; /* stack of SSL_COMP, SSLv3/TLSv1 */
/* Default values used when no per-SSL value is defined follow */
/* used if SSL's info_callback is NULL */
void (*info_callback) (const SSL *ssl, int type, int val);
/*
* What we put in certificate_authorities extension for TLS 1.3
* (ClientHello and CertificateRequest) or just client cert requests for
* earlier versions. If client_ca_names is populated then it is only used
* for client cert requests, and in preference to ca_names.
*/
STACK_OF(X509_NAME) *ca_names;
STACK_OF(X509_NAME) *client_ca_names;
/*
* Default values to use in SSL structures follow (these are copied by
* SSL_new)
*/
uint32_t options;
uint32_t mode;
int min_proto_version;
int max_proto_version;
size_t max_cert_list;
struct cert_st /* CERT */ *cert;
int read_ahead;
/* callback that allows applications to peek at protocol messages */
void (*msg_callback) (int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg);
void *msg_callback_arg;
uint32_t verify_mode;
size_t sid_ctx_length;
unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
/* called 'verify_callback' in the SSL */
int (*default_verify_callback) (int ok, X509_STORE_CTX *ctx);
/* Default generate session ID callback. */
GEN_SESSION_CB generate_session_id;
X509_VERIFY_PARAM *param;
int quiet_shutdown;
# ifndef OPENSSL_NO_CT
CTLOG_STORE *ctlog_store; /* CT Log Store */
/*
* Validates that the SCTs (Signed Certificate Timestamps) are sufficient.
* If they are not, the connection should be aborted.
*/
ssl_ct_validation_cb ct_validation_callback;
void *ct_validation_callback_arg;
# endif
/*
* If we're using more than one pipeline how should we divide the data
* up between the pipes?
*/
size_t split_send_fragment;
/*
* Maximum amount of data to send in one fragment. actual record size can
* be more than this due to padding and MAC overheads.
*/
size_t max_send_fragment;
/* Up to how many pipelines should we use? If 0 then 1 is assumed */
size_t max_pipelines;
/* The default read buffer length to use (0 means not set) */
size_t default_read_buf_len;
# ifndef OPENSSL_NO_ENGINE
/*
* Engine to pass requests for client certs to
*/
ENGINE *client_cert_engine;
# endif
/* ClientHello callback. Mostly for extensions, but not entirely. */
SSL_client_hello_cb_fn client_hello_cb;
void *client_hello_cb_arg;
/* TLS extensions. */
struct {
/* TLS extensions servername callback */
int (*servername_cb) (SSL *, int *, void *);
void *servername_arg;
/* RFC 4507 session ticket keys */
unsigned char tick_key_name[TLSEXT_KEYNAME_LENGTH];
SSL_CTX_EXT_SECURE *secure;
/* Callback to support customisation of ticket key setting */
int (*ticket_key_cb) (SSL *ssl,
unsigned char *name, unsigned char *iv,
EVP_CIPHER_CTX *ectx, HMAC_CTX *hctx, int enc);
/* certificate status request info */
/* Callback for status request */
int (*status_cb) (SSL *ssl, void *arg);
void *status_arg;
/* ext status type used for CSR extension (OCSP Stapling) */
int status_type;
/* RFC 4366 Maximum Fragment Length Negotiation */
uint8_t max_fragment_len_mode;
# ifndef OPENSSL_NO_EC
/* EC extension values inherited by SSL structure */
size_t ecpointformats_len;
unsigned char *ecpointformats;
size_t supportedgroups_len;
uint16_t *supportedgroups;
# endif /* OPENSSL_NO_EC */
/*
* ALPN information (we are in the process of transitioning from NPN to
* ALPN.)
*/
/*-
* For a server, this contains a callback function that allows the
* server to select the protocol for the connection.
* out: on successful return, this must point to the raw protocol
* name (without the length prefix).
* outlen: on successful return, this contains the length of |*out|.
* in: points to the client's list of supported protocols in
* wire-format.
* inlen: the length of |in|.
*/
int (*alpn_select_cb) (SSL *s,
const unsigned char **out,
unsigned char *outlen,
const unsigned char *in,
unsigned int inlen, void *arg);
void *alpn_select_cb_arg;
/*
* For a client, this contains the list of supported protocols in wire
* format.
*/
unsigned char *alpn;
size_t alpn_len;
# ifndef OPENSSL_NO_NEXTPROTONEG
/* Next protocol negotiation information */
/*
* For a server, this contains a callback function by which the set of
* advertised protocols can be provided.
*/
SSL_CTX_npn_advertised_cb_func npn_advertised_cb;
void *npn_advertised_cb_arg;
/*
* For a client, this contains a callback function that selects the next
* protocol from the list provided by the server.
*/
SSL_CTX_npn_select_cb_func npn_select_cb;
void *npn_select_cb_arg;
# endif
unsigned char cookie_hmac_key[SHA256_DIGEST_LENGTH];
} ext;
# ifndef OPENSSL_NO_PSK
SSL_psk_client_cb_func psk_client_callback;
SSL_psk_server_cb_func psk_server_callback;
# endif
SSL_psk_find_session_cb_func psk_find_session_cb;
SSL_psk_use_session_cb_func psk_use_session_cb;
# ifndef OPENSSL_NO_SRP
SRP_CTX srp_ctx; /* ctx for SRP authentication */
# endif
/* Shared DANE context */
struct dane_ctx_st dane;
# ifndef OPENSSL_NO_SRTP
/* SRTP profiles we are willing to do from RFC 5764 */
STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
# endif
/*
* Callback for disabling session caching and ticket support on a session
* basis, depending on the chosen cipher.
*/
int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure);
CRYPTO_RWLOCK *lock;
/*
* Callback for logging key material for use with debugging tools like
* Wireshark. The callback should log `line` followed by a newline.
*/
SSL_CTX_keylog_cb_func keylog_callback;
/*
* The maximum number of bytes advertised in session tickets that can be
* sent as early data.
*/
uint32_t max_early_data;
/*
* The maximum number of bytes of early data that a server will tolerate
* (which should be at least as much as max_early_data).
*/
uint32_t recv_max_early_data;
/* TLS1.3 padding callback */
size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg);
void *record_padding_arg;
size_t block_padding;
/* Session ticket appdata */
SSL_CTX_generate_session_ticket_fn generate_ticket_cb;
SSL_CTX_decrypt_session_ticket_fn decrypt_ticket_cb;
void *ticket_cb_data;
/* The number of TLS1.3 tickets to automatically send */
size_t num_tickets;
/* Callback to determine if early_data is acceptable or not */
SSL_allow_early_data_cb_fn allow_early_data_cb;
void *allow_early_data_cb_data;
/* Do we advertise Post-handshake auth support? */
int pha_enabled;
};
struct ssl_st {
/*
* protocol version (one of SSL2_VERSION, SSL3_VERSION, TLS1_VERSION,
* DTLS1_VERSION)
*/
int version;
/* SSLv3 */
const SSL_METHOD *method;
/*
* There are 2 BIO's even though they are normally both the same. This
* is so data can be read and written to different handlers
*/
/* used by SSL_read */
BIO *rbio;
/* used by SSL_write */
BIO *wbio;
/* used during session-id reuse to concatenate messages */
BIO *bbio;
/*
* This holds a variable that indicates what we were doing when a 0 or -1
* is returned. This is needed for non-blocking IO so we know what
* request needs re-doing when in SSL_accept or SSL_connect
*/
int rwstate;
int (*handshake_func) (SSL *);
/*
* Imagine that here's a boolean member "init" that is switched as soon
* as SSL_set_{accept/connect}_state is called for the first time, so
* that "state" and "handshake_func" are properly initialized. But as
* handshake_func is == 0 until then, we use this test instead of an
* "init" member.
*/
/* are we the server side? */
int server;
/*
* Generate a new session or reuse an old one.
* NB: For servers, the 'new' session may actually be a previously
* cached session or even the previous session unless
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set
*/
int new_session;
/* don't send shutdown packets */
int quiet_shutdown;
/* we have shut things down, 0x01 sent, 0x02 for received */
int shutdown;
/* where we are */
OSSL_STATEM statem;
SSL_EARLY_DATA_STATE early_data_state;
BUF_MEM *init_buf; /* buffer used during init */
void *init_msg; /* pointer to handshake message body, set by
* ssl3_get_message() */
size_t init_num; /* amount read/written */
size_t init_off; /* amount read/written */
struct ssl3_state_st *s3; /* SSLv3 variables */
struct dtls1_state_st *d1; /* DTLSv1 variables */
/* callback that allows applications to peek at protocol messages */
void (*msg_callback) (int write_p, int version, int content_type,
const void *buf, size_t len, SSL *ssl, void *arg);
void *msg_callback_arg;
int hit; /* reusing a previous session */
X509_VERIFY_PARAM *param;
/* Per connection DANE state */
SSL_DANE dane;
/* crypto */
STACK_OF(SSL_CIPHER) *cipher_list;
STACK_OF(SSL_CIPHER) *cipher_list_by_id;
/* TLSv1.3 specific ciphersuites */
STACK_OF(SSL_CIPHER) *tls13_ciphersuites;
/*
* These are the ones being used, the ones in SSL_SESSION are the ones to
* be 'copied' into these ones
*/
uint32_t mac_flags;
/*
* The TLS1.3 secrets.
*/
unsigned char early_secret[EVP_MAX_MD_SIZE];
unsigned char handshake_secret[EVP_MAX_MD_SIZE];
unsigned char master_secret[EVP_MAX_MD_SIZE];
unsigned char resumption_master_secret[EVP_MAX_MD_SIZE];
unsigned char client_finished_secret[EVP_MAX_MD_SIZE];
unsigned char server_finished_secret[EVP_MAX_MD_SIZE];
unsigned char server_finished_hash[EVP_MAX_MD_SIZE];
unsigned char handshake_traffic_hash[EVP_MAX_MD_SIZE];
unsigned char client_app_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char server_app_traffic_secret[EVP_MAX_MD_SIZE];
unsigned char exporter_master_secret[EVP_MAX_MD_SIZE];
unsigned char early_exporter_master_secret[EVP_MAX_MD_SIZE];
EVP_CIPHER_CTX *enc_read_ctx; /* cryptographic state */
unsigned char read_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static read IV */
EVP_MD_CTX *read_hash; /* used for mac generation */
COMP_CTX *compress; /* compression */
COMP_CTX *expand; /* uncompress */
EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
unsigned char write_iv[EVP_MAX_IV_LENGTH]; /* TLSv1.3 static write IV */
EVP_MD_CTX *write_hash; /* used for mac generation */
/* session info */
/* client cert? */
/* This is used to hold the server certificate used */
struct cert_st /* CERT */ *cert;
/*
* The hash of all messages prior to the CertificateVerify, and the length
* of that hash.
*/
unsigned char cert_verify_hash[EVP_MAX_MD_SIZE];
size_t cert_verify_hash_len;
/* Flag to indicate whether we should send a HelloRetryRequest or not */
enum {SSL_HRR_NONE = 0, SSL_HRR_PENDING, SSL_HRR_COMPLETE}
hello_retry_request;
/*
* the session_id_context is used to ensure sessions are only reused in
* the appropriate context
*/
size_t sid_ctx_length;
unsigned char sid_ctx[SSL_MAX_SID_CTX_LENGTH];
/* This can also be in the session once a session is established */
SSL_SESSION *session;
/* TLSv1.3 PSK session */
SSL_SESSION *psksession;
unsigned char *psksession_id;
size_t psksession_id_len;
/* Default generate session ID callback. */
GEN_SESSION_CB generate_session_id;
/*
* The temporary TLSv1.3 session id. This isn't really a session id at all
* but is a random value sent in the legacy session id field.
*/
unsigned char tmp_session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
size_t tmp_session_id_len;
/* Used in SSL3 */
/*
* 0 don't care about verify failure.
* 1 fail if verify fails
*/
uint32_t verify_mode;
/* fail if callback returns 0 */
int (*verify_callback) (int ok, X509_STORE_CTX *ctx);
/* optional informational callback */
void (*info_callback) (const SSL *ssl, int type, int val);
/* error bytes to be written */
int error;
/* actual code */
int error_code;
# ifndef OPENSSL_NO_PSK
SSL_psk_client_cb_func psk_client_callback;
SSL_psk_server_cb_func psk_server_callback;
# endif
SSL_psk_find_session_cb_func psk_find_session_cb;
SSL_psk_use_session_cb_func psk_use_session_cb;
SSL_CTX *ctx;
/* Verified chain of peer */
STACK_OF(X509) *verified_chain;
long verify_result;
/* extra application data */
CRYPTO_EX_DATA ex_data;
/*
* What we put in certificate_authorities extension for TLS 1.3
* (ClientHello and CertificateRequest) or just client cert requests for
* earlier versions. If client_ca_names is populated then it is only used
* for client cert requests, and in preference to ca_names.
*/
STACK_OF(X509_NAME) *ca_names;
STACK_OF(X509_NAME) *client_ca_names;
CRYPTO_REF_COUNT references;
/* protocol behaviour */
uint32_t options;
/* API behaviour */
uint32_t mode;
int min_proto_version;
int max_proto_version;
size_t max_cert_list;
int first_packet;
/*
* What was passed in ClientHello.legacy_version. Used for RSA pre-master
* secret and SSLv3/TLS (<=1.2) rollback check
*/
int client_version;
/*
* If we're using more than one pipeline how should we divide the data
* up between the pipes?
*/
size_t split_send_fragment;
/*
* Maximum amount of data to send in one fragment. actual record size can
* be more than this due to padding and MAC overheads.
*/
size_t max_send_fragment;
/* Up to how many pipelines should we use? If 0 then 1 is assumed */
size_t max_pipelines;
struct {
/* Built-in extension flags */
uint8_t extflags[TLSEXT_IDX_num_builtins];
/* TLS extension debug callback */
void (*debug_cb)(SSL *s, int client_server, int type,
const unsigned char *data, int len, void *arg);
void *debug_arg;
char *hostname;
/* certificate status request info */
/* Status type or -1 if no status type */
int status_type;
/* Raw extension data, if seen */
unsigned char *scts;
/* Length of raw extension data, if seen */
uint16_t scts_len;
/* Expect OCSP CertificateStatus message */
int status_expected;
struct {
/* OCSP status request only */
STACK_OF(OCSP_RESPID) *ids;
X509_EXTENSIONS *exts;
/* OCSP response received or to be sent */
unsigned char *resp;
size_t resp_len;
} ocsp;
/* RFC4507 session ticket expected to be received or sent */
int ticket_expected;
# ifndef OPENSSL_NO_EC
size_t ecpointformats_len;
/* our list */
unsigned char *ecpointformats;
# endif /* OPENSSL_NO_EC */
size_t supportedgroups_len;
/* our list */
uint16_t *supportedgroups;
/* TLS Session Ticket extension override */
TLS_SESSION_TICKET_EXT *session_ticket;
/* TLS Session Ticket extension callback */
tls_session_ticket_ext_cb_fn session_ticket_cb;
void *session_ticket_cb_arg;
/* TLS pre-shared secret session resumption */
tls_session_secret_cb_fn session_secret_cb;
void *session_secret_cb_arg;
/*
* For a client, this contains the list of supported protocols in wire
* format.
*/
unsigned char *alpn;
size_t alpn_len;
/*
* Next protocol negotiation. For the client, this is the protocol that
* we sent in NextProtocol and is set when handling ServerHello
* extensions. For a server, this is the client's selected_protocol from
* NextProtocol and is set when handling the NextProtocol message, before
* the Finished message.
*/
unsigned char *npn;
size_t npn_len;
/* The available PSK key exchange modes */
int psk_kex_mode;
/* Set to one if we have negotiated ETM */
int use_etm;
/* Are we expecting to receive early data? */
int early_data;
/* Is the session suitable for early data? */
int early_data_ok;
/* May be sent by a server in HRR. Must be echoed back in ClientHello */
unsigned char *tls13_cookie;
size_t tls13_cookie_len;
/* Have we received a cookie from the client? */
int cookieok;
/*
* Maximum Fragment Length as per RFC 4366.
* If this member contains one of the allowed values (1-4)
* then we should include Maximum Fragment Length Negotiation
* extension in Client Hello.
* Please note that value of this member does not have direct
* effect. The actual (binding) value is stored in SSL_SESSION,
* as this extension is optional on server side.
*/
uint8_t max_fragment_len_mode;
+
+ /*
+ * On the client side the number of ticket identities we sent in the
+ * ClientHello. On the server side the identity of the ticket we
+ * selected.
+ */
+ int tick_identity;
} ext;
/*
* Parsed form of the ClientHello, kept around across client_hello_cb
* calls.
*/
CLIENTHELLO_MSG *clienthello;
/*-
* no further mod of servername
* 0 : call the servername extension callback.
* 1 : prepare 2, allow last ack just after in server callback.
* 2 : don't call servername callback, no ack in server hello
*/
int servername_done;
# ifndef OPENSSL_NO_CT
/*
* Validates that the SCTs (Signed Certificate Timestamps) are sufficient.
* If they are not, the connection should be aborted.
*/
ssl_ct_validation_cb ct_validation_callback;
/* User-supplied argument that is passed to the ct_validation_callback */
void *ct_validation_callback_arg;
/*
* Consolidated stack of SCTs from all sources.
* Lazily populated by CT_get_peer_scts(SSL*)
*/
STACK_OF(SCT) *scts;
/* Have we attempted to find/parse SCTs yet? */
int scts_parsed;
# endif
SSL_CTX *session_ctx; /* initial ctx, used to store sessions */
# ifndef OPENSSL_NO_SRTP
/* What we'll do */
STACK_OF(SRTP_PROTECTION_PROFILE) *srtp_profiles;
/* What's been chosen */
SRTP_PROTECTION_PROFILE *srtp_profile;
# endif
/*-
* 1 if we are renegotiating.
* 2 if we are a server and are inside a handshake
* (i.e. not just sending a HelloRequest)
*/
int renegotiate;
/* If sending a KeyUpdate is pending */
int key_update;
/* Post-handshake authentication state */
SSL_PHA_STATE post_handshake_auth;
int pha_enabled;
uint8_t* pha_context;
size_t pha_context_len;
int certreqs_sent;
EVP_MD_CTX *pha_dgst; /* this is just the digest through ClientFinished */
# ifndef OPENSSL_NO_SRP
/* ctx for SRP authentication */
SRP_CTX srp_ctx;
# endif
/*
* Callback for disabling session caching and ticket support on a session
* basis, depending on the chosen cipher.
*/
int (*not_resumable_session_cb) (SSL *ssl, int is_forward_secure);
RECORD_LAYER rlayer;
/* Default password callback. */
pem_password_cb *default_passwd_callback;
/* Default password callback user data. */
void *default_passwd_callback_userdata;
/* Async Job info */
ASYNC_JOB *job;
ASYNC_WAIT_CTX *waitctx;
size_t asyncrw;
/*
* The maximum number of bytes advertised in session tickets that can be
* sent as early data.
*/
uint32_t max_early_data;
/*
* The maximum number of bytes of early data that a server will tolerate
* (which should be at least as much as max_early_data).
*/
uint32_t recv_max_early_data;
/*
* The number of bytes of early data received so far. If we accepted early
* data then this is a count of the plaintext bytes. If we rejected it then
* this is a count of the ciphertext bytes.
*/
uint32_t early_data_count;
/* TLS1.3 padding callback */
size_t (*record_padding_cb)(SSL *s, int type, size_t len, void *arg);
void *record_padding_arg;
size_t block_padding;
CRYPTO_RWLOCK *lock;
RAND_DRBG *drbg;
/* The number of TLS1.3 tickets to automatically send */
size_t num_tickets;
/* The number of TLS1.3 tickets actually sent so far */
size_t sent_tickets;
/* The next nonce value to use when we send a ticket on this connection */
uint64_t next_ticket_nonce;
/* Callback to determine if early_data is acceptable or not */
SSL_allow_early_data_cb_fn allow_early_data_cb;
void *allow_early_data_cb_data;
};
/*
* Structure containing table entry of values associated with the signature
* algorithms (signature scheme) extension
*/
typedef struct sigalg_lookup_st {
/* TLS 1.3 signature scheme name */
const char *name;
/* Raw value used in extension */
uint16_t sigalg;
/* NID of hash algorithm or NID_undef if no hash */
int hash;
/* Index of hash algorithm or -1 if no hash algorithm */
int hash_idx;
/* NID of signature algorithm */
int sig;
/* Index of signature algorithm */
int sig_idx;
/* Combined hash and signature NID, if any */
int sigandhash;
/* Required public key curve (ECDSA only) */
int curve;
} SIGALG_LOOKUP;
typedef struct tls_group_info_st {
int nid; /* Curve NID */
int secbits; /* Bits of security (from SP800-57) */
uint16_t flags; /* Flags: currently just group type */
} TLS_GROUP_INFO;
/* flags values */
# define TLS_CURVE_TYPE 0x3 /* Mask for group type */
# define TLS_CURVE_PRIME 0x0
# define TLS_CURVE_CHAR2 0x1
# define TLS_CURVE_CUSTOM 0x2
typedef struct cert_pkey_st CERT_PKEY;
/*
* Structure containing table entry of certificate info corresponding to
* CERT_PKEY entries
*/
typedef struct {
- int nid; /* NID of pubic key algorithm */
+ int nid; /* NID of public key algorithm */
uint32_t amask; /* authmask corresponding to key type */
} SSL_CERT_LOOKUP;
typedef struct ssl3_state_st {
long flags;
size_t read_mac_secret_size;
unsigned char read_mac_secret[EVP_MAX_MD_SIZE];
size_t write_mac_secret_size;
unsigned char write_mac_secret[EVP_MAX_MD_SIZE];
unsigned char server_random[SSL3_RANDOM_SIZE];
unsigned char client_random[SSL3_RANDOM_SIZE];
/* flags for countermeasure against known-IV weakness */
int need_empty_fragments;
int empty_fragment_done;
/* used during startup, digest all incoming/outgoing packets */
BIO *handshake_buffer;
/*
* When handshake digest is determined, buffer is hashed and
* freed and MD_CTX for the required digest is stored here.
*/
EVP_MD_CTX *handshake_dgst;
/*
* Set whenever an expected ChangeCipherSpec message is processed.
* Unset when the peer's Finished message is received.
* Unexpected ChangeCipherSpec messages trigger a fatal alert.
*/
int change_cipher_spec;
int warn_alert;
int fatal_alert;
/*
* we allow one fatal and one warning alert to be outstanding, send close
* alert via the warning alert
*/
int alert_dispatch;
unsigned char send_alert[2];
/*
* This flag is set when we should renegotiate ASAP, basically when there
* is no more data in the read or write buffers
*/
int renegotiate;
int total_renegotiations;
int num_renegotiations;
int in_read_app_data;
struct {
/* actually only need to be 16+20 for SSLv3 and 12 for TLS */
unsigned char finish_md[EVP_MAX_MD_SIZE * 2];
size_t finish_md_len;
unsigned char peer_finish_md[EVP_MAX_MD_SIZE * 2];
size_t peer_finish_md_len;
size_t message_size;
int message_type;
/* used to hold the new cipher we are going to use */
const SSL_CIPHER *new_cipher;
# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
EVP_PKEY *pkey; /* holds short lived DH/ECDH key */
# endif
/* used for certificate requests */
int cert_req;
/* Certificate types in certificate request message. */
uint8_t *ctype;
size_t ctype_len;
/* Certificate authorities list peer sent */
STACK_OF(X509_NAME) *peer_ca_names;
size_t key_block_length;
unsigned char *key_block;
const EVP_CIPHER *new_sym_enc;
const EVP_MD *new_hash;
int new_mac_pkey_type;
size_t new_mac_secret_size;
# ifndef OPENSSL_NO_COMP
const SSL_COMP *new_compression;
# else
char *new_compression;
# endif
int cert_request;
/* Raw values of the cipher list from a client */
unsigned char *ciphers_raw;
size_t ciphers_rawlen;
/* Temporary storage for premaster secret */
unsigned char *pms;
size_t pmslen;
# ifndef OPENSSL_NO_PSK
/* Temporary storage for PSK key */
unsigned char *psk;
size_t psklen;
# endif
/* Signature algorithm we actually use */
const SIGALG_LOOKUP *sigalg;
/* Pointer to certificate we use */
CERT_PKEY *cert;
/*
* signature algorithms peer reports: e.g. supported signature
* algorithms extension for server or as part of a certificate
* request for client.
* Keep track of the algorithms for TLS and X.509 usage separately.
*/
uint16_t *peer_sigalgs;
uint16_t *peer_cert_sigalgs;
/* Size of above arrays */
size_t peer_sigalgslen;
size_t peer_cert_sigalgslen;
/* Sigalg peer actually uses */
const SIGALG_LOOKUP *peer_sigalg;
/*
* Set if corresponding CERT_PKEY can be used with current
* SSL session: e.g. appropriate curve, signature algorithms etc.
* If zero it can't be used at all.
*/
uint32_t valid_flags[SSL_PKEY_NUM];
/*
* For servers the following masks are for the key and auth algorithms
* that are supported by the certs below. For clients they are masks of
* *disabled* algorithms based on the current session.
*/
uint32_t mask_k;
uint32_t mask_a;
/*
* The following are used by the client to see if a cipher is allowed or
* not. It contains the minimum and maximum version the client's using
* based on what it knows so far.
*/
int min_ver;
int max_ver;
} tmp;
/* Connection binding to prevent renegotiation attacks */
unsigned char previous_client_finished[EVP_MAX_MD_SIZE];
size_t previous_client_finished_len;
unsigned char previous_server_finished[EVP_MAX_MD_SIZE];
size_t previous_server_finished_len;
int send_connection_binding; /* TODOEKR */
# ifndef OPENSSL_NO_NEXTPROTONEG
/*
* Set if we saw the Next Protocol Negotiation extension from our peer.
*/
int npn_seen;
# endif
/*
* ALPN information (we are in the process of transitioning from NPN to
* ALPN.)
*/
/*
* In a server these point to the selected ALPN protocol after the
* ClientHello has been processed. In a client these contain the protocol
* that the server selected once the ServerHello has been processed.
*/
unsigned char *alpn_selected;
size_t alpn_selected_len;
/* used by the server to know what options were proposed */
unsigned char *alpn_proposed;
size_t alpn_proposed_len;
/* used by the client to know if it actually sent alpn */
int alpn_sent;
# ifndef OPENSSL_NO_EC
/*
* This is set to true if we believe that this is a version of Safari
* running on OS X 10.6 or newer. We wish to know this because Safari on
* 10.8 .. 10.8.3 has broken ECDHE-ECDSA support.
*/
char is_probably_safari;
# endif /* !OPENSSL_NO_EC */
/* For clients: peer temporary key */
# if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
/* The group_id for the DH/ECDH key */
uint16_t group_id;
EVP_PKEY *peer_tmp;
# endif
} SSL3_STATE;
/* DTLS structures */
# ifndef OPENSSL_NO_SCTP
# define DTLS1_SCTP_AUTH_LABEL "EXPORTER_DTLS_OVER_SCTP"
# endif
/* Max MTU overhead we know about so far is 40 for IPv6 + 8 for UDP */
# define DTLS1_MAX_MTU_OVERHEAD 48
/*
* Flag used in message reuse to indicate the buffer contains the record
* header as well as the handshake message header.
*/
# define DTLS1_SKIP_RECORD_HEADER 2
struct dtls1_retransmit_state {
EVP_CIPHER_CTX *enc_write_ctx; /* cryptographic state */
EVP_MD_CTX *write_hash; /* used for mac generation */
COMP_CTX *compress; /* compression */
SSL_SESSION *session;
unsigned short epoch;
};
struct hm_header_st {
unsigned char type;
size_t msg_len;
unsigned short seq;
size_t frag_off;
size_t frag_len;
unsigned int is_ccs;
struct dtls1_retransmit_state saved_retransmit_state;
};
struct dtls1_timeout_st {
/* Number of read timeouts so far */
unsigned int read_timeouts;
/* Number of write timeouts so far */
unsigned int write_timeouts;
/* Number of alerts received so far */
unsigned int num_alerts;
};
typedef struct hm_fragment_st {
struct hm_header_st msg_header;
unsigned char *fragment;
unsigned char *reassembly;
} hm_fragment;
typedef struct pqueue_st pqueue;
typedef struct pitem_st pitem;
struct pitem_st {
unsigned char priority[8]; /* 64-bit value in big-endian encoding */
void *data;
pitem *next;
};
typedef struct pitem_st *piterator;
pitem *pitem_new(unsigned char *prio64be, void *data);
void pitem_free(pitem *item);
pqueue *pqueue_new(void);
void pqueue_free(pqueue *pq);
pitem *pqueue_insert(pqueue *pq, pitem *item);
pitem *pqueue_peek(pqueue *pq);
pitem *pqueue_pop(pqueue *pq);
pitem *pqueue_find(pqueue *pq, unsigned char *prio64be);
pitem *pqueue_iterator(pqueue *pq);
pitem *pqueue_next(piterator *iter);
size_t pqueue_size(pqueue *pq);
typedef struct dtls1_state_st {
unsigned char cookie[DTLS1_COOKIE_LENGTH];
size_t cookie_len;
unsigned int cookie_verified;
/* handshake message numbers */
unsigned short handshake_write_seq;
unsigned short next_handshake_write_seq;
unsigned short handshake_read_seq;
/* Buffered handshake messages */
pqueue *buffered_messages;
/* Buffered (sent) handshake records */
pqueue *sent_messages;
size_t link_mtu; /* max on-the-wire DTLS packet size */
size_t mtu; /* max DTLS packet size */
struct hm_header_st w_msg_hdr;
struct hm_header_st r_msg_hdr;
struct dtls1_timeout_st timeout;
/*
* Indicates when the last handshake msg sent will timeout
*/
struct timeval next_timeout;
/* Timeout duration */
unsigned int timeout_duration_us;
unsigned int retransmitting;
# ifndef OPENSSL_NO_SCTP
int shutdown_received;
# endif
DTLS_timer_cb timer_cb;
} DTLS1_STATE;
# ifndef OPENSSL_NO_EC
/*
* From ECC-TLS draft, used in encoding the curve type in ECParameters
*/
# define EXPLICIT_PRIME_CURVE_TYPE 1
# define EXPLICIT_CHAR2_CURVE_TYPE 2
# define NAMED_CURVE_TYPE 3
# endif /* OPENSSL_NO_EC */
struct cert_pkey_st {
X509 *x509;
EVP_PKEY *privatekey;
/* Chain for this certificate */
STACK_OF(X509) *chain;
/*-
* serverinfo data for this certificate. The data is in TLS Extension
* wire format, specifically it's a series of records like:
* uint16_t extension_type; // (RFC 5246, 7.4.1.4, Extension)
* uint16_t length;
* uint8_t data[length];
*/
unsigned char *serverinfo;
size_t serverinfo_length;
};
/* Retrieve Suite B flags */
# define tls1_suiteb(s) (s->cert->cert_flags & SSL_CERT_FLAG_SUITEB_128_LOS)
/* Uses to check strict mode: suite B modes are always strict */
# define SSL_CERT_FLAGS_CHECK_TLS_STRICT \
(SSL_CERT_FLAG_SUITEB_128_LOS|SSL_CERT_FLAG_TLS_STRICT)
typedef enum {
ENDPOINT_CLIENT = 0,
ENDPOINT_SERVER,
ENDPOINT_BOTH
} ENDPOINT;
typedef struct {
unsigned short ext_type;
ENDPOINT role;
/* The context which this extension applies to */
unsigned int context;
/*
* Per-connection flags relating to this extension type: not used if
* part of an SSL_CTX structure.
*/
uint32_t ext_flags;
SSL_custom_ext_add_cb_ex add_cb;
SSL_custom_ext_free_cb_ex free_cb;
void *add_arg;
SSL_custom_ext_parse_cb_ex parse_cb;
void *parse_arg;
} custom_ext_method;
/* ext_flags values */
/*
* Indicates an extension has been received. Used to check for unsolicited or
* duplicate extensions.
*/
# define SSL_EXT_FLAG_RECEIVED 0x1
/*
* Indicates an extension has been sent: used to enable sending of
* corresponding ServerHello extension.
*/
# define SSL_EXT_FLAG_SENT 0x2
typedef struct {
custom_ext_method *meths;
size_t meths_count;
} custom_ext_methods;
typedef struct cert_st {
/* Current active set */
/*
* ALWAYS points to an element of the pkeys array
* Probably it would make more sense to store
* an index, not a pointer.
*/
CERT_PKEY *key;
# ifndef OPENSSL_NO_DH
EVP_PKEY *dh_tmp;
DH *(*dh_tmp_cb) (SSL *ssl, int is_export, int keysize);
int dh_tmp_auto;
# endif
/* Flags related to certificates */
uint32_t cert_flags;
CERT_PKEY pkeys[SSL_PKEY_NUM];
/* Custom certificate types sent in certificate request message. */
uint8_t *ctype;
size_t ctype_len;
/*
* supported signature algorithms. When set on a client this is sent in
* the client hello as the supported signature algorithms extension. For
* servers it represents the signature algorithms we are willing to use.
*/
uint16_t *conf_sigalgs;
/* Size of above array */
size_t conf_sigalgslen;
/*
* Client authentication signature algorithms, if not set then uses
* conf_sigalgs. On servers these will be the signature algorithms sent
* to the client in a certificate request for TLS 1.2. On a client this
* represents the signature algorithms we are willing to use for client
* authentication.
*/
uint16_t *client_sigalgs;
/* Size of above array */
size_t client_sigalgslen;
/*
* Signature algorithms shared by client and server: cached because these
* are used most often.
*/
const SIGALG_LOOKUP **shared_sigalgs;
size_t shared_sigalgslen;
/*
* Certificate setup callback: if set is called whenever a certificate
* may be required (client or server). the callback can then examine any
* appropriate parameters and setup any certificates required. This
* allows advanced applications to select certificates on the fly: for
* example based on supported signature algorithms or curves.
*/
int (*cert_cb) (SSL *ssl, void *arg);
void *cert_cb_arg;
/*
* Optional X509_STORE for chain building or certificate validation If
* NULL the parent SSL_CTX store is used instead.
*/
X509_STORE *chain_store;
X509_STORE *verify_store;
/* Custom extensions */
custom_ext_methods custext;
/* Security callback */
int (*sec_cb) (const SSL *s, const SSL_CTX *ctx, int op, int bits, int nid,
void *other, void *ex);
/* Security level */
int sec_level;
void *sec_ex;
# ifndef OPENSSL_NO_PSK
/* If not NULL psk identity hint to use for servers */
char *psk_identity_hint;
# endif
CRYPTO_REF_COUNT references; /* >1 only if SSL_copy_session_id is used */
CRYPTO_RWLOCK *lock;
} CERT;
# define FP_ICC (int (*)(const void *,const void *))
/*
* This is for the SSLv3/TLSv1.0 differences in crypto/hash stuff It is a bit
* of a mess of functions, but hell, think of it as an opaque structure :-)
*/
typedef struct ssl3_enc_method {
int (*enc) (SSL *, SSL3_RECORD *, size_t, int);
int (*mac) (SSL *, SSL3_RECORD *, unsigned char *, int);
int (*setup_key_block) (SSL *);
int (*generate_master_secret) (SSL *, unsigned char *, unsigned char *,
size_t, size_t *);
int (*change_cipher_state) (SSL *, int);
size_t (*final_finish_mac) (SSL *, const char *, size_t, unsigned char *);
const char *client_finished_label;
size_t client_finished_label_len;
const char *server_finished_label;
size_t server_finished_label_len;
int (*alert_value) (int);
int (*export_keying_material) (SSL *, unsigned char *, size_t,
const char *, size_t,
const unsigned char *, size_t,
int use_context);
/* Various flags indicating protocol version requirements */
uint32_t enc_flags;
/* Set the handshake header */
int (*set_handshake_header) (SSL *s, WPACKET *pkt, int type);
/* Close construction of the handshake message */
int (*close_construct_packet) (SSL *s, WPACKET *pkt, int htype);
/* Write out handshake message */
int (*do_write) (SSL *s);
} SSL3_ENC_METHOD;
# define ssl_set_handshake_header(s, pkt, htype) \
s->method->ssl3_enc->set_handshake_header((s), (pkt), (htype))
# define ssl_close_construct_packet(s, pkt, htype) \
s->method->ssl3_enc->close_construct_packet((s), (pkt), (htype))
# define ssl_do_write(s) s->method->ssl3_enc->do_write(s)
/* Values for enc_flags */
/* Uses explicit IV for CBC mode */
# define SSL_ENC_FLAG_EXPLICIT_IV 0x1
/* Uses signature algorithms extension */
# define SSL_ENC_FLAG_SIGALGS 0x2
/* Uses SHA256 default PRF */
# define SSL_ENC_FLAG_SHA256_PRF 0x4
/* Is DTLS */
# define SSL_ENC_FLAG_DTLS 0x8
/*
* Allow TLS 1.2 ciphersuites: applies to DTLS 1.2 as well as TLS 1.2: may
* apply to others in future.
*/
# define SSL_ENC_FLAG_TLS1_2_CIPHERS 0x10
# ifndef OPENSSL_NO_COMP
/* Used for holding the relevant compression methods loaded into SSL_CTX */
typedef struct ssl3_comp_st {
int comp_id; /* The identifier byte for this compression
* type */
char *name; /* Text name used for the compression type */
COMP_METHOD *method; /* The method :-) */
} SSL3_COMP;
# endif
typedef enum downgrade_en {
DOWNGRADE_NONE,
DOWNGRADE_TO_1_2,
DOWNGRADE_TO_1_1
} DOWNGRADE;
/*
* Dummy status type for the status_type extension. Indicates no status type
* set
*/
#define TLSEXT_STATUSTYPE_nothing -1
/* Sigalgs values */
#define TLSEXT_SIGALG_ecdsa_secp256r1_sha256 0x0403
#define TLSEXT_SIGALG_ecdsa_secp384r1_sha384 0x0503
#define TLSEXT_SIGALG_ecdsa_secp521r1_sha512 0x0603
#define TLSEXT_SIGALG_ecdsa_sha224 0x0303
#define TLSEXT_SIGALG_ecdsa_sha1 0x0203
#define TLSEXT_SIGALG_rsa_pss_rsae_sha256 0x0804
#define TLSEXT_SIGALG_rsa_pss_rsae_sha384 0x0805
#define TLSEXT_SIGALG_rsa_pss_rsae_sha512 0x0806
#define TLSEXT_SIGALG_rsa_pss_pss_sha256 0x0809
#define TLSEXT_SIGALG_rsa_pss_pss_sha384 0x080a
#define TLSEXT_SIGALG_rsa_pss_pss_sha512 0x080b
#define TLSEXT_SIGALG_rsa_pkcs1_sha256 0x0401
#define TLSEXT_SIGALG_rsa_pkcs1_sha384 0x0501
#define TLSEXT_SIGALG_rsa_pkcs1_sha512 0x0601
#define TLSEXT_SIGALG_rsa_pkcs1_sha224 0x0301
#define TLSEXT_SIGALG_rsa_pkcs1_sha1 0x0201
#define TLSEXT_SIGALG_dsa_sha256 0x0402
#define TLSEXT_SIGALG_dsa_sha384 0x0502
#define TLSEXT_SIGALG_dsa_sha512 0x0602
#define TLSEXT_SIGALG_dsa_sha224 0x0302
#define TLSEXT_SIGALG_dsa_sha1 0x0202
#define TLSEXT_SIGALG_gostr34102012_256_gostr34112012_256 0xeeee
#define TLSEXT_SIGALG_gostr34102012_512_gostr34112012_512 0xefef
#define TLSEXT_SIGALG_gostr34102001_gostr3411 0xeded
#define TLSEXT_SIGALG_ed25519 0x0807
#define TLSEXT_SIGALG_ed448 0x0808
/* Known PSK key exchange modes */
#define TLSEXT_KEX_MODE_KE 0x00
#define TLSEXT_KEX_MODE_KE_DHE 0x01
/*
* Internal representations of key exchange modes
*/
#define TLSEXT_KEX_MODE_FLAG_NONE 0
#define TLSEXT_KEX_MODE_FLAG_KE 1
#define TLSEXT_KEX_MODE_FLAG_KE_DHE 2
-/* An invalid index into the TLSv1.3 PSK identities */
-#define TLSEXT_PSK_BAD_IDENTITY -1
-
#define SSL_USE_PSS(s) (s->s3->tmp.peer_sigalg != NULL && \
s->s3->tmp.peer_sigalg->sig == EVP_PKEY_RSA_PSS)
/* A dummy signature value not valid for TLSv1.2 signature algs */
#define TLSEXT_signature_rsa_pss 0x0101
/* TLSv1.3 downgrade protection sentinel values */
extern const unsigned char tls11downgrade[8];
extern const unsigned char tls12downgrade[8];
extern SSL3_ENC_METHOD ssl3_undef_enc_method;
__owur const SSL_METHOD *ssl_bad_method(int ver);
__owur const SSL_METHOD *sslv3_method(void);
__owur const SSL_METHOD *sslv3_server_method(void);
__owur const SSL_METHOD *sslv3_client_method(void);
__owur const SSL_METHOD *tlsv1_method(void);
__owur const SSL_METHOD *tlsv1_server_method(void);
__owur const SSL_METHOD *tlsv1_client_method(void);
__owur const SSL_METHOD *tlsv1_1_method(void);
__owur const SSL_METHOD *tlsv1_1_server_method(void);
__owur const SSL_METHOD *tlsv1_1_client_method(void);
__owur const SSL_METHOD *tlsv1_2_method(void);
__owur const SSL_METHOD *tlsv1_2_server_method(void);
__owur const SSL_METHOD *tlsv1_2_client_method(void);
__owur const SSL_METHOD *tlsv1_3_method(void);
__owur const SSL_METHOD *tlsv1_3_server_method(void);
__owur const SSL_METHOD *tlsv1_3_client_method(void);
__owur const SSL_METHOD *dtlsv1_method(void);
__owur const SSL_METHOD *dtlsv1_server_method(void);
__owur const SSL_METHOD *dtlsv1_client_method(void);
__owur const SSL_METHOD *dtls_bad_ver_client_method(void);
__owur const SSL_METHOD *dtlsv1_2_method(void);
__owur const SSL_METHOD *dtlsv1_2_server_method(void);
__owur const SSL_METHOD *dtlsv1_2_client_method(void);
extern const SSL3_ENC_METHOD TLSv1_enc_data;
extern const SSL3_ENC_METHOD TLSv1_1_enc_data;
extern const SSL3_ENC_METHOD TLSv1_2_enc_data;
extern const SSL3_ENC_METHOD TLSv1_3_enc_data;
extern const SSL3_ENC_METHOD SSLv3_enc_data;
extern const SSL3_ENC_METHOD DTLSv1_enc_data;
extern const SSL3_ENC_METHOD DTLSv1_2_enc_data;
/*
* Flags for SSL methods
*/
# define SSL_METHOD_NO_FIPS (1U<<0)
# define SSL_METHOD_NO_SUITEB (1U<<1)
# define IMPLEMENT_tls_meth_func(version, flags, mask, func_name, s_accept, \
s_connect, enc_data) \
const SSL_METHOD *func_name(void) \
{ \
static const SSL_METHOD func_name##_data= { \
version, \
flags, \
mask, \
tls1_new, \
tls1_clear, \
tls1_free, \
s_accept, \
s_connect, \
ssl3_read, \
ssl3_peek, \
ssl3_write, \
ssl3_shutdown, \
ssl3_renegotiate, \
ssl3_renegotiate_check, \
ssl3_read_bytes, \
ssl3_write_bytes, \
ssl3_dispatch_alert, \
ssl3_ctrl, \
ssl3_ctx_ctrl, \
ssl3_get_cipher_by_char, \
ssl3_put_cipher_by_char, \
ssl3_pending, \
ssl3_num_ciphers, \
ssl3_get_cipher, \
tls1_default_timeout, \
&enc_data, \
ssl_undefined_void_function, \
ssl3_callback_ctrl, \
ssl3_ctx_callback_ctrl, \
}; \
return &func_name##_data; \
}
# define IMPLEMENT_ssl3_meth_func(func_name, s_accept, s_connect) \
const SSL_METHOD *func_name(void) \
{ \
static const SSL_METHOD func_name##_data= { \
SSL3_VERSION, \
SSL_METHOD_NO_FIPS | SSL_METHOD_NO_SUITEB, \
SSL_OP_NO_SSLv3, \
ssl3_new, \
ssl3_clear, \
ssl3_free, \
s_accept, \
s_connect, \
ssl3_read, \
ssl3_peek, \
ssl3_write, \
ssl3_shutdown, \
ssl3_renegotiate, \
ssl3_renegotiate_check, \
ssl3_read_bytes, \
ssl3_write_bytes, \
ssl3_dispatch_alert, \
ssl3_ctrl, \
ssl3_ctx_ctrl, \
ssl3_get_cipher_by_char, \
ssl3_put_cipher_by_char, \
ssl3_pending, \
ssl3_num_ciphers, \
ssl3_get_cipher, \
ssl3_default_timeout, \
&SSLv3_enc_data, \
ssl_undefined_void_function, \
ssl3_callback_ctrl, \
ssl3_ctx_callback_ctrl, \
}; \
return &func_name##_data; \
}
# define IMPLEMENT_dtls1_meth_func(version, flags, mask, func_name, s_accept, \
s_connect, enc_data) \
const SSL_METHOD *func_name(void) \
{ \
static const SSL_METHOD func_name##_data= { \
version, \
flags, \
mask, \
dtls1_new, \
dtls1_clear, \
dtls1_free, \
s_accept, \
s_connect, \
ssl3_read, \
ssl3_peek, \
ssl3_write, \
dtls1_shutdown, \
ssl3_renegotiate, \
ssl3_renegotiate_check, \
dtls1_read_bytes, \
dtls1_write_app_data_bytes, \
dtls1_dispatch_alert, \
dtls1_ctrl, \
ssl3_ctx_ctrl, \
ssl3_get_cipher_by_char, \
ssl3_put_cipher_by_char, \
ssl3_pending, \
ssl3_num_ciphers, \
ssl3_get_cipher, \
dtls1_default_timeout, \
&enc_data, \
ssl_undefined_void_function, \
ssl3_callback_ctrl, \
ssl3_ctx_callback_ctrl, \
}; \
return &func_name##_data; \
}
struct openssl_ssl_test_functions {
int (*p_ssl_init_wbio_buffer) (SSL *s);
int (*p_ssl3_setup_buffers) (SSL *s);
};
const char *ssl_protocol_to_string(int version);
/* Returns true if certificate and private key for 'idx' are present */
static ossl_inline int ssl_has_cert(const SSL *s, int idx)
{
if (idx < 0 || idx >= SSL_PKEY_NUM)
return 0;
return s->cert->pkeys[idx].x509 != NULL
&& s->cert->pkeys[idx].privatekey != NULL;
}
static ossl_inline void tls1_get_peer_groups(SSL *s, const uint16_t **pgroups,
size_t *pgroupslen)
{
*pgroups = s->session->ext.supportedgroups;
*pgroupslen = s->session->ext.supportedgroups_len;
}
# ifndef OPENSSL_UNIT_TEST
__owur int ssl_read_internal(SSL *s, void *buf, size_t num, size_t *readbytes);
__owur int ssl_write_internal(SSL *s, const void *buf, size_t num, size_t *written);
void ssl_clear_cipher_ctx(SSL *s);
int ssl_clear_bad_session(SSL *s);
__owur CERT *ssl_cert_new(void);
__owur CERT *ssl_cert_dup(CERT *cert);
void ssl_cert_clear_certs(CERT *c);
void ssl_cert_free(CERT *c);
__owur int ssl_generate_session_id(SSL *s, SSL_SESSION *ss);
__owur int ssl_get_new_session(SSL *s, int session);
__owur SSL_SESSION *lookup_sess_in_cache(SSL *s, const unsigned char *sess_id,
size_t sess_id_len);
__owur int ssl_get_prev_session(SSL *s, CLIENTHELLO_MSG *hello);
__owur SSL_SESSION *ssl_session_dup(SSL_SESSION *src, int ticket);
__owur int ssl_cipher_id_cmp(const SSL_CIPHER *a, const SSL_CIPHER *b);
DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id);
__owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
const SSL_CIPHER *const *bp);
__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
STACK_OF(SSL_CIPHER) **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
const char *rule_str,
CERT *c);
__owur int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format);
__owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
STACK_OF(SSL_CIPHER) **skp,
STACK_OF(SSL_CIPHER) **scsvs, int sslv2format,
int fatal);
void ssl_update_cache(SSL *s, int mode);
__owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
const EVP_MD **md, int *mac_pkey_type,
size_t *mac_secret_size, SSL_COMP **comp,
int use_etm);
__owur int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
size_t *int_overhead, size_t *blocksize,
size_t *ext_overhead);
__owur int ssl_cert_is_disabled(size_t idx);
__owur const SSL_CIPHER *ssl_get_cipher_by_char(SSL *ssl,
const unsigned char *ptr,
int all);
__owur int ssl_cert_set0_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain);
__owur int ssl_cert_set1_chain(SSL *s, SSL_CTX *ctx, STACK_OF(X509) *chain);
__owur int ssl_cert_add0_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x);
__owur int ssl_cert_add1_chain_cert(SSL *s, SSL_CTX *ctx, X509 *x);
__owur int ssl_cert_select_current(CERT *c, X509 *x);
__owur int ssl_cert_set_current(CERT *c, long arg);
void ssl_cert_set_cert_cb(CERT *c, int (*cb) (SSL *ssl, void *arg), void *arg);
__owur int ssl_verify_cert_chain(SSL *s, STACK_OF(X509) *sk);
__owur int ssl_build_cert_chain(SSL *s, SSL_CTX *ctx, int flags);
__owur int ssl_cert_set_cert_store(CERT *c, X509_STORE *store, int chain,
int ref);
__owur int ssl_security(const SSL *s, int op, int bits, int nid, void *other);
__owur int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid,
void *other);
__owur int ssl_cert_lookup_by_nid(int nid, size_t *pidx);
__owur const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk,
size_t *pidx);
__owur const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx);
int ssl_undefined_function(SSL *s);
__owur int ssl_undefined_void_function(void);
__owur int ssl_undefined_const_function(const SSL *s);
__owur int ssl_get_server_cert_serverinfo(SSL *s,
const unsigned char **serverinfo,
size_t *serverinfo_length);
void ssl_set_masks(SSL *s);
__owur STACK_OF(SSL_CIPHER) *ssl_get_ciphers_by_id(SSL *s);
__owur int ssl_x509err2alert(int type);
void ssl_sort_cipher_list(void);
int ssl_load_ciphers(void);
__owur int ssl_fill_hello_random(SSL *s, int server, unsigned char *field,
size_t len, DOWNGRADE dgrd);
__owur int ssl_generate_master_secret(SSL *s, unsigned char *pms, size_t pmslen,
int free_pms);
__owur EVP_PKEY *ssl_generate_pkey(EVP_PKEY *pm);
__owur int ssl_derive(SSL *s, EVP_PKEY *privkey, EVP_PKEY *pubkey,
int genmaster);
__owur EVP_PKEY *ssl_dh_to_pkey(DH *dh);
__owur unsigned int ssl_get_max_send_fragment(const SSL *ssl);
__owur unsigned int ssl_get_split_send_fragment(const SSL *ssl);
__owur const SSL_CIPHER *ssl3_get_cipher_by_id(uint32_t id);
__owur const SSL_CIPHER *ssl3_get_cipher_by_std_name(const char *stdname);
__owur const SSL_CIPHER *ssl3_get_cipher_by_char(const unsigned char *p);
__owur int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt,
size_t *len);
int ssl3_init_finished_mac(SSL *s);
__owur int ssl3_setup_key_block(SSL *s);
__owur int ssl3_change_cipher_state(SSL *s, int which);
void ssl3_cleanup_key_block(SSL *s);
__owur int ssl3_do_write(SSL *s, int type);
int ssl3_send_alert(SSL *s, int level, int desc);
__owur int ssl3_generate_master_secret(SSL *s, unsigned char *out,
unsigned char *p, size_t len,
size_t *secret_size);
__owur int ssl3_get_req_cert_type(SSL *s, WPACKET *pkt);
__owur int ssl3_num_ciphers(void);
__owur const SSL_CIPHER *ssl3_get_cipher(unsigned int u);
int ssl3_renegotiate(SSL *ssl);
int ssl3_renegotiate_check(SSL *ssl, int initok);
__owur int ssl3_dispatch_alert(SSL *s);
__owur size_t ssl3_final_finish_mac(SSL *s, const char *sender, size_t slen,
unsigned char *p);
__owur int ssl3_finish_mac(SSL *s, const unsigned char *buf, size_t len);
void ssl3_free_digest_list(SSL *s);
__owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt,
CERT_PKEY *cpk);
__owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,
STACK_OF(SSL_CIPHER) *clnt,
STACK_OF(SSL_CIPHER) *srvr);
__owur int ssl3_digest_cached_records(SSL *s, int keep);
__owur int ssl3_new(SSL *s);
void ssl3_free(SSL *s);
__owur int ssl3_read(SSL *s, void *buf, size_t len, size_t *readbytes);
__owur int ssl3_peek(SSL *s, void *buf, size_t len, size_t *readbytes);
__owur int ssl3_write(SSL *s, const void *buf, size_t len, size_t *written);
__owur int ssl3_shutdown(SSL *s);
int ssl3_clear(SSL *s);
__owur long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg);
__owur long ssl3_ctx_ctrl(SSL_CTX *s, int cmd, long larg, void *parg);
__owur long ssl3_callback_ctrl(SSL *s, int cmd, void (*fp) (void));
__owur long ssl3_ctx_callback_ctrl(SSL_CTX *s, int cmd, void (*fp) (void));
__owur int ssl3_do_change_cipher_spec(SSL *ssl);
__owur long ssl3_default_timeout(void);
__owur int ssl3_set_handshake_header(SSL *s, WPACKET *pkt, int htype);
__owur int tls_close_construct_packet(SSL *s, WPACKET *pkt, int htype);
__owur int tls_setup_handshake(SSL *s);
__owur int dtls1_set_handshake_header(SSL *s, WPACKET *pkt, int htype);
__owur int dtls1_close_construct_packet(SSL *s, WPACKET *pkt, int htype);
__owur int ssl3_handshake_write(SSL *s);
__owur int ssl_allow_compression(SSL *s);
__owur int ssl_version_supported(const SSL *s, int version,
const SSL_METHOD **meth);
__owur int ssl_set_client_hello_version(SSL *s);
__owur int ssl_check_version_downgrade(SSL *s);
__owur int ssl_set_version_bound(int method_version, int version, int *bound);
__owur int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello,
DOWNGRADE *dgrd);
__owur int ssl_choose_client_version(SSL *s, int version,
RAW_EXTENSION *extensions);
__owur int ssl_get_min_max_version(const SSL *s, int *min_version,
int *max_version, int *real_max);
__owur long tls1_default_timeout(void);
__owur int dtls1_do_write(SSL *s, int type);
void dtls1_set_message_header(SSL *s,
unsigned char mt,
size_t len,
size_t frag_off, size_t frag_len);
int dtls1_write_app_data_bytes(SSL *s, int type, const void *buf_, size_t len,
size_t *written);
__owur int dtls1_read_failed(SSL *s, int code);
__owur int dtls1_buffer_message(SSL *s, int ccs);
__owur int dtls1_retransmit_message(SSL *s, unsigned short seq, int *found);
__owur int dtls1_get_queue_priority(unsigned short seq, int is_ccs);
int dtls1_retransmit_buffered_messages(SSL *s);
void dtls1_clear_received_buffer(SSL *s);
void dtls1_clear_sent_buffer(SSL *s);
void dtls1_get_message_header(unsigned char *data,
struct hm_header_st *msg_hdr);
__owur long dtls1_default_timeout(void);
__owur struct timeval *dtls1_get_timeout(SSL *s, struct timeval *timeleft);
__owur int dtls1_check_timeout_num(SSL *s);
__owur int dtls1_handle_timeout(SSL *s);
void dtls1_start_timer(SSL *s);
void dtls1_stop_timer(SSL *s);
__owur int dtls1_is_timer_expired(SSL *s);
void dtls1_double_timeout(SSL *s);
__owur int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie,
size_t cookie_len);
__owur size_t dtls1_min_mtu(SSL *s);
void dtls1_hm_fragment_free(hm_fragment *frag);
__owur int dtls1_query_mtu(SSL *s);
__owur int tls1_new(SSL *s);
void tls1_free(SSL *s);
int tls1_clear(SSL *s);
__owur int dtls1_new(SSL *s);
void dtls1_free(SSL *s);
int dtls1_clear(SSL *s);
long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg);
__owur int dtls1_shutdown(SSL *s);
__owur int dtls1_dispatch_alert(SSL *s);
__owur int ssl_init_wbio_buffer(SSL *s);
int ssl_free_wbio_buffer(SSL *s);
__owur int tls1_change_cipher_state(SSL *s, int which);
__owur int tls1_setup_key_block(SSL *s);
__owur size_t tls1_final_finish_mac(SSL *s, const char *str, size_t slen,
unsigned char *p);
__owur int tls1_generate_master_secret(SSL *s, unsigned char *out,
unsigned char *p, size_t len,
size_t *secret_size);
__owur int tls13_setup_key_block(SSL *s);
__owur size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen,
unsigned char *p);
__owur int tls13_change_cipher_state(SSL *s, int which);
__owur int tls13_update_key(SSL *s, int send);
__owur int tls13_hkdf_expand(SSL *s, const EVP_MD *md,
const unsigned char *secret,
const unsigned char *label, size_t labellen,
const unsigned char *data, size_t datalen,
unsigned char *out, size_t outlen, int fatal);
__owur int tls13_derive_key(SSL *s, const EVP_MD *md,
const unsigned char *secret, unsigned char *key,
size_t keylen);
__owur int tls13_derive_iv(SSL *s, const EVP_MD *md,
const unsigned char *secret, unsigned char *iv,
size_t ivlen);
__owur int tls13_derive_finishedkey(SSL *s, const EVP_MD *md,
const unsigned char *secret,
unsigned char *fin, size_t finlen);
int tls13_generate_secret(SSL *s, const EVP_MD *md,
const unsigned char *prevsecret,
const unsigned char *insecret,
size_t insecretlen,
unsigned char *outsecret);
__owur int tls13_generate_handshake_secret(SSL *s,
const unsigned char *insecret,
size_t insecretlen);
__owur int tls13_generate_master_secret(SSL *s, unsigned char *out,
unsigned char *prev, size_t prevlen,
size_t *secret_size);
__owur int tls1_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen,
const unsigned char *p, size_t plen,
int use_context);
__owur int tls13_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen,
const unsigned char *context,
size_t contextlen, int use_context);
__owur int tls13_export_keying_material_early(SSL *s, unsigned char *out,
size_t olen, const char *label,
size_t llen,
const unsigned char *context,
size_t contextlen);
__owur int tls1_alert_code(int code);
__owur int tls13_alert_code(int code);
__owur int ssl3_alert_code(int code);
# ifndef OPENSSL_NO_EC
__owur int ssl_check_srvr_ecc_cert_and_alg(X509 *x, SSL *s);
# endif
SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
# ifndef OPENSSL_NO_EC
__owur const TLS_GROUP_INFO *tls1_group_id_lookup(uint16_t curve_id);
__owur int tls1_check_group_id(SSL *s, uint16_t group_id, int check_own_curves);
__owur uint16_t tls1_shared_group(SSL *s, int nmatch);
__owur int tls1_set_groups(uint16_t **pext, size_t *pextlen,
int *curves, size_t ncurves);
__owur int tls1_set_groups_list(uint16_t **pext, size_t *pextlen,
const char *str);
void tls1_get_formatlist(SSL *s, const unsigned char **pformats,
size_t *num_formats);
__owur int tls1_check_ec_tmp_key(SSL *s, unsigned long id);
__owur EVP_PKEY *ssl_generate_pkey_group(SSL *s, uint16_t id);
__owur EVP_PKEY *ssl_generate_param_group(uint16_t id);
# endif /* OPENSSL_NO_EC */
__owur int tls_curve_allowed(SSL *s, uint16_t curve, int op);
void tls1_get_supported_groups(SSL *s, const uint16_t **pgroups,
size_t *pgroupslen);
__owur int tls1_set_server_sigalgs(SSL *s);
__owur SSL_TICKET_STATUS tls_get_ticket_from_client(SSL *s, CLIENTHELLO_MSG *hello,
SSL_SESSION **ret);
__owur SSL_TICKET_STATUS tls_decrypt_ticket(SSL *s, const unsigned char *etick,
size_t eticklen,
const unsigned char *sess_id,
size_t sesslen, SSL_SESSION **psess);
__owur int tls_use_ticket(SSL *s);
void ssl_set_sig_mask(uint32_t *pmask_a, SSL *s, int op);
__owur int tls1_set_sigalgs_list(CERT *c, const char *str, int client);
__owur int tls1_set_raw_sigalgs(CERT *c, const uint16_t *psigs, size_t salglen,
int client);
__owur int tls1_set_sigalgs(CERT *c, const int *salg, size_t salglen,
int client);
int tls1_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain,
int idx);
void tls1_set_cert_validity(SSL *s);
# ifndef OPENSSL_NO_CT
__owur int ssl_validate_ct(SSL *s);
# endif
# ifndef OPENSSL_NO_DH
__owur DH *ssl_get_auto_dh(SSL *s);
# endif
__owur int ssl_security_cert(SSL *s, SSL_CTX *ctx, X509 *x, int vfy, int is_ee);
__owur int ssl_security_cert_chain(SSL *s, STACK_OF(X509) *sk, X509 *ex,
int vfy);
int tls_choose_sigalg(SSL *s, int fatalerrs);
__owur EVP_MD_CTX *ssl_replace_hash(EVP_MD_CTX **hash, const EVP_MD *md);
void ssl_clear_hash_ctx(EVP_MD_CTX **hash);
__owur long ssl_get_algorithm2(SSL *s);
__owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
const uint16_t *psig, size_t psiglen);
__owur int tls1_save_u16(PACKET *pkt, uint16_t **pdest, size_t *pdestlen);
__owur int tls1_save_sigalgs(SSL *s, PACKET *pkt, int cert);
__owur int tls1_process_sigalgs(SSL *s);
__owur int tls1_set_peer_legacy_sigalg(SSL *s, const EVP_PKEY *pkey);
__owur int tls1_lookup_md(const SIGALG_LOOKUP *lu, const EVP_MD **pmd);
__owur size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs);
# ifndef OPENSSL_NO_EC
__owur int tls_check_sigalg_curve(const SSL *s, int curve);
# endif
__owur int tls12_check_peer_sigalg(SSL *s, uint16_t, EVP_PKEY *pkey);
__owur int ssl_set_client_disabled(SSL *s);
__owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op, int echde);
__owur int ssl_handshake_hash(SSL *s, unsigned char *out, size_t outlen,
size_t *hashlen);
__owur const EVP_MD *ssl_md(int idx);
__owur const EVP_MD *ssl_handshake_md(SSL *s);
__owur const EVP_MD *ssl_prf_md(SSL *s);
/*
* ssl_log_rsa_client_key_exchange logs |premaster| to the SSL_CTX associated
* with |ssl|, if logging is enabled. It returns one on success and zero on
* failure. The entry is identified by the first 8 bytes of
* |encrypted_premaster|.
*/
__owur int ssl_log_rsa_client_key_exchange(SSL *ssl,
const uint8_t *encrypted_premaster,
size_t encrypted_premaster_len,
const uint8_t *premaster,
size_t premaster_len);
/*
* ssl_log_secret logs |secret| to the SSL_CTX associated with |ssl|, if
* logging is available. It returns one on success and zero on failure. It tags
* the entry with |label|.
*/
__owur int ssl_log_secret(SSL *ssl, const char *label,
const uint8_t *secret, size_t secret_len);
#define MASTER_SECRET_LABEL "CLIENT_RANDOM"
#define CLIENT_EARLY_LABEL "CLIENT_EARLY_TRAFFIC_SECRET"
#define CLIENT_HANDSHAKE_LABEL "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
#define SERVER_HANDSHAKE_LABEL "SERVER_HANDSHAKE_TRAFFIC_SECRET"
#define CLIENT_APPLICATION_LABEL "CLIENT_TRAFFIC_SECRET_0"
#define SERVER_APPLICATION_LABEL "SERVER_TRAFFIC_SECRET_0"
#define EARLY_EXPORTER_SECRET_LABEL "EARLY_EXPORTER_SECRET"
#define EXPORTER_SECRET_LABEL "EXPORTER_SECRET"
/* s3_cbc.c */
__owur char ssl3_cbc_record_digest_supported(const EVP_MD_CTX *ctx);
__owur int ssl3_cbc_digest_record(const EVP_MD_CTX *ctx,
unsigned char *md_out,
size_t *md_out_size,
const unsigned char header[13],
const unsigned char *data,
size_t data_plus_mac_size,
size_t data_plus_mac_plus_padding_size,
const unsigned char *mac_secret,
size_t mac_secret_length, char is_sslv3);
__owur int srp_generate_server_master_secret(SSL *s);
__owur int srp_generate_client_master_secret(SSL *s);
__owur int srp_verify_server_param(SSL *s);
/* statem/statem_srvr.c */
__owur int send_certificate_request(SSL *s);
/* statem/extensions_cust.c */
custom_ext_method *custom_ext_find(const custom_ext_methods *exts,
ENDPOINT role, unsigned int ext_type,
size_t *idx);
void custom_ext_init(custom_ext_methods *meths);
__owur int custom_ext_parse(SSL *s, unsigned int context, unsigned int ext_type,
const unsigned char *ext_data, size_t ext_size,
X509 *x, size_t chainidx);
__owur int custom_ext_add(SSL *s, int context, WPACKET *pkt, X509 *x,
size_t chainidx, int maxversion);
__owur int custom_exts_copy(custom_ext_methods *dst,
const custom_ext_methods *src);
__owur int custom_exts_copy_flags(custom_ext_methods *dst,
const custom_ext_methods *src);
void custom_exts_free(custom_ext_methods *exts);
void ssl_comp_free_compression_methods_int(void);
/* ssl_mcnf.c */
void ssl_ctx_system_config(SSL_CTX *ctx);
# else /* OPENSSL_UNIT_TEST */
# define ssl_init_wbio_buffer SSL_test_functions()->p_ssl_init_wbio_buffer
# define ssl3_setup_buffers SSL_test_functions()->p_ssl3_setup_buffers
# endif
#endif
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index c3d3441a1c63..b27608cbb199 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -1,1700 +1,1698 @@
/*
* Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <string.h>
#include "internal/nelem.h"
#include "internal/cryptlib.h"
#include "../ssl_locl.h"
#include "statem_locl.h"
#include "internal/cryptlib.h"
static int final_renegotiate(SSL *s, unsigned int context, int sent);
static int init_server_name(SSL *s, unsigned int context);
static int final_server_name(SSL *s, unsigned int context, int sent);
#ifndef OPENSSL_NO_EC
static int final_ec_pt_formats(SSL *s, unsigned int context, int sent);
#endif
static int init_session_ticket(SSL *s, unsigned int context);
#ifndef OPENSSL_NO_OCSP
static int init_status_request(SSL *s, unsigned int context);
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
static int init_npn(SSL *s, unsigned int context);
#endif
static int init_alpn(SSL *s, unsigned int context);
static int final_alpn(SSL *s, unsigned int context, int sent);
static int init_sig_algs_cert(SSL *s, unsigned int context);
static int init_sig_algs(SSL *s, unsigned int context);
static int init_certificate_authorities(SSL *s, unsigned int context);
static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
unsigned int context,
X509 *x,
size_t chainidx);
static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx);
#ifndef OPENSSL_NO_SRP
static int init_srp(SSL *s, unsigned int context);
#endif
static int init_etm(SSL *s, unsigned int context);
static int init_ems(SSL *s, unsigned int context);
static int final_ems(SSL *s, unsigned int context, int sent);
static int init_psk_kex_modes(SSL *s, unsigned int context);
#ifndef OPENSSL_NO_EC
static int final_key_share(SSL *s, unsigned int context, int sent);
#endif
#ifndef OPENSSL_NO_SRTP
static int init_srtp(SSL *s, unsigned int context);
#endif
static int final_sig_algs(SSL *s, unsigned int context, int sent);
static int final_early_data(SSL *s, unsigned int context, int sent);
static int final_maxfragmentlen(SSL *s, unsigned int context, int sent);
static int init_post_handshake_auth(SSL *s, unsigned int context);
/* Structure to define a built-in extension */
typedef struct extensions_definition_st {
/* The defined type for the extension */
unsigned int type;
/*
* The context that this extension applies to, e.g. what messages and
* protocol versions
*/
unsigned int context;
/*
* Initialise extension before parsing. Always called for relevant contexts
* even if extension not present
*/
int (*init)(SSL *s, unsigned int context);
/* Parse extension sent from client to server */
int (*parse_ctos)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
/* Parse extension send from server to client */
int (*parse_stoc)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx);
/* Construct extension sent from server to client */
EXT_RETURN (*construct_stoc)(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
/* Construct extension sent from client to server */
EXT_RETURN (*construct_ctos)(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
/*
* Finalise extension after parsing. Always called where an extensions was
* initialised even if the extension was not present. |sent| is set to 1 if
* the extension was seen, or 0 otherwise.
*/
int (*final)(SSL *s, unsigned int context, int sent);
} EXTENSION_DEFINITION;
/*
* Definitions of all built-in extensions. NOTE: Changes in the number or order
* of these extensions should be mirrored with equivalent changes to the
* indexes ( TLSEXT_IDX_* ) defined in ssl_locl.h.
* Each extension has an initialiser, a client and
* server side parser and a finaliser. The initialiser is called (if the
* extension is relevant to the given context) even if we did not see the
* extension in the message that we received. The parser functions are only
* called if we see the extension in the message. The finalisers are always
* called if the initialiser was called.
* There are also server and client side constructor functions which are always
* called during message construction if the extension is relevant for the
* given context.
* The initialisation, parsing, finalisation and construction functions are
* always called in the order defined in this list. Some extensions may depend
* on others having been processed first, so the order of this list is
* significant.
* The extension context is defined by a series of flags which specify which
* messages the extension is relevant to. These flags also specify whether the
* extension is relevant to a particular protocol or protocol version.
*
* TODO(TLS1.3): Make sure we have a test to check the consistency of these
*
* NOTE: WebSphere Application Server 7+ cannot handle empty extensions at
* the end, keep these extensions before signature_algorithm.
*/
#define INVALID_EXTENSION { 0x10000, 0, NULL, NULL, NULL, NULL, NULL, NULL }
static const EXTENSION_DEFINITION ext_defs[] = {
{
TLSEXT_TYPE_renegotiate,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_SSL3_ALLOWED | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
NULL, tls_parse_ctos_renegotiate, tls_parse_stoc_renegotiate,
tls_construct_stoc_renegotiate, tls_construct_ctos_renegotiate,
final_renegotiate
},
{
TLSEXT_TYPE_server_name,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
init_server_name,
tls_parse_ctos_server_name, tls_parse_stoc_server_name,
tls_construct_stoc_server_name, tls_construct_ctos_server_name,
final_server_name
},
{
TLSEXT_TYPE_max_fragment_length,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
NULL, tls_parse_ctos_maxfragmentlen, tls_parse_stoc_maxfragmentlen,
tls_construct_stoc_maxfragmentlen, tls_construct_ctos_maxfragmentlen,
final_maxfragmentlen
},
#ifndef OPENSSL_NO_SRP
{
TLSEXT_TYPE_srp,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_AND_BELOW_ONLY,
init_srp, tls_parse_ctos_srp, NULL, NULL, tls_construct_ctos_srp, NULL
},
#else
INVALID_EXTENSION,
#endif
#ifndef OPENSSL_NO_EC
{
TLSEXT_TYPE_ec_point_formats,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
NULL, tls_parse_ctos_ec_pt_formats, tls_parse_stoc_ec_pt_formats,
tls_construct_stoc_ec_pt_formats, tls_construct_ctos_ec_pt_formats,
final_ec_pt_formats
},
{
/*
* "supported_groups" is spread across several specifications.
* It was originally specified as "elliptic_curves" in RFC 4492,
* and broadened to include named FFDH groups by RFC 7919.
* Both RFCs 4492 and 7919 do not include a provision for the server
* to indicate to the client the complete list of groups supported
* by the server, with the server instead just indicating the
* selected group for this connection in the ServerKeyExchange
* message. TLS 1.3 adds a scheme for the server to indicate
* to the client its list of supported groups in the
* EncryptedExtensions message, but none of the relevant
* specifications permit sending supported_groups in the ServerHello.
* Nonetheless (possibly due to the close proximity to the
* "ec_point_formats" extension, which is allowed in the ServerHello),
* there are several servers that send this extension in the
* ServerHello anyway. Up to and including the 1.1.0 release,
* we did not check for the presence of nonpermitted extensions,
* so to avoid a regression, we must permit this extension in the
* TLS 1.2 ServerHello as well.
*
* Note that there is no tls_parse_stoc_supported_groups function,
* so we do not perform any additional parsing, validation, or
* processing on the server's group list -- this is just a minimal
* change to preserve compatibility with these misbehaving servers.
*/
TLSEXT_TYPE_supported_groups,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
| SSL_EXT_TLS1_2_SERVER_HELLO,
NULL, tls_parse_ctos_supported_groups, NULL,
tls_construct_stoc_supported_groups,
tls_construct_ctos_supported_groups, NULL
},
#else
INVALID_EXTENSION,
INVALID_EXTENSION,
#endif
{
TLSEXT_TYPE_session_ticket,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
init_session_ticket, tls_parse_ctos_session_ticket,
tls_parse_stoc_session_ticket, tls_construct_stoc_session_ticket,
tls_construct_ctos_session_ticket, NULL
},
#ifndef OPENSSL_NO_OCSP
{
TLSEXT_TYPE_status_request,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
init_status_request, tls_parse_ctos_status_request,
tls_parse_stoc_status_request, tls_construct_stoc_status_request,
tls_construct_ctos_status_request, NULL
},
#else
INVALID_EXTENSION,
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
{
TLSEXT_TYPE_next_proto_neg,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
init_npn, tls_parse_ctos_npn, tls_parse_stoc_npn,
tls_construct_stoc_next_proto_neg, tls_construct_ctos_npn, NULL
},
#else
INVALID_EXTENSION,
#endif
{
/*
* Must appear in this list after server_name so that finalisation
* happens after server_name callbacks
*/
TLSEXT_TYPE_application_layer_protocol_negotiation,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
init_alpn, tls_parse_ctos_alpn, tls_parse_stoc_alpn,
tls_construct_stoc_alpn, tls_construct_ctos_alpn, final_alpn
},
#ifndef OPENSSL_NO_SRTP
{
TLSEXT_TYPE_use_srtp,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS | SSL_EXT_DTLS_ONLY,
init_srtp, tls_parse_ctos_use_srtp, tls_parse_stoc_use_srtp,
tls_construct_stoc_use_srtp, tls_construct_ctos_use_srtp, NULL
},
#else
INVALID_EXTENSION,
#endif
{
TLSEXT_TYPE_encrypt_then_mac,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
init_etm, tls_parse_ctos_etm, tls_parse_stoc_etm,
tls_construct_stoc_etm, tls_construct_ctos_etm, NULL
},
#ifndef OPENSSL_NO_CT
{
TLSEXT_TYPE_signed_certificate_timestamp,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_CERTIFICATE | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
NULL,
/*
* No server side support for this, but can be provided by a custom
* extension. This is an exception to the rule that custom extensions
* cannot override built in ones.
*/
NULL, tls_parse_stoc_sct, NULL, tls_construct_ctos_sct, NULL
},
#else
INVALID_EXTENSION,
#endif
{
TLSEXT_TYPE_extended_master_secret,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
init_ems, tls_parse_ctos_ems, tls_parse_stoc_ems,
tls_construct_stoc_ems, tls_construct_ctos_ems, final_ems
},
{
TLSEXT_TYPE_signature_algorithms_cert,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
init_sig_algs_cert, tls_parse_ctos_sig_algs_cert,
tls_parse_ctos_sig_algs_cert,
/* We do not generate signature_algorithms_cert at present. */
NULL, NULL, NULL
},
{
TLSEXT_TYPE_post_handshake_auth,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ONLY,
init_post_handshake_auth,
tls_parse_ctos_post_handshake_auth, NULL,
NULL, tls_construct_ctos_post_handshake_auth,
NULL,
},
{
TLSEXT_TYPE_signature_algorithms,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
init_sig_algs, tls_parse_ctos_sig_algs,
tls_parse_ctos_sig_algs, tls_construct_ctos_sig_algs,
tls_construct_ctos_sig_algs, final_sig_algs
},
{
TLSEXT_TYPE_supported_versions,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
| SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY,
NULL,
/* Processed inline as part of version selection */
NULL, tls_parse_stoc_supported_versions,
tls_construct_stoc_supported_versions,
tls_construct_ctos_supported_versions, NULL
},
{
TLSEXT_TYPE_psk_kex_modes,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS_IMPLEMENTATION_ONLY
| SSL_EXT_TLS1_3_ONLY,
init_psk_kex_modes, tls_parse_ctos_psk_kex_modes, NULL, NULL,
tls_construct_ctos_psk_kex_modes, NULL
},
#ifndef OPENSSL_NO_EC
{
/*
* Must be in this list after supported_groups. We need that to have
* been parsed before we do this one.
*/
TLSEXT_TYPE_key_share,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
| SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST | SSL_EXT_TLS_IMPLEMENTATION_ONLY
| SSL_EXT_TLS1_3_ONLY,
NULL, tls_parse_ctos_key_share, tls_parse_stoc_key_share,
tls_construct_stoc_key_share, tls_construct_ctos_key_share,
final_key_share
},
#endif
{
/* Must be after key_share */
TLSEXT_TYPE_cookie,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
| SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
NULL, tls_parse_ctos_cookie, tls_parse_stoc_cookie,
tls_construct_stoc_cookie, tls_construct_ctos_cookie, NULL
},
{
/*
* Special unsolicited ServerHello extension only used when
* SSL_OP_CRYPTOPRO_TLSEXT_BUG is set. We allow it in a ClientHello but
* ignore it.
*/
TLSEXT_TYPE_cryptopro_bug,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_2_AND_BELOW_ONLY,
NULL, NULL, NULL, tls_construct_stoc_cryptopro_bug, NULL, NULL
},
{
TLSEXT_TYPE_early_data,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
| SSL_EXT_TLS1_3_NEW_SESSION_TICKET | SSL_EXT_TLS1_3_ONLY,
NULL, tls_parse_ctos_early_data, tls_parse_stoc_early_data,
tls_construct_stoc_early_data, tls_construct_ctos_early_data,
final_early_data
},
{
TLSEXT_TYPE_certificate_authorities,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
| SSL_EXT_TLS1_3_ONLY,
init_certificate_authorities,
tls_parse_certificate_authorities, tls_parse_certificate_authorities,
tls_construct_certificate_authorities,
tls_construct_certificate_authorities, NULL,
},
{
/* Must be immediately before pre_shared_key */
TLSEXT_TYPE_padding,
SSL_EXT_CLIENT_HELLO,
NULL,
/* We send this, but don't read it */
NULL, NULL, NULL, tls_construct_ctos_padding, NULL
},
{
/* Required by the TLSv1.3 spec to always be the last extension */
TLSEXT_TYPE_psk,
SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_3_SERVER_HELLO
| SSL_EXT_TLS_IMPLEMENTATION_ONLY | SSL_EXT_TLS1_3_ONLY,
NULL, tls_parse_ctos_psk, tls_parse_stoc_psk, tls_construct_stoc_psk,
tls_construct_ctos_psk, NULL
}
};
/* Check whether an extension's context matches the current context */
static int validate_context(SSL *s, unsigned int extctx, unsigned int thisctx)
{
/* Check we're allowed to use this extension in this context */
if ((thisctx & extctx) == 0)
return 0;
if (SSL_IS_DTLS(s)) {
if ((extctx & SSL_EXT_TLS_ONLY) != 0)
return 0;
} else if ((extctx & SSL_EXT_DTLS_ONLY) != 0) {
return 0;
}
return 1;
}
int tls_validate_all_contexts(SSL *s, unsigned int thisctx, RAW_EXTENSION *exts)
{
size_t i, num_exts, builtin_num = OSSL_NELEM(ext_defs), offset;
RAW_EXTENSION *thisext;
unsigned int context;
ENDPOINT role = ENDPOINT_BOTH;
if ((thisctx & SSL_EXT_CLIENT_HELLO) != 0)
role = ENDPOINT_SERVER;
else if ((thisctx & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
role = ENDPOINT_CLIENT;
/* Calculate the number of extensions in the extensions list */
num_exts = builtin_num + s->cert->custext.meths_count;
for (thisext = exts, i = 0; i < num_exts; i++, thisext++) {
if (!thisext->present)
continue;
if (i < builtin_num) {
context = ext_defs[i].context;
} else {
custom_ext_method *meth = NULL;
meth = custom_ext_find(&s->cert->custext, role, thisext->type,
&offset);
if (!ossl_assert(meth != NULL))
return 0;
context = meth->context;
}
if (!validate_context(s, context, thisctx))
return 0;
}
return 1;
}
/*
* Verify whether we are allowed to use the extension |type| in the current
* |context|. Returns 1 to indicate the extension is allowed or unknown or 0 to
* indicate the extension is not allowed. If returning 1 then |*found| is set to
* the definition for the extension we found.
*/
static int verify_extension(SSL *s, unsigned int context, unsigned int type,
custom_ext_methods *meths, RAW_EXTENSION *rawexlist,
RAW_EXTENSION **found)
{
size_t i;
size_t builtin_num = OSSL_NELEM(ext_defs);
const EXTENSION_DEFINITION *thisext;
for (i = 0, thisext = ext_defs; i < builtin_num; i++, thisext++) {
if (type == thisext->type) {
if (!validate_context(s, thisext->context, context))
return 0;
*found = &rawexlist[i];
return 1;
}
}
/* Check the custom extensions */
if (meths != NULL) {
size_t offset = 0;
ENDPOINT role = ENDPOINT_BOTH;
custom_ext_method *meth = NULL;
if ((context & SSL_EXT_CLIENT_HELLO) != 0)
role = ENDPOINT_SERVER;
else if ((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0)
role = ENDPOINT_CLIENT;
meth = custom_ext_find(meths, role, type, &offset);
if (meth != NULL) {
if (!validate_context(s, meth->context, context))
return 0;
*found = &rawexlist[offset + builtin_num];
return 1;
}
}
/* Unknown extension. We allow it */
*found = NULL;
return 1;
}
/*
* Check whether the context defined for an extension |extctx| means whether
* the extension is relevant for the current context |thisctx| or not. Returns
* 1 if the extension is relevant for this context, and 0 otherwise
*/
int extension_is_relevant(SSL *s, unsigned int extctx, unsigned int thisctx)
{
int is_tls13;
/*
* For HRR we haven't selected the version yet but we know it will be
* TLSv1.3
*/
if ((thisctx & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
is_tls13 = 1;
else
is_tls13 = SSL_IS_TLS13(s);
if ((SSL_IS_DTLS(s)
&& (extctx & SSL_EXT_TLS_IMPLEMENTATION_ONLY) != 0)
|| (s->version == SSL3_VERSION
&& (extctx & SSL_EXT_SSL3_ALLOWED) == 0)
/*
* Note that SSL_IS_TLS13() means "TLS 1.3 has been negotiated",
* which is never true when generating the ClientHello.
* However, version negotiation *has* occurred by the time the
* ClientHello extensions are being parsed.
* Be careful to allow TLS 1.3-only extensions when generating
* the ClientHello.
*/
|| (is_tls13 && (extctx & SSL_EXT_TLS1_2_AND_BELOW_ONLY) != 0)
|| (!is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0
&& (thisctx & SSL_EXT_CLIENT_HELLO) == 0)
|| (s->server && !is_tls13 && (extctx & SSL_EXT_TLS1_3_ONLY) != 0)
|| (s->hit && (extctx & SSL_EXT_IGNORE_ON_RESUMPTION) != 0))
return 0;
return 1;
}
/*
* Gather a list of all the extensions from the data in |packet]. |context|
* tells us which message this extension is for. The raw extension data is
* stored in |*res| on success. We don't actually process the content of the
* extensions yet, except to check their types. This function also runs the
* initialiser functions for all known extensions if |init| is nonzero (whether
* we have collected them or not). If successful the caller is responsible for
* freeing the contents of |*res|.
*
* Per http://tools.ietf.org/html/rfc5246#section-7.4.1.4, there may not be
* more than one extension of the same type in a ClientHello or ServerHello.
* This function returns 1 if all extensions are unique and we have parsed their
* types, and 0 if the extensions contain duplicates, could not be successfully
* found, or an internal error occurred. We only check duplicates for
* extensions that we know about. We ignore others.
*/
int tls_collect_extensions(SSL *s, PACKET *packet, unsigned int context,
RAW_EXTENSION **res, size_t *len, int init)
{
PACKET extensions = *packet;
size_t i = 0;
size_t num_exts;
custom_ext_methods *exts = &s->cert->custext;
RAW_EXTENSION *raw_extensions = NULL;
const EXTENSION_DEFINITION *thisexd;
*res = NULL;
/*
* Initialise server side custom extensions. Client side is done during
* construction of extensions for the ClientHello.
*/
if ((context & SSL_EXT_CLIENT_HELLO) != 0)
custom_ext_init(&s->cert->custext);
num_exts = OSSL_NELEM(ext_defs) + (exts != NULL ? exts->meths_count : 0);
raw_extensions = OPENSSL_zalloc(num_exts * sizeof(*raw_extensions));
if (raw_extensions == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
ERR_R_MALLOC_FAILURE);
return 0;
}
i = 0;
while (PACKET_remaining(&extensions) > 0) {
unsigned int type, idx;
PACKET extension;
RAW_EXTENSION *thisex;
if (!PACKET_get_net_2(&extensions, &type) ||
!PACKET_get_length_prefixed_2(&extensions, &extension)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_COLLECT_EXTENSIONS,
SSL_R_BAD_EXTENSION);
goto err;
}
/*
* Verify this extension is allowed. We only check duplicates for
* extensions that we recognise. We also have a special case for the
* PSK extension, which must be the last one in the ClientHello.
*/
if (!verify_extension(s, context, type, exts, raw_extensions, &thisex)
|| (thisex != NULL && thisex->present == 1)
|| (type == TLSEXT_TYPE_psk
&& (context & SSL_EXT_CLIENT_HELLO) != 0
&& PACKET_remaining(&extensions) != 0)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_COLLECT_EXTENSIONS,
SSL_R_BAD_EXTENSION);
goto err;
}
idx = thisex - raw_extensions;
/*-
* Check that we requested this extension (if appropriate). Requests can
* be sent in the ClientHello and CertificateRequest. Unsolicited
* extensions can be sent in the NewSessionTicket. We only do this for
* the built-in extensions. Custom extensions have a different but
* similar check elsewhere.
* Special cases:
* - The HRR cookie extension is unsolicited
* - The renegotiate extension is unsolicited (the client signals
* support via an SCSV)
* - The signed_certificate_timestamp extension can be provided by a
* custom extension or by the built-in version. We let the extension
* itself handle unsolicited response checks.
*/
if (idx < OSSL_NELEM(ext_defs)
&& (context & (SSL_EXT_CLIENT_HELLO
| SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
| SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) == 0
&& type != TLSEXT_TYPE_cookie
&& type != TLSEXT_TYPE_renegotiate
&& type != TLSEXT_TYPE_signed_certificate_timestamp
&& (s->ext.extflags[idx] & SSL_EXT_FLAG_SENT) == 0
#ifndef OPENSSL_NO_GOST
&& !((context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
&& type == TLSEXT_TYPE_cryptopro_bug)
#endif
) {
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
SSL_F_TLS_COLLECT_EXTENSIONS, SSL_R_UNSOLICITED_EXTENSION);
goto err;
}
if (thisex != NULL) {
thisex->data = extension;
thisex->present = 1;
thisex->type = type;
thisex->received_order = i++;
if (s->ext.debug_cb)
s->ext.debug_cb(s, !s->server, thisex->type,
PACKET_data(&thisex->data),
PACKET_remaining(&thisex->data),
s->ext.debug_arg);
}
}
if (init) {
/*
* Initialise all known extensions relevant to this context,
* whether we have found them or not
*/
for (thisexd = ext_defs, i = 0; i < OSSL_NELEM(ext_defs);
i++, thisexd++) {
if (thisexd->init != NULL && (thisexd->context & context) != 0
&& extension_is_relevant(s, thisexd->context, context)
&& !thisexd->init(s, context)) {
/* SSLfatal() already called */
goto err;
}
}
}
*res = raw_extensions;
if (len != NULL)
*len = num_exts;
return 1;
err:
OPENSSL_free(raw_extensions);
return 0;
}
/*
* Runs the parser for a given extension with index |idx|. |exts| contains the
* list of all parsed extensions previously collected by
* tls_collect_extensions(). The parser is only run if it is applicable for the
* given |context| and the parser has not already been run. If this is for a
* Certificate message, then we also provide the parser with the relevant
* Certificate |x| and its position in the |chainidx| with 0 being the first
* Certificate. Returns 1 on success or 0 on failure. If an extension is not
* present this counted as success.
*/
int tls_parse_extension(SSL *s, TLSEXT_INDEX idx, int context,
RAW_EXTENSION *exts, X509 *x, size_t chainidx)
{
RAW_EXTENSION *currext = &exts[idx];
int (*parser)(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx) = NULL;
/* Skip if the extension is not present */
if (!currext->present)
return 1;
/* Skip if we've already parsed this extension */
if (currext->parsed)
return 1;
currext->parsed = 1;
if (idx < OSSL_NELEM(ext_defs)) {
/* We are handling a built-in extension */
const EXTENSION_DEFINITION *extdef = &ext_defs[idx];
/* Check if extension is defined for our protocol. If not, skip */
if (!extension_is_relevant(s, extdef->context, context))
return 1;
parser = s->server ? extdef->parse_ctos : extdef->parse_stoc;
if (parser != NULL)
return parser(s, &currext->data, context, x, chainidx);
/*
* If the parser is NULL we fall through to the custom extension
* processing
*/
}
/* Parse custom extensions */
return custom_ext_parse(s, context, currext->type,
PACKET_data(&currext->data),
PACKET_remaining(&currext->data),
x, chainidx);
}
/*
* Parse all remaining extensions that have not yet been parsed. Also calls the
* finalisation for all extensions at the end if |fin| is nonzero, whether we
* collected them or not. Returns 1 for success or 0 for failure. If we are
* working on a Certificate message then we also pass the Certificate |x| and
* its position in the |chainidx|, with 0 being the first certificate.
*/
int tls_parse_all_extensions(SSL *s, int context, RAW_EXTENSION *exts, X509 *x,
size_t chainidx, int fin)
{
size_t i, numexts = OSSL_NELEM(ext_defs);
const EXTENSION_DEFINITION *thisexd;
/* Calculate the number of extensions in the extensions list */
numexts += s->cert->custext.meths_count;
/* Parse each extension in turn */
for (i = 0; i < numexts; i++) {
if (!tls_parse_extension(s, i, context, exts, x, chainidx)) {
/* SSLfatal() already called */
return 0;
}
}
if (fin) {
/*
* Finalise all known extensions relevant to this context,
* whether we have found them or not
*/
for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs);
i++, thisexd++) {
if (thisexd->final != NULL && (thisexd->context & context) != 0
&& !thisexd->final(s, context, exts[i].present)) {
/* SSLfatal() already called */
return 0;
}
}
}
return 1;
}
int should_add_extension(SSL *s, unsigned int extctx, unsigned int thisctx,
int max_version)
{
/* Skip if not relevant for our context */
if ((extctx & thisctx) == 0)
return 0;
/* Check if this extension is defined for our protocol. If not, skip */
if (!extension_is_relevant(s, extctx, thisctx)
|| ((extctx & SSL_EXT_TLS1_3_ONLY) != 0
&& (thisctx & SSL_EXT_CLIENT_HELLO) != 0
&& (SSL_IS_DTLS(s) || max_version < TLS1_3_VERSION)))
return 0;
return 1;
}
/*
* Construct all the extensions relevant to the current |context| and write
* them to |pkt|. If this is an extension for a Certificate in a Certificate
* message, then |x| will be set to the Certificate we are handling, and
* |chainidx| will indicate the position in the chainidx we are processing (with
* 0 being the first in the chain). Returns 1 on success or 0 on failure. On a
* failure construction stops at the first extension to fail to construct.
*/
int tls_construct_extensions(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
size_t i;
int min_version, max_version = 0, reason;
const EXTENSION_DEFINITION *thisexd;
if (!WPACKET_start_sub_packet_u16(pkt)
/*
* If extensions are of zero length then we don't even add the
* extensions length bytes to a ClientHello/ServerHello
* (for non-TLSv1.3).
*/
|| ((context &
(SSL_EXT_CLIENT_HELLO | SSL_EXT_TLS1_2_SERVER_HELLO)) != 0
&& !WPACKET_set_flags(pkt,
WPACKET_FLAGS_ABANDON_ON_ZERO_LENGTH))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
ERR_R_INTERNAL_ERROR);
return 0;
}
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
if (reason != 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
reason);
return 0;
}
}
/* Add custom extensions first */
if ((context & SSL_EXT_CLIENT_HELLO) != 0) {
/* On the server side with initialise during ClientHello parsing */
custom_ext_init(&s->cert->custext);
}
if (!custom_ext_add(s, context, pkt, x, chainidx, max_version)) {
/* SSLfatal() already called */
return 0;
}
for (i = 0, thisexd = ext_defs; i < OSSL_NELEM(ext_defs); i++, thisexd++) {
EXT_RETURN (*construct)(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx);
EXT_RETURN ret;
/* Skip if not relevant for our context */
if (!should_add_extension(s, thisexd->context, context, max_version))
continue;
construct = s->server ? thisexd->construct_stoc
: thisexd->construct_ctos;
if (construct == NULL)
continue;
ret = construct(s, pkt, context, x, chainidx);
if (ret == EXT_RETURN_FAIL) {
/* SSLfatal() already called */
return 0;
}
if (ret == EXT_RETURN_SENT
&& (context & (SSL_EXT_CLIENT_HELLO
| SSL_EXT_TLS1_3_CERTIFICATE_REQUEST
| SSL_EXT_TLS1_3_NEW_SESSION_TICKET)) != 0)
s->ext.extflags[i] |= SSL_EXT_FLAG_SENT;
}
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_EXTENSIONS,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
/*
* Built in extension finalisation and initialisation functions. All initialise
* or finalise the associated extension type for the given |context|. For
* finalisers |sent| is set to 1 if we saw the extension during parsing, and 0
* otherwise. These functions return 1 on success or 0 on failure.
*/
static int final_renegotiate(SSL *s, unsigned int context, int sent)
{
if (!s->server) {
/*
* Check if we can connect to a server that doesn't support safe
* renegotiation
*/
if (!(s->options & SSL_OP_LEGACY_SERVER_CONNECT)
&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
&& !sent) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
return 1;
}
/* Need RI if renegotiating */
if (s->renegotiate
&& !(s->options & SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)
&& !sent) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_RENEGOTIATE,
SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED);
return 0;
}
return 1;
}
static int init_server_name(SSL *s, unsigned int context)
{
if (s->server) {
s->servername_done = 0;
OPENSSL_free(s->ext.hostname);
s->ext.hostname = NULL;
}
return 1;
}
static int final_server_name(SSL *s, unsigned int context, int sent)
{
int ret = SSL_TLSEXT_ERR_NOACK;
int altmp = SSL_AD_UNRECOGNIZED_NAME;
int was_ticket = (SSL_get_options(s) & SSL_OP_NO_TICKET) == 0;
if (!ossl_assert(s->ctx != NULL) || !ossl_assert(s->session_ctx != NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (s->ctx->ext.servername_cb != NULL)
ret = s->ctx->ext.servername_cb(s, &altmp,
s->ctx->ext.servername_arg);
else if (s->session_ctx->ext.servername_cb != NULL)
ret = s->session_ctx->ext.servername_cb(s, &altmp,
s->session_ctx->ext.servername_arg);
/*
* For servers, propagate the SNI hostname from the temporary
* storage in the SSL to the persistent SSL_SESSION, now that we
* know we accepted it.
* Clients make this copy when parsing the server's response to
* the extension, which is when they find out that the negotiation
* was successful.
*/
if (s->server) {
/* TODO(OpenSSL1.2) revisit !sent case */
if (sent && ret == SSL_TLSEXT_ERR_OK && (!s->hit || SSL_IS_TLS13(s))) {
/* Only store the hostname in the session if we accepted it. */
OPENSSL_free(s->session->ext.hostname);
s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
if (s->session->ext.hostname == NULL && s->ext.hostname != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
}
}
}
/*
* If we switched contexts (whether here or in the client_hello callback),
* move the sess_accept increment from the session_ctx to the new
* context, to avoid the confusing situation of having sess_accept_good
* exceed sess_accept (zero) for the new context.
*/
if (SSL_IS_FIRST_HANDSHAKE(s) && s->ctx != s->session_ctx) {
tsan_counter(&s->ctx->stats.sess_accept);
tsan_decr(&s->session_ctx->stats.sess_accept);
}
/*
* If we're expecting to send a ticket, and tickets were previously enabled,
* and now tickets are disabled, then turn off expected ticket.
* Also, if this is not a resumption, create a new session ID
*/
if (ret == SSL_TLSEXT_ERR_OK && s->ext.ticket_expected
&& was_ticket && (SSL_get_options(s) & SSL_OP_NO_TICKET) != 0) {
s->ext.ticket_expected = 0;
if (!s->hit) {
SSL_SESSION* ss = SSL_get_session(s);
if (ss != NULL) {
OPENSSL_free(ss->ext.tick);
ss->ext.tick = NULL;
ss->ext.ticklen = 0;
ss->ext.tick_lifetime_hint = 0;
ss->ext.tick_age_add = 0;
- ss->ext.tick_identity = 0;
if (!ssl_generate_session_id(s, ss)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
}
switch (ret) {
case SSL_TLSEXT_ERR_ALERT_FATAL:
SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED);
return 0;
case SSL_TLSEXT_ERR_ALERT_WARNING:
/* TLSv1.3 doesn't have warning alerts so we suppress this */
if (!SSL_IS_TLS13(s))
ssl3_send_alert(s, SSL3_AL_WARNING, altmp);
return 1;
case SSL_TLSEXT_ERR_NOACK:
s->servername_done = 0;
return 1;
default:
return 1;
}
}
#ifndef OPENSSL_NO_EC
static int final_ec_pt_formats(SSL *s, unsigned int context, int sent)
{
unsigned long alg_k, alg_a;
if (s->server)
return 1;
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
/*
* If we are client and using an elliptic curve cryptography cipher
* suite, then if server returns an EC point formats lists extension it
* must contain uncompressed.
*/
if (s->ext.ecpointformats != NULL
&& s->ext.ecpointformats_len > 0
&& s->session->ext.ecpointformats != NULL
&& s->session->ext.ecpointformats_len > 0
&& ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))) {
/* we are using an ECC cipher */
size_t i;
unsigned char *list = s->session->ext.ecpointformats;
for (i = 0; i < s->session->ext.ecpointformats_len; i++) {
if (*list++ == TLSEXT_ECPOINTFORMAT_uncompressed)
break;
}
if (i == s->session->ext.ecpointformats_len) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EC_PT_FORMATS,
SSL_R_TLS_INVALID_ECPOINTFORMAT_LIST);
return 0;
}
}
return 1;
}
#endif
static int init_session_ticket(SSL *s, unsigned int context)
{
if (!s->server)
s->ext.ticket_expected = 0;
return 1;
}
#ifndef OPENSSL_NO_OCSP
static int init_status_request(SSL *s, unsigned int context)
{
if (s->server) {
s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
} else {
/*
* Ensure we get sensible values passed to tlsext_status_cb in the event
* that we don't receive a status message
*/
OPENSSL_free(s->ext.ocsp.resp);
s->ext.ocsp.resp = NULL;
s->ext.ocsp.resp_len = 0;
}
return 1;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
static int init_npn(SSL *s, unsigned int context)
{
s->s3->npn_seen = 0;
return 1;
}
#endif
static int init_alpn(SSL *s, unsigned int context)
{
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = NULL;
s->s3->alpn_selected_len = 0;
if (s->server) {
OPENSSL_free(s->s3->alpn_proposed);
s->s3->alpn_proposed = NULL;
s->s3->alpn_proposed_len = 0;
}
return 1;
}
static int final_alpn(SSL *s, unsigned int context, int sent)
{
if (!s->server && !sent && s->session->ext.alpn_selected != NULL)
s->ext.early_data_ok = 0;
if (!s->server || !SSL_IS_TLS13(s))
return 1;
/*
* Call alpn_select callback if needed. Has to be done after SNI and
* cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
* we also have to do this before we decide whether to accept early_data.
* In TLSv1.3 we've already negotiated our cipher so we do this call now.
* For < TLSv1.3 we defer it until after cipher negotiation.
*
* On failure SSLfatal() already called.
*/
return tls_handle_alpn(s);
}
static int init_sig_algs(SSL *s, unsigned int context)
{
/* Clear any signature algorithms extension received */
OPENSSL_free(s->s3->tmp.peer_sigalgs);
s->s3->tmp.peer_sigalgs = NULL;
return 1;
}
static int init_sig_algs_cert(SSL *s, unsigned int context)
{
/* Clear any signature algorithms extension received */
OPENSSL_free(s->s3->tmp.peer_cert_sigalgs);
s->s3->tmp.peer_cert_sigalgs = NULL;
return 1;
}
#ifndef OPENSSL_NO_SRP
static int init_srp(SSL *s, unsigned int context)
{
OPENSSL_free(s->srp_ctx.login);
s->srp_ctx.login = NULL;
return 1;
}
#endif
static int init_etm(SSL *s, unsigned int context)
{
s->ext.use_etm = 0;
return 1;
}
static int init_ems(SSL *s, unsigned int context)
{
if (!s->server)
s->s3->flags &= ~TLS1_FLAGS_RECEIVED_EXTMS;
return 1;
}
static int final_ems(SSL *s, unsigned int context, int sent)
{
if (!s->server && s->hit) {
/*
* Check extended master secret extension is consistent with
* original session.
*/
if (!(s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) !=
!(s->session->flags & SSL_SESS_FLAG_EXTMS)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_FINAL_EMS,
SSL_R_INCONSISTENT_EXTMS);
return 0;
}
}
return 1;
}
static int init_certificate_authorities(SSL *s, unsigned int context)
{
sk_X509_NAME_pop_free(s->s3->tmp.peer_ca_names, X509_NAME_free);
s->s3->tmp.peer_ca_names = NULL;
return 1;
}
static EXT_RETURN tls_construct_certificate_authorities(SSL *s, WPACKET *pkt,
unsigned int context,
X509 *x,
size_t chainidx)
{
const STACK_OF(X509_NAME) *ca_sk = get_ca_names(s);
if (ca_sk == NULL || sk_X509_NAME_num(ca_sk) == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_certificate_authorities)
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (!construct_ca_names(s, ca_sk, pkt)) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CERTIFICATE_AUTHORITIES,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
static int tls_parse_certificate_authorities(SSL *s, PACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!parse_ca_names(s, pkt))
return 0;
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CERTIFICATE_AUTHORITIES, SSL_R_BAD_EXTENSION);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_SRTP
static int init_srtp(SSL *s, unsigned int context)
{
if (s->server)
s->srtp_profile = NULL;
return 1;
}
#endif
static int final_sig_algs(SSL *s, unsigned int context, int sent)
{
if (!sent && SSL_IS_TLS13(s) && !s->hit) {
SSLfatal(s, TLS13_AD_MISSING_EXTENSION, SSL_F_FINAL_SIG_ALGS,
SSL_R_MISSING_SIGALGS_EXTENSION);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_EC
static int final_key_share(SSL *s, unsigned int context, int sent)
{
if (!SSL_IS_TLS13(s))
return 1;
/* Nothing to do for key_share in an HRR */
if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0)
return 1;
/*
* If
* we are a client
* AND
* we have no key_share
* AND
* (we are not resuming
* OR the kex_mode doesn't allow non key_share resumes)
* THEN
* fail;
*/
if (!s->server
&& !sent
&& (!s->hit
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0)) {
/* Nothing left we can do - just fail */
SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_KEY_SHARE,
SSL_R_NO_SUITABLE_KEY_SHARE);
return 0;
}
/*
* IF
* we are a server
* THEN
* IF
* we have a suitable key_share
* THEN
* IF
* we are stateless AND we have no cookie
* THEN
* send a HelloRetryRequest
* ELSE
* IF
* we didn't already send a HelloRetryRequest
* AND
* the client sent a key_share extension
* AND
* (we are not resuming
* OR the kex_mode allows key_share resumes)
* AND
* a shared group exists
* THEN
* send a HelloRetryRequest
* ELSE IF
* we are not resuming
* OR
* the kex_mode doesn't allow non key_share resumes
* THEN
* fail
* ELSE IF
* we are stateless AND we have no cookie
* THEN
* send a HelloRetryRequest
*/
if (s->server) {
if (s->s3->peer_tmp != NULL) {
/* We have a suitable key_share */
if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
&& !s->ext.cookieok) {
if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
/*
* If we are stateless then we wouldn't know about any
* previously sent HRR - so how can this be anything other
* than 0?
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->hello_retry_request = SSL_HRR_PENDING;
return 1;
}
} else {
/* No suitable key_share */
if (s->hello_retry_request == SSL_HRR_NONE && sent
&& (!s->hit
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE)
!= 0)) {
const uint16_t *pgroups, *clntgroups;
size_t num_groups, clnt_num_groups, i;
unsigned int group_id = 0;
/* Check if a shared group exists */
/* Get the clients list of supported groups. */
tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
tls1_get_supported_groups(s, &pgroups, &num_groups);
/*
* Find the first group we allow that is also in client's list
*/
for (i = 0; i < num_groups; i++) {
group_id = pgroups[i];
if (check_in_list(s, group_id, clntgroups, clnt_num_groups,
1))
break;
}
if (i < num_groups) {
/* A shared group exists so send a HelloRetryRequest */
s->s3->group_id = group_id;
s->hello_retry_request = SSL_HRR_PENDING;
return 1;
}
}
if (!s->hit
|| (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE) == 0) {
/* Nothing left we can do - just fail */
SSLfatal(s, sent ? SSL_AD_HANDSHAKE_FAILURE
: SSL_AD_MISSING_EXTENSION,
SSL_F_FINAL_KEY_SHARE, SSL_R_NO_SUITABLE_KEY_SHARE);
return 0;
}
if ((s->s3->flags & TLS1_FLAGS_STATELESS) != 0
&& !s->ext.cookieok) {
if (!ossl_assert(s->hello_retry_request == SSL_HRR_NONE)) {
/*
* If we are stateless then we wouldn't know about any
* previously sent HRR - so how can this be anything other
* than 0?
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->hello_retry_request = SSL_HRR_PENDING;
return 1;
}
}
/*
* We have a key_share so don't send any more HelloRetryRequest
* messages
*/
if (s->hello_retry_request == SSL_HRR_PENDING)
s->hello_retry_request = SSL_HRR_COMPLETE;
} else {
/*
* For a client side resumption with no key_share we need to generate
* the handshake secret (otherwise this is done during key_share
* processing).
*/
if (!sent && !tls13_generate_handshake_secret(s, NULL, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_FINAL_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
#endif
static int init_psk_kex_modes(SSL *s, unsigned int context)
{
s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_NONE;
return 1;
}
int tls_psk_do_binder(SSL *s, const EVP_MD *md, const unsigned char *msgstart,
size_t binderoffset, const unsigned char *binderin,
unsigned char *binderout, SSL_SESSION *sess, int sign,
int external)
{
EVP_PKEY *mackey = NULL;
EVP_MD_CTX *mctx = NULL;
unsigned char hash[EVP_MAX_MD_SIZE], binderkey[EVP_MAX_MD_SIZE];
unsigned char finishedkey[EVP_MAX_MD_SIZE], tmpbinder[EVP_MAX_MD_SIZE];
unsigned char *early_secret;
static const unsigned char resumption_label[] = "res binder";
static const unsigned char external_label[] = "ext binder";
const unsigned char *label;
size_t bindersize, labelsize, hashsize;
int hashsizei = EVP_MD_size(md);
int ret = -1;
int usepskfored = 0;
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashsizei >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
ERR_R_INTERNAL_ERROR);
goto err;
}
hashsize = (size_t)hashsizei;
if (external
&& s->early_data_state == SSL_EARLY_DATA_CONNECTING
&& s->session->ext.max_early_data == 0
&& sess->ext.max_early_data > 0)
usepskfored = 1;
if (external) {
label = external_label;
labelsize = sizeof(external_label) - 1;
} else {
label = resumption_label;
labelsize = sizeof(resumption_label) - 1;
}
/*
* Generate the early_secret. On the server side we've selected a PSK to
* resume with (internal or external) so we always do this. On the client
* side we do this for a non-external (i.e. resumption) PSK or external PSK
* that will be used for early_data so that it is in place for sending early
* data. For client side external PSK not being used for early_data we
* generate it but store it away for later use.
*/
if (s->server || !external || usepskfored)
early_secret = (unsigned char *)s->early_secret;
else
early_secret = (unsigned char *)sess->early_secret;
if (!tls13_generate_secret(s, md, NULL, sess->master_key,
sess->master_key_length, early_secret)) {
/* SSLfatal() already called */
goto err;
}
/*
* Create the handshake hash for the binder key...the messages so far are
* empty!
*/
mctx = EVP_MD_CTX_new();
if (mctx == NULL
|| EVP_DigestInit_ex(mctx, md, NULL) <= 0
|| EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Generate the binder key */
if (!tls13_hkdf_expand(s, md, early_secret, label, labelsize, hash,
hashsize, binderkey, hashsize, 1)) {
/* SSLfatal() already called */
goto err;
}
/* Generate the finished key */
if (!tls13_derive_finishedkey(s, md, binderkey, finishedkey, hashsize)) {
/* SSLfatal() already called */
goto err;
}
if (EVP_DigestInit_ex(mctx, md, NULL) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* Get a hash of the ClientHello up to the start of the binders. If we are
* following a HelloRetryRequest then this includes the hash of the first
* ClientHello and the HelloRetryRequest itself.
*/
if (s->hello_retry_request == SSL_HRR_PENDING) {
size_t hdatalen;
long hdatalen_l;
void *hdata;
hdatalen = hdatalen_l =
BIO_get_mem_data(s->s3->handshake_buffer, &hdata);
if (hdatalen_l <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
SSL_R_BAD_HANDSHAKE_LENGTH);
goto err;
}
/*
* For servers the handshake buffer data will include the second
* ClientHello - which we don't want - so we need to take that bit off.
*/
if (s->server) {
PACKET hashprefix, msg;
/* Find how many bytes are left after the first two messages */
if (!PACKET_buf_init(&hashprefix, hdata, hdatalen)
|| !PACKET_forward(&hashprefix, 1)
|| !PACKET_get_length_prefixed_3(&hashprefix, &msg)
|| !PACKET_forward(&hashprefix, 1)
|| !PACKET_get_length_prefixed_3(&hashprefix, &msg)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
ERR_R_INTERNAL_ERROR);
goto err;
}
hdatalen -= PACKET_remaining(&hashprefix);
}
if (EVP_DigestUpdate(mctx, hdata, hdatalen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (EVP_DigestUpdate(mctx, msgstart, binderoffset) <= 0
|| EVP_DigestFinal_ex(mctx, hash, NULL) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
ERR_R_INTERNAL_ERROR);
goto err;
}
mackey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, finishedkey,
hashsize);
if (mackey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!sign)
binderout = tmpbinder;
bindersize = hashsize;
if (EVP_DigestSignInit(mctx, NULL, md, NULL, mackey) <= 0
|| EVP_DigestSignUpdate(mctx, hash, hashsize) <= 0
|| EVP_DigestSignFinal(mctx, binderout, &bindersize) <= 0
|| bindersize != hashsize) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PSK_DO_BINDER,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (sign) {
ret = 1;
} else {
/* HMAC keys can't do EVP_DigestVerify* - use CRYPTO_memcmp instead */
ret = (CRYPTO_memcmp(binderin, binderout, hashsize) == 0);
if (!ret)
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PSK_DO_BINDER,
SSL_R_BINDER_DOES_NOT_VERIFY);
}
err:
OPENSSL_cleanse(binderkey, sizeof(binderkey));
OPENSSL_cleanse(finishedkey, sizeof(finishedkey));
EVP_PKEY_free(mackey);
EVP_MD_CTX_free(mctx);
return ret;
}
static int final_early_data(SSL *s, unsigned int context, int sent)
{
if (!sent)
return 1;
if (!s->server) {
if (context == SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS
&& sent
&& !s->ext.early_data_ok) {
/*
* If we get here then the server accepted our early_data but we
* later realised that it shouldn't have done (e.g. inconsistent
* ALPN)
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_FINAL_EARLY_DATA,
SSL_R_BAD_EARLY_DATA);
return 0;
}
return 1;
}
if (s->max_early_data == 0
|| !s->hit
- || s->session->ext.tick_identity != 0
|| s->early_data_state != SSL_EARLY_DATA_ACCEPTING
|| !s->ext.early_data_ok
|| s->hello_retry_request != SSL_HRR_NONE
|| (s->ctx->allow_early_data_cb != NULL
&& !s->ctx->allow_early_data_cb(s,
s->ctx->allow_early_data_cb_data))) {
s->ext.early_data = SSL_EARLY_DATA_REJECTED;
} else {
s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
if (!tls13_change_cipher_state(s,
SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_SERVER_READ)) {
/* SSLfatal() already called */
return 0;
}
}
return 1;
}
static int final_maxfragmentlen(SSL *s, unsigned int context, int sent)
{
/*
* Session resumption on server-side with MFL extension active
* BUT MFL extension packet was not resent (i.e. sent == 0)
*/
if (s->server && s->hit && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& !sent ) {
SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_FINAL_MAXFRAGMENTLEN,
SSL_R_BAD_EXTENSION);
return 0;
}
/* Current SSL buffer is lower than requested MFL */
if (s->session && USE_MAX_FRAGMENT_LENGTH_EXT(s->session)
&& s->max_send_fragment < GET_MAX_FRAGMENT_LENGTH(s->session))
/* trigger a larger buffer reallocation */
if (!ssl3_setup_buffers(s)) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
static int init_post_handshake_auth(SSL *s, unsigned int context)
{
s->post_handshake_auth = SSL_PHA_NONE;
return 1;
}
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index ab4dbf67131e..3c7d84427f08 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -1,1991 +1,2001 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/ocsp.h>
#include "../ssl_locl.h"
#include "internal/cryptlib.h"
#include "statem_locl.h"
EXT_RETURN tls_construct_ctos_renegotiate(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
/* Add RI if renegotiating */
if (!s->renegotiate)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u8(pkt, s->s3->previous_client_finished,
s->s3->previous_client_finished_len)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_RENEGOTIATE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_ctos_server_name(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (s->ext.hostname == NULL)
return EXT_RETURN_NOT_SENT;
/* Add TLS extension servername to the Client Hello message */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
/* Sub-packet for server_name extension */
|| !WPACKET_start_sub_packet_u16(pkt)
/* Sub-packet for servername list (always 1 hostname)*/
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_NAMETYPE_host_name)
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.hostname,
strlen(s->ext.hostname))
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
/* Push a Max Fragment Len extension into ClientHello */
EXT_RETURN tls_construct_ctos_maxfragmentlen(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (s->ext.max_fragment_len_mode == TLSEXT_max_fragment_length_DISABLED)
return EXT_RETURN_NOT_SENT;
/* Add Max Fragment Length extension if client enabled it. */
/*-
* 4 bytes for this extension type and extension length
* 1 byte for the Max Fragment Length code value.
*/
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
/* Sub-packet for Max Fragment Length extension (1 byte) */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, s->ext.max_fragment_len_mode)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_SRP
EXT_RETURN tls_construct_ctos_srp(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
/* Add SRP username if there is one */
if (s->srp_ctx.login == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_srp)
/* Sub-packet for SRP extension */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)
/* login must not be zero...internal error if so */
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
|| !WPACKET_memcpy(pkt, s->srp_ctx.login,
strlen(s->srp_ctx.login))
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SRP,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
#ifndef OPENSSL_NO_EC
static int use_ecc(SSL *s)
{
int i, end, ret = 0;
unsigned long alg_k, alg_a;
STACK_OF(SSL_CIPHER) *cipher_stack = NULL;
/* See if we support any ECC ciphersuites */
if (s->version == SSL3_VERSION)
return 0;
cipher_stack = SSL_get1_supported_ciphers(s);
end = sk_SSL_CIPHER_num(cipher_stack);
for (i = 0; i < end; i++) {
const SSL_CIPHER *c = sk_SSL_CIPHER_value(cipher_stack, i);
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
if ((alg_k & (SSL_kECDHE | SSL_kECDHEPSK))
|| (alg_a & SSL_aECDSA)
|| c->min_tls >= TLS1_3_VERSION) {
ret = 1;
break;
}
}
sk_SSL_CIPHER_free(cipher_stack);
return ret;
}
EXT_RETURN tls_construct_ctos_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const unsigned char *pformats;
size_t num_formats;
if (!use_ecc(s))
return EXT_RETURN_NOT_SENT;
/* Add TLS extension ECPointFormats to the ClientHello message */
tls1_get_formatlist(s, &pformats, &num_formats);
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
/* Sub-packet for formats extension */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u8(pkt, pformats, num_formats)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_ctos_supported_groups(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const uint16_t *pgroups = NULL;
size_t num_groups = 0, i;
if (!use_ecc(s))
return EXT_RETURN_NOT_SENT;
/*
* Add TLS extension supported_groups to the ClientHello message
*/
/* TODO(TLS1.3): Add support for DHE groups */
tls1_get_supported_groups(s, &pgroups, &num_groups);
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
/* Sub-packet for supported_groups extension */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* Copy curve ID if supported */
for (i = 0; i < num_groups; i++) {
uint16_t ctmp = pgroups[i];
if (tls_curve_allowed(s, ctmp, SSL_SECOP_CURVE_SUPPORTED)) {
if (!WPACKET_put_bytes_u16(pkt, ctmp)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
EXT_RETURN tls_construct_ctos_session_ticket(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
size_t ticklen;
if (!tls_use_ticket(s))
return EXT_RETURN_NOT_SENT;
if (!s->new_session && s->session != NULL
&& s->session->ext.tick != NULL
&& s->session->ssl_version != TLS1_3_VERSION) {
ticklen = s->session->ext.ticklen;
} else if (s->session && s->ext.session_ticket != NULL
&& s->ext.session_ticket->data != NULL) {
ticklen = s->ext.session_ticket->length;
s->session->ext.tick = OPENSSL_malloc(ticklen);
if (s->session->ext.tick == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
memcpy(s->session->ext.tick,
s->ext.session_ticket->data, ticklen);
s->session->ext.ticklen = ticklen;
} else {
ticklen = 0;
}
if (ticklen == 0 && s->ext.session_ticket != NULL &&
s->ext.session_ticket->data == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|| !WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick, ticklen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_ctos_sig_algs(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
size_t salglen;
const uint16_t *salg;
if (!SSL_CLIENT_USE_SIGALGS(s))
return EXT_RETURN_NOT_SENT;
salglen = tls12_get_psigalgs(s, 1, &salg);
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signature_algorithms)
/* Sub-packet for sig-algs extension */
|| !WPACKET_start_sub_packet_u16(pkt)
/* Sub-packet for the actual list */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !tls12_copy_sigalgs(s, pkt, salg, salglen)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SIG_ALGS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_OCSP
EXT_RETURN tls_construct_ctos_status_request(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
int i;
/* This extension isn't defined for client Certificates */
if (x != NULL)
return EXT_RETURN_NOT_SENT;
if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
/* Sub-packet for status request extension */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_STATUSTYPE_ocsp)
/* Sub-packet for the ids */
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
for (i = 0; i < sk_OCSP_RESPID_num(s->ext.ocsp.ids); i++) {
unsigned char *idbytes;
OCSP_RESPID *id = sk_OCSP_RESPID_value(s->ext.ocsp.ids, i);
int idlen = i2d_OCSP_RESPID(id, NULL);
if (idlen <= 0
/* Sub-packet for an individual id */
|| !WPACKET_sub_allocate_bytes_u16(pkt, idlen, &idbytes)
|| i2d_OCSP_RESPID(id, &idbytes) != idlen) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
if (!WPACKET_close(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (s->ext.ocsp.exts) {
unsigned char *extbytes;
int extlen = i2d_X509_EXTENSIONS(s->ext.ocsp.exts, NULL);
if (extlen < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (!WPACKET_allocate_bytes(pkt, extlen, &extbytes)
|| i2d_X509_EXTENSIONS(s->ext.ocsp.exts, &extbytes)
!= extlen) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
EXT_RETURN tls_construct_ctos_npn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->ctx->ext.npn_select_cb == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
return EXT_RETURN_NOT_SENT;
/*
* The client advertises an empty extension to indicate its support
* for Next Protocol Negotiation
*/
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_NPN,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
EXT_RETURN tls_construct_ctos_alpn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
s->s3->alpn_sent = 0;
if (s->ext.alpn == NULL || !SSL_IS_FIRST_HANDSHAKE(s))
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt,
TLSEXT_TYPE_application_layer_protocol_negotiation)
/* Sub-packet ALPN extension */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.alpn, s->ext.alpn_len)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ALPN,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->s3->alpn_sent = 1;
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_SRTP
EXT_RETURN tls_construct_ctos_use_srtp(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
STACK_OF(SRTP_PROTECTION_PROFILE) *clnt = SSL_get_srtp_profiles(s);
int i, end;
if (clnt == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
/* Sub-packet for SRTP extension */
|| !WPACKET_start_sub_packet_u16(pkt)
/* Sub-packet for the protection profile list */
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
end = sk_SRTP_PROTECTION_PROFILE_num(clnt);
for (i = 0; i < end; i++) {
const SRTP_PROTECTION_PROFILE *prof =
sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
if (prof == NULL || !WPACKET_put_bytes_u16(pkt, prof->id)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
if (!WPACKET_close(pkt)
/* Add an empty use_mki value */
|| !WPACKET_put_bytes_u8(pkt, 0)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_USE_SRTP,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
EXT_RETURN tls_construct_ctos_etm(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_ETM,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_CT
EXT_RETURN tls_construct_ctos_sct(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->ct_validation_callback == NULL)
return EXT_RETURN_NOT_SENT;
/* Not defined for client Certificates */
if (x != NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_signed_certificate_timestamp)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_SCT,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
EXT_RETURN tls_construct_ctos_ems(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EMS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
int currv, min_version, max_version, reason;
reason = ssl_get_min_max_version(s, &min_version, &max_version, NULL);
if (reason != 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, reason);
return EXT_RETURN_FAIL;
}
/*
* Don't include this if we can't negotiate TLSv1.3. We can do a straight
* comparison here because we will never be called in DTLS.
*/
if (max_version < TLS1_3_VERSION)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
for (currv = max_version; currv >= min_version; currv--) {
if (!WPACKET_put_bytes_u16(pkt, currv)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
/*
* Construct a psk_kex_modes extension.
*/
EXT_RETURN tls_construct_ctos_psk_kex_modes(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
int nodhe = s->options & SSL_OP_ALLOW_NO_DHE_KEX;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk_kex_modes)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)
|| !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE_DHE)
|| (nodhe && !WPACKET_put_bytes_u8(pkt, TLSEXT_KEX_MODE_KE))
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_PSK_KEX_MODES, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->ext.psk_kex_mode = TLSEXT_KEX_MODE_FLAG_KE_DHE;
if (nodhe)
s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
#endif
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_TLS1_3
static int add_key_share(SSL *s, WPACKET *pkt, unsigned int curve_id)
{
unsigned char *encoded_point = NULL;
EVP_PKEY *key_share_key = NULL;
size_t encodedlen;
if (s->s3->tmp.pkey != NULL) {
if (!ossl_assert(s->hello_retry_request == SSL_HRR_PENDING)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* Could happen if we got an HRR that wasn't requesting a new key_share
*/
key_share_key = s->s3->tmp.pkey;
} else {
key_share_key = ssl_generate_pkey_group(s, curve_id);
if (key_share_key == NULL) {
/* SSLfatal() already called */
return 0;
}
}
/* Encode the public key. */
encodedlen = EVP_PKEY_get1_tls_encodedpoint(key_share_key,
&encoded_point);
if (encodedlen == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE, ERR_R_EC_LIB);
goto err;
}
/* Create KeyShareEntry */
if (!WPACKET_put_bytes_u16(pkt, curve_id)
|| !WPACKET_sub_memcpy_u16(pkt, encoded_point, encodedlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_ADD_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* TODO(TLS1.3): When changing to send more than one key_share we're
* going to need to be able to save more than one EVP_PKEY. For now
* we reuse the existing tmp.pkey
*/
s->s3->tmp.pkey = key_share_key;
s->s3->group_id = curve_id;
OPENSSL_free(encoded_point);
return 1;
err:
if (s->s3->tmp.pkey == NULL)
EVP_PKEY_free(key_share_key);
OPENSSL_free(encoded_point);
return 0;
}
#endif
EXT_RETURN tls_construct_ctos_key_share(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
size_t i, num_groups = 0;
const uint16_t *pgroups = NULL;
uint16_t curve_id = 0;
/* key_share extension */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
/* Extension data sub-packet */
|| !WPACKET_start_sub_packet_u16(pkt)
/* KeyShare list sub-packet */
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
tls1_get_supported_groups(s, &pgroups, &num_groups);
/*
* TODO(TLS1.3): Make the number of key_shares sent configurable. For
* now, just send one
*/
if (s->s3->group_id != 0) {
curve_id = s->s3->group_id;
} else {
for (i = 0; i < num_groups; i++) {
if (!tls_curve_allowed(s, pgroups[i], SSL_SECOP_CURVE_SUPPORTED))
continue;
curve_id = pgroups[i];
break;
}
}
if (curve_id == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
SSL_R_NO_SUITABLE_KEY_SHARE);
return EXT_RETURN_FAIL;
}
if (!add_key_share(s, pkt, curve_id)) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
#else
return EXT_RETURN_NOT_SENT;
#endif
}
EXT_RETURN tls_construct_ctos_cookie(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
EXT_RETURN ret = EXT_RETURN_FAIL;
/* Should only be set if we've had an HRR */
if (s->ext.tls13_cookie_len == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
/* Extension data sub-packet */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u16(pkt, s->ext.tls13_cookie,
s->ext.tls13_cookie_len)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_COOKIE,
ERR_R_INTERNAL_ERROR);
goto end;
}
ret = EXT_RETURN_SENT;
end:
OPENSSL_free(s->ext.tls13_cookie);
s->ext.tls13_cookie = NULL;
s->ext.tls13_cookie_len = 0;
return ret;
}
EXT_RETURN tls_construct_ctos_early_data(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_PSK
char identity[PSK_MAX_IDENTITY_LEN + 1];
#endif /* OPENSSL_NO_PSK */
const unsigned char *id = NULL;
size_t idlen = 0;
SSL_SESSION *psksess = NULL;
SSL_SESSION *edsess = NULL;
const EVP_MD *handmd = NULL;
if (s->hello_retry_request == SSL_HRR_PENDING)
handmd = ssl_handshake_md(s);
if (s->psk_use_session_cb != NULL
&& (!s->psk_use_session_cb(s, handmd, &id, &idlen, &psksess)
|| (psksess != NULL
&& psksess->ssl_version != TLS1_3_VERSION))) {
SSL_SESSION_free(psksess);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
SSL_R_BAD_PSK);
return EXT_RETURN_FAIL;
}
#ifndef OPENSSL_NO_PSK
if (psksess == NULL && s->psk_client_callback != NULL) {
unsigned char psk[PSK_MAX_PSK_LEN];
size_t psklen = 0;
memset(identity, 0, sizeof(identity));
psklen = s->psk_client_callback(s, NULL, identity, sizeof(identity) - 1,
psk, sizeof(psk));
if (psklen > PSK_MAX_PSK_LEN) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
} else if (psklen > 0) {
const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
const SSL_CIPHER *cipher;
idlen = strlen(identity);
if (idlen > PSK_MAX_IDENTITY_LEN) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
id = (unsigned char *)identity;
/*
* We found a PSK using an old style callback. We don't know
* the digest so we default to SHA256 as per the TLSv1.3 spec
*/
cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
if (cipher == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
psksess = SSL_SESSION_new();
if (psksess == NULL
|| !SSL_SESSION_set1_master_key(psksess, psk, psklen)
|| !SSL_SESSION_set_cipher(psksess, cipher)
|| !SSL_SESSION_set_protocol_version(psksess, TLS1_3_VERSION)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
ERR_R_INTERNAL_ERROR);
OPENSSL_cleanse(psk, psklen);
return EXT_RETURN_FAIL;
}
OPENSSL_cleanse(psk, psklen);
}
}
#endif /* OPENSSL_NO_PSK */
SSL_SESSION_free(s->psksession);
s->psksession = psksess;
if (psksess != NULL) {
OPENSSL_free(s->psksession_id);
s->psksession_id = OPENSSL_memdup(id, idlen);
if (s->psksession_id == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->psksession_id_len = idlen;
}
if (s->early_data_state != SSL_EARLY_DATA_CONNECTING
|| (s->session->ext.max_early_data == 0
&& (psksess == NULL || psksess->ext.max_early_data == 0))) {
s->max_early_data = 0;
return EXT_RETURN_NOT_SENT;
}
edsess = s->session->ext.max_early_data != 0 ? s->session : psksess;
s->max_early_data = edsess->ext.max_early_data;
if (edsess->ext.hostname != NULL) {
if (s->ext.hostname == NULL
|| (s->ext.hostname != NULL
&& strcmp(s->ext.hostname, edsess->ext.hostname) != 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
SSL_R_INCONSISTENT_EARLY_DATA_SNI);
return EXT_RETURN_FAIL;
}
}
if ((s->ext.alpn == NULL && edsess->ext.alpn_selected != NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
return EXT_RETURN_FAIL;
}
/*
* Verify that we are offering an ALPN protocol consistent with the early
* data.
*/
if (edsess->ext.alpn_selected != NULL) {
PACKET prots, alpnpkt;
int found = 0;
if (!PACKET_buf_init(&prots, s->ext.alpn, s->ext.alpn_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
while (PACKET_get_length_prefixed_1(&prots, &alpnpkt)) {
if (PACKET_equal(&alpnpkt, edsess->ext.alpn_selected,
edsess->ext.alpn_selected_len)) {
found = 1;
break;
}
}
if (!found) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
SSL_R_INCONSISTENT_EARLY_DATA_ALPN);
return EXT_RETURN_FAIL;
}
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_EARLY_DATA,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/*
* We set this to rejected here. Later, if the server acknowledges the
* extension, we set it to accepted.
*/
s->ext.early_data = SSL_EARLY_DATA_REJECTED;
s->ext.early_data_ok = 1;
return EXT_RETURN_SENT;
}
#define F5_WORKAROUND_MIN_MSG_LEN 0xff
#define F5_WORKAROUND_MAX_MSG_LEN 0x200
/*
* PSK pre binder overhead =
* 2 bytes for TLSEXT_TYPE_psk
* 2 bytes for extension length
* 2 bytes for identities list length
* 2 bytes for identity length
* 4 bytes for obfuscated_ticket_age
* 2 bytes for binder list length
* 1 byte for binder length
* The above excludes the number of bytes for the identity itself and the
* subsequent binder bytes
*/
#define PSK_PRE_BINDER_OVERHEAD (2 + 2 + 2 + 2 + 4 + 2 + 1)
EXT_RETURN tls_construct_ctos_padding(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
unsigned char *padbytes;
size_t hlen;
if ((s->options & SSL_OP_TLSEXT_PADDING) == 0)
return EXT_RETURN_NOT_SENT;
/*
* Add padding to workaround bugs in F5 terminators. See RFC7685.
* This code calculates the length of all extensions added so far but
* excludes the PSK extension (because that MUST be written last). Therefore
* this extension MUST always appear second to last.
*/
if (!WPACKET_get_total_written(pkt, &hlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/*
* If we're going to send a PSK then that will be written out after this
* extension, so we need to calculate how long it is going to be.
*/
if (s->session->ssl_version == TLS1_3_VERSION
&& s->session->ext.ticklen != 0
&& s->session->cipher != NULL) {
const EVP_MD *md = ssl_md(s->session->cipher->algorithm2);
if (md != NULL) {
/*
* Add the fixed PSK overhead, the identity length and the binder
* length.
*/
hlen += PSK_PRE_BINDER_OVERHEAD + s->session->ext.ticklen
+ EVP_MD_size(md);
}
}
if (hlen > F5_WORKAROUND_MIN_MSG_LEN && hlen < F5_WORKAROUND_MAX_MSG_LEN) {
/* Calculate the amount of padding we need to add */
hlen = F5_WORKAROUND_MAX_MSG_LEN - hlen;
/*
* Take off the size of extension header itself (2 bytes for type and
* 2 bytes for length bytes), but ensure that the extension is at least
* 1 byte long so as not to have an empty extension last (WebSphere 7.x,
* 8.x are intolerant of that condition)
*/
if (hlen > 4)
hlen -= 4;
else
hlen = 1;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_padding)
|| !WPACKET_sub_allocate_bytes_u16(pkt, hlen, &padbytes)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PADDING,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
memset(padbytes, 0, hlen);
}
return EXT_RETURN_SENT;
}
/*
* Construct the pre_shared_key extension
*/
EXT_RETURN tls_construct_ctos_psk(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
uint32_t now, agesec, agems = 0;
size_t reshashsize = 0, pskhashsize = 0, binderoffset, msglen;
unsigned char *resbinder = NULL, *pskbinder = NULL, *msgstart = NULL;
const EVP_MD *handmd = NULL, *mdres = NULL, *mdpsk = NULL;
int dores = 0;
- s->session->ext.tick_identity = TLSEXT_PSK_BAD_IDENTITY;
+ s->ext.tick_identity = 0;
/*
* Note: At this stage of the code we only support adding a single
* resumption PSK. If we add support for multiple PSKs then the length
* calculations in the padding extension will need to be adjusted.
*/
/*
* If this is an incompatible or new session then we have nothing to resume
* so don't add this extension.
*/
if (s->session->ssl_version != TLS1_3_VERSION
|| (s->session->ext.ticklen == 0 && s->psksession == NULL))
return EXT_RETURN_NOT_SENT;
if (s->hello_retry_request == SSL_HRR_PENDING)
handmd = ssl_handshake_md(s);
if (s->session->ext.ticklen != 0) {
/* Get the digest associated with the ciphersuite in the session */
if (s->session->cipher == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
mdres = ssl_md(s->session->cipher->algorithm2);
if (mdres == NULL) {
/*
* Don't recognize this cipher so we can't use the session.
* Ignore it
*/
goto dopsksess;
}
if (s->hello_retry_request == SSL_HRR_PENDING && mdres != handmd) {
/*
* Selected ciphersuite hash does not match the hash for the session
* so we can't use it.
*/
goto dopsksess;
}
/*
* Technically the C standard just says time() returns a time_t and says
* nothing about the encoding of that type. In practice most
* implementations follow POSIX which holds it as an integral type in
* seconds since epoch. We've already made the assumption that we can do
* this in multiple places in the code, so portability shouldn't be an
* issue.
*/
now = (uint32_t)time(NULL);
agesec = now - (uint32_t)s->session->time;
/*
* We calculate the age in seconds but the server may work in ms. Due to
* rounding errors we could overestimate the age by up to 1s. It is
* better to underestimate it. Otherwise, if the RTT is very short, when
* the server calculates the age reported by the client it could be
* bigger than the age calculated on the server - which should never
* happen.
*/
if (agesec > 0)
agesec--;
if (s->session->ext.tick_lifetime_hint < agesec) {
/* Ticket is too old. Ignore it. */
goto dopsksess;
}
/*
* Calculate age in ms. We're just doing it to nearest second. Should be
* good enough.
*/
agems = agesec * (uint32_t)1000;
if (agesec != 0 && agems / (uint32_t)1000 != agesec) {
/*
* Overflow. Shouldn't happen unless this is a *really* old session.
* If so we just ignore it.
*/
goto dopsksess;
}
/*
* Obfuscate the age. Overflow here is fine, this addition is supposed
* to be mod 2^32.
*/
agems += s->session->ext.tick_age_add;
reshashsize = EVP_MD_size(mdres);
+ s->ext.tick_identity++;
dores = 1;
}
dopsksess:
if (!dores && s->psksession == NULL)
return EXT_RETURN_NOT_SENT;
if (s->psksession != NULL) {
mdpsk = ssl_md(s->psksession->cipher->algorithm2);
if (mdpsk == NULL) {
/*
* Don't recognize this cipher so we can't use the session.
* If this happens it's an application bug.
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
SSL_R_BAD_PSK);
return EXT_RETURN_FAIL;
}
if (s->hello_retry_request == SSL_HRR_PENDING && mdpsk != handmd) {
/*
* Selected ciphersuite hash does not match the hash for the PSK
* session. This is an application bug.
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
SSL_R_BAD_PSK);
return EXT_RETURN_FAIL;
}
pskhashsize = EVP_MD_size(mdpsk);
}
/* Create the extension, but skip over the binder for now */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (dores) {
if (!WPACKET_sub_memcpy_u16(pkt, s->session->ext.tick,
s->session->ext.ticklen)
|| !WPACKET_put_bytes_u32(pkt, agems)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
if (s->psksession != NULL) {
if (!WPACKET_sub_memcpy_u16(pkt, s->psksession_id,
s->psksession_id_len)
|| !WPACKET_put_bytes_u32(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
+ s->ext.tick_identity++;
}
if (!WPACKET_close(pkt)
|| !WPACKET_get_total_written(pkt, &binderoffset)
|| !WPACKET_start_sub_packet_u16(pkt)
|| (dores
&& !WPACKET_sub_allocate_bytes_u8(pkt, reshashsize, &resbinder))
|| (s->psksession != NULL
&& !WPACKET_sub_allocate_bytes_u8(pkt, pskhashsize, &pskbinder))
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)
|| !WPACKET_get_total_written(pkt, &msglen)
/*
* We need to fill in all the sub-packet lengths now so we can
* calculate the HMAC of the message up to the binders
*/
|| !WPACKET_fill_lengths(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
msgstart = WPACKET_get_curr(pkt) - msglen;
if (dores
&& tls_psk_do_binder(s, mdres, msgstart, binderoffset, NULL,
resbinder, s->session, 1, 0) != 1) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
if (s->psksession != NULL
&& tls_psk_do_binder(s, mdpsk, msgstart, binderoffset, NULL,
pskbinder, s->psksession, 1, 1) != 1) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
- if (dores)
- s->session->ext.tick_identity = 0;
- if (s->psksession != NULL)
- s->psksession->ext.tick_identity = (dores ? 1 : 0);
-
return EXT_RETURN_SENT;
#else
return EXT_RETURN_NOT_SENT;
#endif
}
EXT_RETURN tls_construct_ctos_post_handshake_auth(SSL *s, WPACKET *pkt,
unsigned int context,
X509 *x, size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
if (!s->pha_enabled)
return EXT_RETURN_NOT_SENT;
/* construct extension - 0 length, no contents */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_post_handshake_auth)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_POST_HANDSHAKE_AUTH,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->post_handshake_auth = SSL_PHA_EXT_SENT;
return EXT_RETURN_SENT;
#else
return EXT_RETURN_NOT_SENT;
#endif
}
/*
* Parse the server's renegotiation binding and abort if it's not right
*/
int tls_parse_stoc_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
size_t expected_len = s->s3->previous_client_finished_len
+ s->s3->previous_server_finished_len;
size_t ilen;
const unsigned char *data;
/* Check for logic errors */
if (!ossl_assert(expected_len == 0
|| s->s3->previous_client_finished_len != 0)
|| !ossl_assert(expected_len == 0
|| s->s3->previous_server_finished_len != 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* Parse the length byte */
if (!PACKET_get_1_len(pkt, &ilen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_ENCODING_ERR);
return 0;
}
/* Consistency check */
if (PACKET_remaining(pkt) != ilen) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_ENCODING_ERR);
return 0;
}
/* Check that the extension matches */
if (ilen != expected_len) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
if (!PACKET_get_bytes(pkt, &data, s->s3->previous_client_finished_len)
|| memcmp(data, s->s3->previous_client_finished,
s->s3->previous_client_finished_len) != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
if (!PACKET_get_bytes(pkt, &data, s->s3->previous_server_finished_len)
|| memcmp(data, s->s3->previous_server_finished,
s->s3->previous_server_finished_len) != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
s->s3->send_connection_binding = 1;
return 1;
}
/* Parse the server's max fragment len extension packet */
int tls_parse_stoc_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
SSL_R_BAD_EXTENSION);
return 0;
}
/* |value| should contains a valid max-fragment-length code. */
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
/* Must be the same value as client-configured one who was sent to server */
/*-
* RFC 6066: if a client receives a maximum fragment length negotiation
* response that differs from the length it requested, ...
* It must abort with SSL_AD_ILLEGAL_PARAMETER alert
*/
if (value != s->ext.max_fragment_len_mode) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_STOC_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
/*
* Maximum Fragment Length Negotiation succeeded.
* The negotiated Maximum Fragment Length is binding now.
*/
s->session->ext.max_fragment_len_mode = value;
return 1;
}
int tls_parse_stoc_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->ext.hostname == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (PACKET_remaining(pkt) > 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit) {
if (s->session->ext.hostname != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.hostname = OPENSSL_strdup(s->ext.hostname);
if (s->session->ext.hostname == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
#ifndef OPENSSL_NO_EC
int tls_parse_stoc_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
size_t ecpointformats_len;
PACKET ecptformatlist;
if (!PACKET_as_length_prefixed_1(pkt, &ecptformatlist)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS,
SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit) {
ecpointformats_len = PACKET_remaining(&ecptformatlist);
if (ecpointformats_len == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, SSL_R_BAD_LENGTH);
return 0;
}
s->session->ext.ecpointformats_len = 0;
OPENSSL_free(s->session->ext.ecpointformats);
s->session->ext.ecpointformats = OPENSSL_malloc(ecpointformats_len);
if (s->session->ext.ecpointformats == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.ecpointformats_len = ecpointformats_len;
if (!PACKET_copy_bytes(&ecptformatlist,
s->session->ext.ecpointformats,
ecpointformats_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
#endif
int tls_parse_stoc_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->ext.session_ticket_cb != NULL &&
!s->ext.session_ticket_cb(s, PACKET_data(pkt),
PACKET_remaining(pkt),
s->ext.session_ticket_cb_arg)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
return 0;
}
if (!tls_use_ticket(s)) {
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
return 0;
}
if (PACKET_remaining(pkt) > 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_STOC_SESSION_TICKET, SSL_R_BAD_EXTENSION);
return 0;
}
s->ext.ticket_expected = 1;
return 1;
}
#ifndef OPENSSL_NO_OCSP
int tls_parse_stoc_status_request(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) {
/* We ignore this if the server sends a CertificateRequest */
/* TODO(TLS1.3): Add support for this */
return 1;
}
/*
* MUST only be sent if we've requested a status
* request message. In TLS <= 1.2 it must also be empty.
*/
if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION,
SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
if (!SSL_IS_TLS13(s) && PACKET_remaining(pkt) > 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_STOC_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
if (SSL_IS_TLS13(s)) {
/* We only know how to handle this if it's for the first Certificate in
* the chain. We ignore any other responses.
*/
if (chainidx != 0)
return 1;
/* SSLfatal() already called */
return tls_process_cert_status_body(s, pkt);
}
/* Set flag to expect CertificateStatus message */
s->ext.status_expected = 1;
return 1;
}
#endif
#ifndef OPENSSL_NO_CT
int tls_parse_stoc_sct(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
if (context == SSL_EXT_TLS1_3_CERTIFICATE_REQUEST) {
/* We ignore this if the server sends it in a CertificateRequest */
/* TODO(TLS1.3): Add support for this */
return 1;
}
/*
* Only take it if we asked for it - i.e if there is no CT validation
* callback set, then a custom extension MAY be processing it, so we
* need to let control continue to flow to that.
*/
if (s->ct_validation_callback != NULL) {
size_t size = PACKET_remaining(pkt);
/* Simply copy it off for later processing */
OPENSSL_free(s->ext.scts);
s->ext.scts = NULL;
s->ext.scts_len = (uint16_t)size;
if (size > 0) {
s->ext.scts = OPENSSL_malloc(size);
if (s->ext.scts == NULL
|| !PACKET_copy_bytes(pkt, s->ext.scts, size)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_SCT,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
} else {
ENDPOINT role = (context & SSL_EXT_TLS1_2_SERVER_HELLO) != 0
? ENDPOINT_CLIENT : ENDPOINT_BOTH;
/*
* If we didn't ask for it then there must be a custom extension,
* otherwise this is unsolicited.
*/
if (custom_ext_find(&s->cert->custext, role,
TLSEXT_TYPE_signed_certificate_timestamp,
NULL) == NULL) {
SSLfatal(s, TLS1_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_SCT,
SSL_R_BAD_EXTENSION);
return 0;
}
if (!custom_ext_parse(s, context,
TLSEXT_TYPE_signed_certificate_timestamp,
PACKET_data(pkt), PACKET_remaining(pkt),
x, chainidx)) {
/* SSLfatal already called */
return 0;
}
}
return 1;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* ssl_next_proto_validate validates a Next Protocol Negotiation block. No
* elements of zero length are allowed and the set of elements must exactly
* fill the length of the block. Returns 1 on success or 0 on failure.
*/
static int ssl_next_proto_validate(SSL *s, PACKET *pkt)
{
PACKET tmp_protocol;
while (PACKET_remaining(pkt)) {
if (!PACKET_get_length_prefixed_1(pkt, &tmp_protocol)
|| PACKET_remaining(&tmp_protocol) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_SSL_NEXT_PROTO_VALIDATE,
SSL_R_BAD_EXTENSION);
return 0;
}
}
return 1;
}
int tls_parse_stoc_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
unsigned char *selected;
unsigned char selected_len;
PACKET tmppkt;
/* Check if we are in a renegotiation. If so ignore this extension */
if (!SSL_IS_FIRST_HANDSHAKE(s))
return 1;
/* We must have requested it. */
if (s->ctx->ext.npn_select_cb == NULL) {
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_NPN,
SSL_R_BAD_EXTENSION);
return 0;
}
/* The data must be valid */
tmppkt = *pkt;
if (!ssl_next_proto_validate(s, &tmppkt)) {
/* SSLfatal() already called */
return 0;
}
if (s->ctx->ext.npn_select_cb(s, &selected, &selected_len,
PACKET_data(pkt),
PACKET_remaining(pkt),
s->ctx->ext.npn_select_cb_arg) !=
SSL_TLSEXT_ERR_OK) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_STOC_NPN,
SSL_R_BAD_EXTENSION);
return 0;
}
/*
* Could be non-NULL if server has sent multiple NPN extensions in
* a single Serverhello
*/
OPENSSL_free(s->ext.npn);
s->ext.npn = OPENSSL_malloc(selected_len);
if (s->ext.npn == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_NPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
memcpy(s->ext.npn, selected, selected_len);
s->ext.npn_len = selected_len;
s->s3->npn_seen = 1;
return 1;
}
#endif
int tls_parse_stoc_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
size_t len;
/* We must have requested it. */
if (!s->s3->alpn_sent) {
SSLfatal(s, SSL_AD_UNSUPPORTED_EXTENSION, SSL_F_TLS_PARSE_STOC_ALPN,
SSL_R_BAD_EXTENSION);
return 0;
}
/*-
* The extension data consists of:
* uint16 list_length
* uint8 proto_length;
* uint8 proto[proto_length];
*/
if (!PACKET_get_net_2_len(pkt, &len)
|| PACKET_remaining(pkt) != len || !PACKET_get_1_len(pkt, &len)
|| PACKET_remaining(pkt) != len) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
SSL_R_BAD_EXTENSION);
return 0;
}
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = OPENSSL_malloc(len);
if (s->s3->alpn_selected == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_copy_bytes(pkt, s->s3->alpn_selected, len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
SSL_R_BAD_EXTENSION);
return 0;
}
s->s3->alpn_selected_len = len;
if (s->session->ext.alpn_selected == NULL
|| s->session->ext.alpn_selected_len != len
|| memcmp(s->session->ext.alpn_selected, s->s3->alpn_selected, len)
!= 0) {
/* ALPN not consistent with the old session so cannot use early_data */
s->ext.early_data_ok = 0;
}
if (!s->hit) {
/*
* This is a new session and so alpn_selected should have been
* initialised to NULL. We should update it with the selected ALPN.
*/
if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.alpn_selected =
OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
if (s->session->ext.alpn_selected == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
}
return 1;
}
#ifndef OPENSSL_NO_SRTP
int tls_parse_stoc_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
unsigned int id, ct, mki;
int i;
STACK_OF(SRTP_PROTECTION_PROFILE) *clnt;
SRTP_PROTECTION_PROFILE *prof;
if (!PACKET_get_net_2(pkt, &ct) || ct != 2
|| !PACKET_get_net_2(pkt, &id)
|| !PACKET_get_1(pkt, &mki)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
if (mki != 0) {
/* Must be no MKI, since we never offer one */
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_USE_SRTP,
SSL_R_BAD_SRTP_MKI_VALUE);
return 0;
}
/* Throw an error if the server gave us an unsolicited extension */
clnt = SSL_get_srtp_profiles(s);
if (clnt == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
SSL_R_NO_SRTP_PROFILES);
return 0;
}
/*
* Check to see if the server gave us something we support (and
* presumably offered)
*/
for (i = 0; i < sk_SRTP_PROTECTION_PROFILE_num(clnt); i++) {
prof = sk_SRTP_PROTECTION_PROFILE_value(clnt, i);
if (prof->id == id) {
s->srtp_profile = prof;
return 1;
}
}
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_USE_SRTP,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
#endif
int tls_parse_stoc_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
/* Ignore if inappropriate ciphersuite */
if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC)
&& s->s3->tmp.new_cipher->algorithm_mac != SSL_AEAD
&& s->s3->tmp.new_cipher->algorithm_enc != SSL_RC4)
s->ext.use_etm = 1;
return 1;
}
int tls_parse_stoc_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
if (!s->hit)
s->session->flags |= SSL_SESS_FLAG_EXTMS;
return 1;
}
int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int version;
if (!PACKET_get_net_2(pkt, &version)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/*
* The only protocol version we support which is valid in this extension in
* a ServerHello is TLSv1.3 therefore we shouldn't be getting anything else.
*/
if (version != TLS1_3_VERSION) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_STOC_SUPPORTED_VERSIONS,
SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
return 0;
}
/* We ignore this extension for HRRs except to sanity check it */
if (context == SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST)
return 1;
/* We just set it here. We validate it in ssl_choose_client_version */
s->version = version;
return 1;
}
int tls_parse_stoc_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned int group_id;
PACKET encoded_pt;
EVP_PKEY *ckey = s->s3->tmp.pkey, *skey = NULL;
/* Sanity check */
if (ckey == NULL || s->s3->peer_tmp != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_get_net_2(pkt, &group_id)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
if ((context & SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST) != 0) {
const uint16_t *pgroups = NULL;
size_t i, num_groups;
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/*
* It is an error if the HelloRetryRequest wants a key_share that we
* already sent in the first ClientHello
*/
if (group_id == s->s3->group_id) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Validate the selected group is one we support */
tls1_get_supported_groups(s, &pgroups, &num_groups);
for (i = 0; i < num_groups; i++) {
if (group_id == pgroups[i])
break;
}
if (i >= num_groups
|| !tls_curve_allowed(s, group_id, SSL_SECOP_CURVE_SUPPORTED)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_STOC_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
return 0;
}
s->s3->group_id = group_id;
EVP_PKEY_free(s->s3->tmp.pkey);
s->s3->tmp.pkey = NULL;
return 1;
}
if (group_id != s->s3->group_id) {
/*
* This isn't for the group that we sent in the original
* key_share!
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
SSL_R_BAD_KEY_SHARE);
return 0;
}
if (!PACKET_as_length_prefixed_2(pkt, &encoded_pt)
|| PACKET_remaining(&encoded_pt) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
skey = ssl_generate_pkey(ckey);
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
ERR_R_MALLOC_FAILURE);
return 0;
}
if (!EVP_PKEY_set1_tls_encodedpoint(skey, PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_KEY_SHARE,
SSL_R_BAD_ECPOINT);
EVP_PKEY_free(skey);
return 0;
}
if (ssl_derive(s, ckey, skey, 1) == 0) {
/* SSLfatal() already called */
EVP_PKEY_free(skey);
return 0;
}
s->s3->peer_tmp = skey;
#endif
return 1;
}
int tls_parse_stoc_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET cookie;
if (!PACKET_as_length_prefixed_2(pkt, &cookie)
|| !PACKET_memdup(&cookie, &s->ext.tls13_cookie,
&s->ext.tls13_cookie_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_COOKIE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
return 1;
}
int tls_parse_stoc_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
unsigned long max_early_data;
if (!PACKET_get_net_4(pkt, &max_early_data)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
SSL_R_INVALID_MAX_EARLY_DATA);
return 0;
}
s->session->ext.max_early_data = max_early_data;
return 1;
}
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->ext.early_data_ok
- || !s->hit
- || s->session->ext.tick_identity != 0) {
+ || !s->hit) {
/*
* If we get here then we didn't send early data, or we didn't resume
* using the first identity, or the SNI/ALPN is not consistent so the
* server should not be accepting it.
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_EARLY_DATA,
SSL_R_BAD_EXTENSION);
return 0;
}
s->ext.early_data = SSL_EARLY_DATA_ACCEPTED;
return 1;
}
int tls_parse_stoc_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned int identity;
if (!PACKET_get_net_2(pkt, &identity) || PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
SSL_R_LENGTH_MISMATCH);
return 0;
}
- if (s->session->ext.tick_identity == (int)identity) {
+ if (identity >= (unsigned int)s->ext.tick_identity) {
+ SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK,
+ SSL_R_BAD_PSK_IDENTITY);
+ return 0;
+ }
+
+ /*
+ * Session resumption tickets are always sent before PSK tickets. If the
+ * ticket index is 0 then it must be for a session resumption ticket if we
+ * sent two tickets, or if we didn't send a PSK ticket.
+ */
+ if (identity == 0 && (s->psksession == NULL || s->ext.tick_identity == 2)) {
s->hit = 1;
SSL_SESSION_free(s->psksession);
s->psksession = NULL;
return 1;
}
- if (s->psksession == NULL
- || s->psksession->ext.tick_identity != (int)identity) {
- SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_STOC_PSK,
- SSL_R_BAD_PSK_IDENTITY);
+ if (s->psksession == NULL) {
+ /* Should never happen */
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_STOC_PSK,
+ ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* If we used the external PSK for sending early_data then s->early_secret
* is already set up, so don't overwrite it. Otherwise we copy the
* early_secret across that we generated earlier.
*/
if ((s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
|| s->session->ext.max_early_data > 0
|| s->psksession->ext.max_early_data == 0)
memcpy(s->early_secret, s->psksession->early_secret, EVP_MAX_MD_SIZE);
SSL_SESSION_free(s->session);
s->session = s->psksession;
s->psksession = NULL;
s->hit = 1;
+ /* Early data is only allowed if we used the first ticket */
+ if (identity != 0)
+ s->ext.early_data_ok = 0;
#endif
return 1;
}
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 0f2b22392bca..6301b4e77caf 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -1,1959 +1,1959 @@
/*
- * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2016-2019 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <openssl/ocsp.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
#include "internal/cryptlib.h"
#define COOKIE_STATE_FORMAT_VERSION 0
/*
* 2 bytes for packet length, 2 bytes for format version, 2 bytes for
* protocol version, 2 bytes for group id, 2 bytes for cipher id, 1 byte for
* key_share present flag, 4 bytes for timestamp, 2 bytes for the hashlen,
* EVP_MAX_MD_SIZE for transcript hash, 1 byte for app cookie length, app cookie
* length bytes, SHA256_DIGEST_LENGTH bytes for the HMAC of the whole thing.
*/
#define MAX_COOKIE_SIZE (2 + 2 + 2 + 2 + 2 + 1 + 4 + 2 + EVP_MAX_MD_SIZE + 1 \
+ SSL_COOKIE_LENGTH + SHA256_DIGEST_LENGTH)
/*
* Message header + 2 bytes for protocol version + number of random bytes +
* + 1 byte for legacy session id length + number of bytes in legacy session id
* + 2 bytes for ciphersuite + 1 byte for legacy compression
* + 2 bytes for extension block length + 6 bytes for key_share extension
* + 4 bytes for cookie extension header + the number of bytes in the cookie
*/
#define MAX_HRR_SIZE (SSL3_HM_HEADER_LENGTH + 2 + SSL3_RANDOM_SIZE + 1 \
+ SSL_MAX_SSL_SESSION_ID_LENGTH + 2 + 1 + 2 + 6 + 4 \
+ MAX_COOKIE_SIZE)
/*
* Parse the client's renegotiation binding and abort if it's not right
*/
int tls_parse_ctos_renegotiate(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int ilen;
const unsigned char *data;
/* Parse the length byte */
if (!PACKET_get_1(pkt, &ilen)
|| !PACKET_get_bytes(pkt, &data, ilen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
SSL_R_RENEGOTIATION_ENCODING_ERR);
return 0;
}
/* Check that the extension matches */
if (ilen != s->s3->previous_client_finished_len) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
if (memcmp(data, s->s3->previous_client_finished,
s->s3->previous_client_finished_len)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PARSE_CTOS_RENEGOTIATE,
SSL_R_RENEGOTIATION_MISMATCH);
return 0;
}
s->s3->send_connection_binding = 1;
return 1;
}
/*-
* The servername extension is treated as follows:
*
* - Only the hostname type is supported with a maximum length of 255.
* - The servername is rejected if too long or if it contains zeros,
* in which case an fatal alert is generated.
* - The servername field is maintained together with the session cache.
* - When a session is resumed, the servername call back invoked in order
* to allow the application to position itself to the right context.
* - The servername is acknowledged if it is new for a session or when
* it is identical to a previously used for the same session.
* Applications can control the behaviour. They can at any time
* set a 'desirable' servername for a new SSL object. This can be the
* case for example with HTTPS when a Host: header field is received and
* a renegotiation is requested. In this case, a possible servername
* presented in the new client hello is only acknowledged if it matches
* the value of the Host: field.
* - Applications must use SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION
* if they provide for changing an explicit servername context for the
* session, i.e. when the session has been established with a servername
* extension.
* - On session reconnect, the servername extension may be absent.
*/
int tls_parse_ctos_server_name(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int servname_type;
PACKET sni, hostname;
if (!PACKET_as_length_prefixed_2(pkt, &sni)
/* ServerNameList must be at least 1 byte long. */
|| PACKET_remaining(&sni) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
/*
* Although the intent was for server_name to be extensible, RFC 4366
* was not clear about it; and so OpenSSL among other implementations,
* always and only allows a 'host_name' name types.
* RFC 6066 corrected the mistake but adding new name types
* is nevertheless no longer feasible, so act as if no other
* SNI types can exist, to simplify parsing.
*
* Also note that the RFC permits only one SNI value per type,
* i.e., we can only have a single hostname.
*/
if (!PACKET_get_1(&sni, &servname_type)
|| servname_type != TLSEXT_NAMETYPE_host_name
|| !PACKET_as_length_prefixed_2(&sni, &hostname)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit || SSL_IS_TLS13(s)) {
if (PACKET_remaining(&hostname) > TLSEXT_MAXLEN_host_name) {
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
if (PACKET_contains_zero_byte(&hostname)) {
SSLfatal(s, SSL_AD_UNRECOGNIZED_NAME,
SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
SSL_R_BAD_EXTENSION);
return 0;
}
/*
* Store the requested SNI in the SSL as temporary storage.
* If we accept it, it will get stored in the SSL_SESSION as well.
*/
OPENSSL_free(s->ext.hostname);
s->ext.hostname = NULL;
if (!PACKET_strndup(&hostname, &s->ext.hostname)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->servername_done = 1;
}
if (s->hit) {
/*
* TODO(openssl-team): if the SNI doesn't match, we MUST
* fall back to a full handshake.
*/
s->servername_done = (s->session->ext.hostname != NULL)
&& PACKET_equal(&hostname, s->session->ext.hostname,
strlen(s->session->ext.hostname));
if (!s->servername_done && s->session->ext.hostname != NULL)
s->ext.early_data_ok = 0;
}
return 1;
}
int tls_parse_ctos_maxfragmentlen(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
unsigned int value;
if (PACKET_remaining(pkt) != 1 || !PACKET_get_1(pkt, &value)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
SSL_R_BAD_EXTENSION);
return 0;
}
/* Received |value| should be a valid max-fragment-length code. */
if (!IS_MAX_FRAGMENT_LENGTH_EXT_VALID(value)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
/*
* RFC 6066: The negotiated length applies for the duration of the session
* including session resumptions.
* We should receive the same code as in resumed session !
*/
if (s->hit && s->session->ext.max_fragment_len_mode != value) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_CTOS_MAXFRAGMENTLEN,
SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
return 0;
}
/*
* Store it in session, so it'll become binding for us
* and we'll include it in a next Server Hello.
*/
s->session->ext.max_fragment_len_mode = value;
return 1;
}
#ifndef OPENSSL_NO_SRP
int tls_parse_ctos_srp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET srp_I;
if (!PACKET_as_length_prefixed_1(pkt, &srp_I)
|| PACKET_contains_zero_byte(&srp_I)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_SRP,
SSL_R_BAD_EXTENSION);
return 0;
}
/*
* TODO(openssl-team): currently, we re-authenticate the user
* upon resumption. Instead, we MUST ignore the login.
*/
if (!PACKET_strndup(&srp_I, &s->srp_ctx.login)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_SRP,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
#endif
#ifndef OPENSSL_NO_EC
int tls_parse_ctos_ec_pt_formats(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
PACKET ec_point_format_list;
if (!PACKET_as_length_prefixed_1(pkt, &ec_point_format_list)
|| PACKET_remaining(&ec_point_format_list) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS,
SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit) {
if (!PACKET_memdup(&ec_point_format_list,
&s->session->ext.ecpointformats,
&s->session->ext.ecpointformats_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
#endif /* OPENSSL_NO_EC */
int tls_parse_ctos_session_ticket(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->ext.session_ticket_cb &&
!s->ext.session_ticket_cb(s, PACKET_data(pkt),
PACKET_remaining(pkt),
s->ext.session_ticket_cb_arg)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int tls_parse_ctos_sig_algs_cert(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
PACKET supported_sig_algs;
if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
|| PACKET_remaining(&supported_sig_algs) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 1)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_SIG_ALGS_CERT, SSL_R_BAD_EXTENSION);
return 0;
}
return 1;
}
int tls_parse_ctos_sig_algs(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET supported_sig_algs;
if (!PACKET_as_length_prefixed_2(pkt, &supported_sig_algs)
|| PACKET_remaining(&supported_sig_algs) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit && !tls1_save_sigalgs(s, &supported_sig_algs, 0)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_SIG_ALGS, SSL_R_BAD_EXTENSION);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_OCSP
int tls_parse_ctos_status_request(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
PACKET responder_id_list, exts;
/* We ignore this in a resumption handshake */
if (s->hit)
return 1;
/* Not defined if we get one of these in a client Certificate */
if (x != NULL)
return 1;
if (!PACKET_get_1(pkt, (unsigned int *)&s->ext.status_type)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
if (s->ext.status_type != TLSEXT_STATUSTYPE_ocsp) {
/*
* We don't know what to do with any other type so ignore it.
*/
s->ext.status_type = TLSEXT_STATUSTYPE_nothing;
return 1;
}
if (!PACKET_get_length_prefixed_2 (pkt, &responder_id_list)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
/*
* We remove any OCSP_RESPIDs from a previous handshake
* to prevent unbounded memory growth - CVE-2016-6304
*/
sk_OCSP_RESPID_pop_free(s->ext.ocsp.ids, OCSP_RESPID_free);
if (PACKET_remaining(&responder_id_list) > 0) {
s->ext.ocsp.ids = sk_OCSP_RESPID_new_null();
if (s->ext.ocsp.ids == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_MALLOC_FAILURE);
return 0;
}
} else {
s->ext.ocsp.ids = NULL;
}
while (PACKET_remaining(&responder_id_list) > 0) {
OCSP_RESPID *id;
PACKET responder_id;
const unsigned char *id_data;
if (!PACKET_get_length_prefixed_2(&responder_id_list, &responder_id)
|| PACKET_remaining(&responder_id) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
id_data = PACKET_data(&responder_id);
/* TODO(size_t): Convert d2i_* to size_t */
id = d2i_OCSP_RESPID(NULL, &id_data,
(int)PACKET_remaining(&responder_id));
if (id == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
if (id_data != PACKET_end(&responder_id)) {
OCSP_RESPID_free(id);
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
if (!sk_OCSP_RESPID_push(s->ext.ocsp.ids, id)) {
OCSP_RESPID_free(id);
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
return 0;
}
}
/* Read in request_extensions */
if (!PACKET_as_length_prefixed_2(pkt, &exts)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
if (PACKET_remaining(&exts) > 0) {
const unsigned char *ext_data = PACKET_data(&exts);
sk_X509_EXTENSION_pop_free(s->ext.ocsp.exts,
X509_EXTENSION_free);
s->ext.ocsp.exts =
d2i_X509_EXTENSIONS(NULL, &ext_data, (int)PACKET_remaining(&exts));
if (s->ext.ocsp.exts == NULL || ext_data != PACKET_end(&exts)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_STATUS_REQUEST, SSL_R_BAD_EXTENSION);
return 0;
}
}
return 1;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_parse_ctos_npn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
/*
* We shouldn't accept this extension on a
* renegotiation.
*/
if (SSL_IS_FIRST_HANDSHAKE(s))
s->s3->npn_seen = 1;
return 1;
}
#endif
/*
* Save the ALPN extension in a ClientHello.|pkt| holds the contents of the ALPN
* extension, not including type and length. Returns: 1 on success, 0 on error.
*/
int tls_parse_ctos_alpn(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET protocol_list, save_protocol_list, protocol;
if (!SSL_IS_FIRST_HANDSHAKE(s))
return 1;
if (!PACKET_as_length_prefixed_2(pkt, &protocol_list)
|| PACKET_remaining(&protocol_list) < 2) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
SSL_R_BAD_EXTENSION);
return 0;
}
save_protocol_list = protocol_list;
do {
/* Protocol names can't be empty. */
if (!PACKET_get_length_prefixed_1(&protocol_list, &protocol)
|| PACKET_remaining(&protocol) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
SSL_R_BAD_EXTENSION);
return 0;
}
} while (PACKET_remaining(&protocol_list) != 0);
OPENSSL_free(s->s3->alpn_proposed);
s->s3->alpn_proposed = NULL;
s->s3->alpn_proposed_len = 0;
if (!PACKET_memdup(&save_protocol_list,
&s->s3->alpn_proposed, &s->s3->alpn_proposed_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_SRTP
int tls_parse_ctos_use_srtp(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
STACK_OF(SRTP_PROTECTION_PROFILE) *srvr;
unsigned int ct, mki_len, id;
int i, srtp_pref;
PACKET subpkt;
/* Ignore this if we have no SRTP profiles */
if (SSL_get_srtp_profiles(s) == NULL)
return 1;
/* Pull off the length of the cipher suite list and check it is even */
if (!PACKET_get_net_2(pkt, &ct) || (ct & 1) != 0
|| !PACKET_get_sub_packet(pkt, &subpkt, ct)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
srvr = SSL_get_srtp_profiles(s);
s->srtp_profile = NULL;
/* Search all profiles for a match initially */
srtp_pref = sk_SRTP_PROTECTION_PROFILE_num(srvr);
while (PACKET_remaining(&subpkt)) {
if (!PACKET_get_net_2(&subpkt, &id)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
/*
* Only look for match in profiles of higher preference than
* current match.
* If no profiles have been have been configured then this
* does nothing.
*/
for (i = 0; i < srtp_pref; i++) {
SRTP_PROTECTION_PROFILE *sprof =
sk_SRTP_PROTECTION_PROFILE_value(srvr, i);
if (sprof->id == id) {
s->srtp_profile = sprof;
srtp_pref = i;
break;
}
}
}
/* Now extract the MKI value as a sanity check, but discard it for now */
if (!PACKET_get_1(pkt, &mki_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
SSL_R_BAD_SRTP_PROTECTION_PROFILE_LIST);
return 0;
}
if (!PACKET_forward(pkt, mki_len)
|| PACKET_remaining(pkt)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_USE_SRTP,
SSL_R_BAD_SRTP_MKI_VALUE);
return 0;
}
return 1;
}
#endif
int tls_parse_ctos_etm(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
if (!(s->options & SSL_OP_NO_ENCRYPT_THEN_MAC))
s->ext.use_etm = 1;
return 1;
}
/*
* Process a psk_kex_modes extension received in the ClientHello. |pkt| contains
* the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
*/
int tls_parse_ctos_psk_kex_modes(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
PACKET psk_kex_modes;
unsigned int mode;
if (!PACKET_as_length_prefixed_1(pkt, &psk_kex_modes)
|| PACKET_remaining(&psk_kex_modes) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK_KEX_MODES,
SSL_R_BAD_EXTENSION);
return 0;
}
while (PACKET_get_1(&psk_kex_modes, &mode)) {
if (mode == TLSEXT_KEX_MODE_KE_DHE)
s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE_DHE;
else if (mode == TLSEXT_KEX_MODE_KE
&& (s->options & SSL_OP_ALLOW_NO_DHE_KEX) != 0)
s->ext.psk_kex_mode |= TLSEXT_KEX_MODE_FLAG_KE;
}
#endif
return 1;
}
/*
* Process a key_share extension received in the ClientHello. |pkt| contains
* the raw PACKET data for the extension. Returns 1 on success or 0 on failure.
*/
int tls_parse_ctos_key_share(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned int group_id;
PACKET key_share_list, encoded_pt;
const uint16_t *clntgroups, *srvrgroups;
size_t clnt_num_groups, srvr_num_groups;
int found = 0;
if (s->hit && (s->ext.psk_kex_mode & TLSEXT_KEX_MODE_FLAG_KE_DHE) == 0)
return 1;
/* Sanity check */
if (s->s3->peer_tmp != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!PACKET_as_length_prefixed_2(pkt, &key_share_list)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/* Get our list of supported groups */
tls1_get_supported_groups(s, &srvrgroups, &srvr_num_groups);
/* Get the clients list of supported groups. */
tls1_get_peer_groups(s, &clntgroups, &clnt_num_groups);
if (clnt_num_groups == 0) {
/*
* This can only happen if the supported_groups extension was not sent,
* because we verify that the length is non-zero when we process that
* extension.
*/
SSLfatal(s, SSL_AD_MISSING_EXTENSION, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION);
return 0;
}
if (s->s3->group_id != 0 && PACKET_remaining(&key_share_list) == 0) {
/*
* If we set a group_id already, then we must have sent an HRR
* requesting a new key_share. If we haven't got one then that is an
* error
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
SSL_R_BAD_KEY_SHARE);
return 0;
}
while (PACKET_remaining(&key_share_list) > 0) {
if (!PACKET_get_net_2(&key_share_list, &group_id)
|| !PACKET_get_length_prefixed_2(&key_share_list, &encoded_pt)
|| PACKET_remaining(&encoded_pt) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/*
* If we already found a suitable key_share we loop through the
* rest to verify the structure, but don't process them.
*/
if (found)
continue;
/*
* If we sent an HRR then the key_share sent back MUST be for the group
* we requested, and must be the only key_share sent.
*/
if (s->s3->group_id != 0
&& (group_id != s->s3->group_id
|| PACKET_remaining(&key_share_list) != 0)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Check if this share is in supported_groups sent from client */
if (!check_in_list(s, group_id, clntgroups, clnt_num_groups, 0)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_KEY_SHARE);
return 0;
}
/* Check if this share is for a group we can use */
if (!check_in_list(s, group_id, srvrgroups, srvr_num_groups, 1)) {
/* Share not suitable */
continue;
}
if ((s->s3->peer_tmp = ssl_generate_param_group(group_id)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_KEY_SHARE,
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
return 0;
}
s->s3->group_id = group_id;
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_CTOS_KEY_SHARE, SSL_R_BAD_ECPOINT);
return 0;
}
found = 1;
}
#endif
return 1;
}
int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned int format, version, key_share, group_id;
EVP_MD_CTX *hctx;
EVP_PKEY *pkey;
PACKET cookie, raw, chhash, appcookie;
WPACKET hrrpkt;
const unsigned char *data, *mdin, *ciphdata;
unsigned char hmac[SHA256_DIGEST_LENGTH];
unsigned char hrr[MAX_HRR_SIZE];
size_t rawlen, hmaclen, hrrlen, ciphlen;
unsigned long tm, now;
/* Ignore any cookie if we're not set up to verify it */
if (s->ctx->verify_stateless_cookie_cb == NULL
|| (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
return 1;
if (!PACKET_as_length_prefixed_2(pkt, &cookie)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
raw = cookie;
data = PACKET_data(&raw);
rawlen = PACKET_remaining(&raw);
if (rawlen < SHA256_DIGEST_LENGTH
|| !PACKET_forward(&raw, rawlen - SHA256_DIGEST_LENGTH)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
mdin = PACKET_data(&raw);
/* Verify the HMAC of the cookie */
hctx = EVP_MD_CTX_create();
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
s->session_ctx->ext.cookie_hmac_key,
sizeof(s->session_ctx->ext
.cookie_hmac_key));
if (hctx == NULL || pkey == NULL) {
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
ERR_R_MALLOC_FAILURE);
return 0;
}
hmaclen = SHA256_DIGEST_LENGTH;
if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
|| EVP_DigestSign(hctx, hmac, &hmaclen, data,
rawlen - SHA256_DIGEST_LENGTH) <= 0
|| hmaclen != SHA256_DIGEST_LENGTH) {
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
ERR_R_INTERNAL_ERROR);
return 0;
}
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
if (CRYPTO_memcmp(hmac, mdin, SHA256_DIGEST_LENGTH) != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_COOKIE_MISMATCH);
return 0;
}
if (!PACKET_get_net_2(&cookie, &format)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/* Check the cookie format is something we recognise. Ignore it if not */
if (format != COOKIE_STATE_FORMAT_VERSION)
return 1;
/*
* The rest of these checks really shouldn't fail since we have verified the
* HMAC above.
*/
/* Check the version number is sane */
if (!PACKET_get_net_2(&cookie, &version)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
if (version != TLS1_3_VERSION) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_BAD_PROTOCOL_VERSION_NUMBER);
return 0;
}
if (!PACKET_get_net_2(&cookie, &group_id)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
ciphdata = PACKET_data(&cookie);
if (!PACKET_forward(&cookie, 2)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
if (group_id != s->s3->group_id
|| s->s3->tmp.new_cipher
!= ssl_get_cipher_by_char(s, ciphdata, 0)) {
/*
* We chose a different cipher or group id this time around to what is
* in the cookie. Something must have changed.
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_BAD_CIPHER);
return 0;
}
if (!PACKET_get_1(&cookie, &key_share)
|| !PACKET_get_net_4(&cookie, &tm)
|| !PACKET_get_length_prefixed_2(&cookie, &chhash)
|| !PACKET_get_length_prefixed_1(&cookie, &appcookie)
|| PACKET_remaining(&cookie) != SHA256_DIGEST_LENGTH) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/* We tolerate a cookie age of up to 10 minutes (= 60 * 10 seconds) */
now = (unsigned long)time(NULL);
if (tm > now || (now - tm) > 600) {
/* Cookie is stale. Ignore it */
return 1;
}
/* Verify the app cookie */
if (s->ctx->verify_stateless_cookie_cb(s, PACKET_data(&appcookie),
PACKET_remaining(&appcookie)) == 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PARSE_CTOS_COOKIE,
SSL_R_COOKIE_MISMATCH);
return 0;
}
/*
* Reconstruct the HRR that we would have sent in response to the original
* ClientHello so we can add it to the transcript hash.
* Note: This won't work with custom HRR extensions
*/
if (!WPACKET_init_static_len(&hrrpkt, hrr, sizeof(hrr), 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!WPACKET_put_bytes_u8(&hrrpkt, SSL3_MT_SERVER_HELLO)
|| !WPACKET_start_sub_packet_u24(&hrrpkt)
|| !WPACKET_put_bytes_u16(&hrrpkt, TLS1_2_VERSION)
|| !WPACKET_memcpy(&hrrpkt, hrrrandom, SSL3_RANDOM_SIZE)
|| !WPACKET_sub_memcpy_u8(&hrrpkt, s->tmp_session_id,
s->tmp_session_id_len)
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, &hrrpkt,
&ciphlen)
|| !WPACKET_put_bytes_u8(&hrrpkt, 0)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|| !WPACKET_put_bytes_u16(&hrrpkt, s->version)
|| !WPACKET_close(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (key_share) {
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|| !WPACKET_put_bytes_u16(&hrrpkt, s->s3->group_id)
|| !WPACKET_close(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_cookie)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
|| !WPACKET_sub_memcpy_u16(&hrrpkt, data, rawlen)
|| !WPACKET_close(&hrrpkt) /* cookie extension */
|| !WPACKET_close(&hrrpkt) /* extension block */
|| !WPACKET_close(&hrrpkt) /* message */
|| !WPACKET_get_total_written(&hrrpkt, &hrrlen)
|| !WPACKET_finish(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* Reconstruct the transcript hash */
if (!create_synthetic_message_hash(s, PACKET_data(&chhash),
PACKET_remaining(&chhash), hrr,
hrrlen)) {
/* SSLfatal() already called */
return 0;
}
/* Act as if this ClientHello came after a HelloRetryRequest */
s->hello_retry_request = 1;
s->ext.cookieok = 1;
#endif
return 1;
}
#ifndef OPENSSL_NO_EC
int tls_parse_ctos_supported_groups(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
PACKET supported_groups_list;
/* Each group is 2 bytes and we must have at least 1. */
if (!PACKET_as_length_prefixed_2(pkt, &supported_groups_list)
|| PACKET_remaining(&supported_groups_list) == 0
|| (PACKET_remaining(&supported_groups_list) % 2) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS, SSL_R_BAD_EXTENSION);
return 0;
}
if (!s->hit || SSL_IS_TLS13(s)) {
OPENSSL_free(s->session->ext.supportedgroups);
s->session->ext.supportedgroups = NULL;
s->session->ext.supportedgroups_len = 0;
if (!tls1_save_u16(&supported_groups_list,
&s->session->ext.supportedgroups,
&s->session->ext.supportedgroups_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
return 1;
}
#endif
int tls_parse_ctos_ems(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
/* The extension must always be empty */
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_EMS, SSL_R_BAD_EXTENSION);
return 0;
}
s->s3->flags |= TLS1_FLAGS_RECEIVED_EXTMS;
return 1;
}
int tls_parse_ctos_early_data(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
return 0;
}
if (s->hello_retry_request != SSL_HRR_NONE) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PARSE_CTOS_EARLY_DATA, SSL_R_BAD_EXTENSION);
return 0;
}
return 1;
}
static SSL_TICKET_STATUS tls_get_stateful_ticket(SSL *s, PACKET *tick,
SSL_SESSION **sess)
{
SSL_SESSION *tmpsess = NULL;
s->ext.ticket_expected = 1;
switch (PACKET_remaining(tick)) {
case 0:
return SSL_TICKET_EMPTY;
case SSL_MAX_SSL_SESSION_ID_LENGTH:
break;
default:
return SSL_TICKET_NO_DECRYPT;
}
tmpsess = lookup_sess_in_cache(s, PACKET_data(tick),
SSL_MAX_SSL_SESSION_ID_LENGTH);
if (tmpsess == NULL)
return SSL_TICKET_NO_DECRYPT;
*sess = tmpsess;
return SSL_TICKET_SUCCESS;
}
int tls_parse_ctos_psk(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
size_t chainidx)
{
PACKET identities, binders, binder;
size_t binderoffset, hashsize;
SSL_SESSION *sess = NULL;
unsigned int id, i, ext = 0;
const EVP_MD *md = NULL;
/*
* If we have no PSK kex mode that we recognise then we can't resume so
* ignore this extension
*/
if ((s->ext.psk_kex_mode
& (TLSEXT_KEX_MODE_FLAG_KE | TLSEXT_KEX_MODE_FLAG_KE_DHE)) == 0)
return 1;
if (!PACKET_get_length_prefixed_2(pkt, &identities)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
return 0;
}
s->ext.ticket_expected = 0;
for (id = 0; PACKET_remaining(&identities) != 0; id++) {
PACKET identity;
unsigned long ticket_agel;
size_t idlen;
if (!PACKET_get_length_prefixed_2(&identities, &identity)
|| !PACKET_get_net_4(&identities, &ticket_agel)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
return 0;
}
idlen = PACKET_remaining(&identity);
if (s->psk_find_session_cb != NULL
&& !s->psk_find_session_cb(s, PACKET_data(&identity), idlen,
&sess)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_PSK, SSL_R_BAD_EXTENSION);
return 0;
}
#ifndef OPENSSL_NO_PSK
if(sess == NULL
&& s->psk_server_callback != NULL
&& idlen <= PSK_MAX_IDENTITY_LEN) {
char *pskid = NULL;
unsigned char pskdata[PSK_MAX_PSK_LEN];
unsigned int pskdatalen;
if (!PACKET_strndup(&identity, &pskid)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
return 0;
}
pskdatalen = s->psk_server_callback(s, pskid, pskdata,
sizeof(pskdata));
OPENSSL_free(pskid);
if (pskdatalen > PSK_MAX_PSK_LEN) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
return 0;
} else if (pskdatalen > 0) {
const SSL_CIPHER *cipher;
const unsigned char tls13_aes128gcmsha256_id[] = { 0x13, 0x01 };
/*
* We found a PSK using an old style callback. We don't know
* the digest so we default to SHA256 as per the TLSv1.3 spec
*/
cipher = SSL_CIPHER_find(s, tls13_aes128gcmsha256_id);
if (cipher == NULL) {
OPENSSL_cleanse(pskdata, pskdatalen);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
return 0;
}
sess = SSL_SESSION_new();
if (sess == NULL
|| !SSL_SESSION_set1_master_key(sess, pskdata,
pskdatalen)
|| !SSL_SESSION_set_cipher(sess, cipher)
|| !SSL_SESSION_set_protocol_version(sess,
TLS1_3_VERSION)) {
OPENSSL_cleanse(pskdata, pskdatalen);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_cleanse(pskdata, pskdatalen);
}
}
#endif /* OPENSSL_NO_PSK */
if (sess != NULL) {
/* We found a PSK */
SSL_SESSION *sesstmp = ssl_session_dup(sess, 0);
if (sesstmp == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
return 0;
}
SSL_SESSION_free(sess);
sess = sesstmp;
/*
* We've just been told to use this session for this context so
* make sure the sid_ctx matches up.
*/
memcpy(sess->sid_ctx, s->sid_ctx, s->sid_ctx_length);
sess->sid_ctx_length = s->sid_ctx_length;
ext = 1;
if (id == 0)
s->ext.early_data_ok = 1;
s->ext.ticket_expected = 1;
} else {
uint32_t ticket_age = 0, now, agesec, agems;
int ret;
/*
* If we are using anti-replay protection then we behave as if
* SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
* is no point in using full stateless tickets.
*/
if ((s->options & SSL_OP_NO_TICKET) != 0
|| (s->max_early_data > 0
&& (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))
ret = tls_get_stateful_ticket(s, &identity, &sess);
else
ret = tls_decrypt_ticket(s, PACKET_data(&identity),
PACKET_remaining(&identity), NULL, 0,
&sess);
if (ret == SSL_TICKET_EMPTY) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
SSL_R_BAD_EXTENSION);
return 0;
}
if (ret == SSL_TICKET_FATAL_ERR_MALLOC
|| ret == SSL_TICKET_FATAL_ERR_OTHER) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PARSE_CTOS_PSK, ERR_R_INTERNAL_ERROR);
return 0;
}
if (ret == SSL_TICKET_NONE || ret == SSL_TICKET_NO_DECRYPT)
continue;
/* Check for replay */
if (s->max_early_data > 0
&& (s->options & SSL_OP_NO_ANTI_REPLAY) == 0
&& !SSL_CTX_remove_session(s->session_ctx, sess)) {
SSL_SESSION_free(sess);
sess = NULL;
continue;
}
ticket_age = (uint32_t)ticket_agel;
now = (uint32_t)time(NULL);
agesec = now - (uint32_t)sess->time;
agems = agesec * (uint32_t)1000;
ticket_age -= sess->ext.tick_age_add;
/*
* For simplicity we do our age calculations in seconds. If the
* client does it in ms then it could appear that their ticket age
* is longer than ours (our ticket age calculation should always be
* slightly longer than the client's due to the network latency).
* Therefore we add 1000ms to our age calculation to adjust for
* rounding errors.
*/
if (id == 0
&& sess->timeout >= (long)agesec
&& agems / (uint32_t)1000 == agesec
&& ticket_age <= agems + 1000
&& ticket_age + TICKET_AGE_ALLOWANCE >= agems + 1000) {
/*
* Ticket age is within tolerance and not expired. We allow it
* for early data
*/
s->ext.early_data_ok = 1;
}
}
md = ssl_md(sess->cipher->algorithm2);
if (md != ssl_md(s->s3->tmp.new_cipher->algorithm2)) {
/* The ciphersuite is not compatible with this session. */
SSL_SESSION_free(sess);
sess = NULL;
s->ext.early_data_ok = 0;
s->ext.ticket_expected = 0;
continue;
}
break;
}
if (sess == NULL)
return 1;
binderoffset = PACKET_data(pkt) - (const unsigned char *)s->init_buf->data;
hashsize = EVP_MD_size(md);
if (!PACKET_get_length_prefixed_2(pkt, &binders)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
SSL_R_BAD_EXTENSION);
goto err;
}
for (i = 0; i <= id; i++) {
if (!PACKET_get_length_prefixed_1(&binders, &binder)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
SSL_R_BAD_EXTENSION);
goto err;
}
}
if (PACKET_remaining(&binder) != hashsize) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_PSK,
SSL_R_BAD_EXTENSION);
goto err;
}
if (tls_psk_do_binder(s, md, (const unsigned char *)s->init_buf->data,
binderoffset, PACKET_data(&binder), NULL, sess, 0,
ext) != 1) {
/* SSLfatal() already called */
goto err;
}
- sess->ext.tick_identity = id;
+ s->ext.tick_identity = id;
SSL_SESSION_free(s->session);
s->session = sess;
return 1;
err:
SSL_SESSION_free(sess);
return 0;
}
int tls_parse_ctos_post_handshake_auth(SSL *s, PACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PARSE_CTOS_POST_HANDSHAKE_AUTH,
SSL_R_POST_HANDSHAKE_AUTH_ENCODING_ERR);
return 0;
}
s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
return 1;
}
/*
* Add the server's renegotiation binding
*/
EXT_RETURN tls_construct_stoc_renegotiate(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!s->s3->send_connection_binding)
return EXT_RETURN_NOT_SENT;
/* Still add this even if SSL_OP_NO_RENEGOTIATION is set */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_renegotiate)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)
|| !WPACKET_memcpy(pkt, s->s3->previous_client_finished,
s->s3->previous_client_finished_len)
|| !WPACKET_memcpy(pkt, s->s3->previous_server_finished,
s->s3->previous_server_finished_len)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_RENEGOTIATE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_server_name(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (s->hit || s->servername_done != 1
|| s->ext.hostname == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_server_name)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_SERVER_NAME,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
/* Add/include the server's max fragment len extension into ServerHello */
EXT_RETURN tls_construct_stoc_maxfragmentlen(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!USE_MAX_FRAGMENT_LENGTH_EXT(s->session))
return EXT_RETURN_NOT_SENT;
/*-
* 4 bytes for this extension type and extension length
* 1 byte for the Max Fragment Length code value.
*/
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_max_fragment_length)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u8(pkt, s->session->ext.max_fragment_len_mode)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_MAXFRAGMENTLEN, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_ec_pt_formats(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
unsigned long alg_a = s->s3->tmp.new_cipher->algorithm_auth;
int using_ecc = ((alg_k & SSL_kECDHE) || (alg_a & SSL_aECDSA))
&& (s->session->ext.ecpointformats != NULL);
const unsigned char *plist;
size_t plistlen;
if (!using_ecc)
return EXT_RETURN_NOT_SENT;
tls1_get_formatlist(s, &plist, &plistlen);
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_ec_point_formats)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u8(pkt, plist, plistlen)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_EC_PT_FORMATS, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
#ifndef OPENSSL_NO_EC
EXT_RETURN tls_construct_stoc_supported_groups(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const uint16_t *groups;
size_t numgroups, i, first = 1;
/* s->s3->group_id is non zero if we accepted a key_share */
if (s->s3->group_id == 0)
return EXT_RETURN_NOT_SENT;
/* Get our list of supported groups */
tls1_get_supported_groups(s, &groups, &numgroups);
if (numgroups == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* Copy group ID if supported */
for (i = 0; i < numgroups; i++) {
uint16_t group = groups[i];
if (tls_curve_allowed(s, group, SSL_SECOP_CURVE_SUPPORTED)) {
if (first) {
/*
* Check if the client is already using our preferred group. If
* so we don't need to add this extension
*/
if (s->s3->group_id == group)
return EXT_RETURN_NOT_SENT;
/* Add extension header */
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_groups)
/* Sub-packet for supported_groups extension */
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
first = 0;
}
if (!WPACKET_put_bytes_u16(pkt, group)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
}
}
if (!WPACKET_close(pkt) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_GROUPS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
EXT_RETURN tls_construct_stoc_session_ticket(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!s->ext.ticket_expected || !tls_use_ticket(s)) {
s->ext.ticket_expected = 0;
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_session_ticket)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_SESSION_TICKET, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_OCSP
EXT_RETURN tls_construct_stoc_status_request(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!s->ext.status_expected)
return EXT_RETURN_NOT_SENT;
if (SSL_IS_TLS13(s) && chainidx != 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_status_request)
|| !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/*
* In TLSv1.3 we include the certificate status itself. In <= TLSv1.2 we
* send back an empty extension, with the certificate status appearing as a
* separate message
*/
if (SSL_IS_TLS13(s) && !tls_construct_cert_status_body(s, pkt)) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_STATUS_REQUEST, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
#ifndef OPENSSL_NO_NEXTPROTONEG
EXT_RETURN tls_construct_stoc_next_proto_neg(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const unsigned char *npa;
unsigned int npalen;
int ret;
int npn_seen = s->s3->npn_seen;
s->s3->npn_seen = 0;
if (!npn_seen || s->ctx->ext.npn_advertised_cb == NULL)
return EXT_RETURN_NOT_SENT;
ret = s->ctx->ext.npn_advertised_cb(s, &npa, &npalen,
s->ctx->ext.npn_advertised_cb_arg);
if (ret == SSL_TLSEXT_ERR_OK) {
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_next_proto_neg)
|| !WPACKET_sub_memcpy_u16(pkt, npa, npalen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_NEXT_PROTO_NEG,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
s->s3->npn_seen = 1;
}
return EXT_RETURN_SENT;
}
#endif
EXT_RETURN tls_construct_stoc_alpn(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (s->s3->alpn_selected == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt,
TLSEXT_TYPE_application_layer_protocol_negotiation)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_sub_memcpy_u8(pkt, s->s3->alpn_selected,
s->s3->alpn_selected_len)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_ALPN, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#ifndef OPENSSL_NO_SRTP
EXT_RETURN tls_construct_stoc_use_srtp(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (s->srtp_profile == NULL)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_use_srtp)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, 2)
|| !WPACKET_put_bytes_u16(pkt, s->srtp_profile->id)
|| !WPACKET_put_bytes_u8(pkt, 0)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_USE_SRTP,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
#endif
EXT_RETURN tls_construct_stoc_etm(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (!s->ext.use_etm)
return EXT_RETURN_NOT_SENT;
/*
* Don't use encrypt_then_mac if AEAD or RC4 might want to disable
* for other cases too.
*/
if (s->s3->tmp.new_cipher->algorithm_mac == SSL_AEAD
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_RC4
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT
|| s->s3->tmp.new_cipher->algorithm_enc == SSL_eGOST2814789CNT12) {
s->ext.use_etm = 0;
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_encrypt_then_mac)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_ETM,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_ems(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if ((s->s3->flags & TLS1_FLAGS_RECEIVED_EXTMS) == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_extended_master_secret)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EMS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (!ossl_assert(SSL_IS_TLS13(s))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->version)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_key_share(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned char *encodedPoint;
size_t encoded_pt_len = 0;
EVP_PKEY *ckey = s->s3->peer_tmp, *skey = NULL;
if (s->hello_retry_request == SSL_HRR_PENDING) {
if (ckey != NULL) {
/* Original key_share was acceptable so don't ask for another one */
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
if (ckey == NULL) {
/* No key_share received from client - must be resuming */
if (!s->hit || !tls13_generate_handshake_secret(s, NULL, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_NOT_SENT;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_key_share)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
skey = ssl_generate_pkey(ckey);
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
ERR_R_MALLOC_FAILURE);
return EXT_RETURN_FAIL;
}
/* Generate encoding of server key */
encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(skey, &encodedPoint);
if (encoded_pt_len == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
ERR_R_EC_LIB);
EVP_PKEY_free(skey);
return EXT_RETURN_FAIL;
}
if (!WPACKET_sub_memcpy_u16(pkt, encodedPoint, encoded_pt_len)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_KEY_SHARE,
ERR_R_INTERNAL_ERROR);
EVP_PKEY_free(skey);
OPENSSL_free(encodedPoint);
return EXT_RETURN_FAIL;
}
OPENSSL_free(encodedPoint);
/* This causes the crypto state to be updated based on the derived keys */
s->s3->tmp.pkey = skey;
if (ssl_derive(s, skey, ckey, 1) == 0) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
#else
return EXT_RETURN_FAIL;
#endif
}
EXT_RETURN tls_construct_stoc_cookie(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
#ifndef OPENSSL_NO_TLS1_3
unsigned char *hashval1, *hashval2, *appcookie1, *appcookie2, *cookie;
unsigned char *hmac, *hmac2;
size_t startlen, ciphlen, totcookielen, hashlen, hmaclen, appcookielen;
EVP_MD_CTX *hctx;
EVP_PKEY *pkey;
int ret = EXT_RETURN_FAIL;
if ((s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
return EXT_RETURN_NOT_SENT;
if (s->ctx->gen_stateless_cookie_cb == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
SSL_R_NO_COOKIE_CALLBACK_SET);
return EXT_RETURN_FAIL;
}
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_cookie)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_get_total_written(pkt, &startlen)
|| !WPACKET_reserve_bytes(pkt, MAX_COOKIE_SIZE, &cookie)
|| !WPACKET_put_bytes_u16(pkt, COOKIE_STATE_FORMAT_VERSION)
|| !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION)
|| !WPACKET_put_bytes_u16(pkt, s->s3->group_id)
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt,
&ciphlen)
/* Is there a key_share extension present in this HRR? */
|| !WPACKET_put_bytes_u8(pkt, s->s3->peer_tmp == NULL)
|| !WPACKET_put_bytes_u32(pkt, (unsigned int)time(NULL))
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &hashval1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/*
* Get the hash of the initial ClientHello. ssl_handshake_hash() operates
* on raw buffers, so we first reserve sufficient bytes (above) and then
* subsequently allocate them (below)
*/
if (!ssl3_digest_cached_records(s, 0)
|| !ssl_handshake_hash(s, hashval1, EVP_MAX_MD_SIZE, &hashlen)) {
/* SSLfatal() already called */
return EXT_RETURN_FAIL;
}
if (!WPACKET_allocate_bytes(pkt, hashlen, &hashval2)
|| !ossl_assert(hashval1 == hashval2)
|| !WPACKET_close(pkt)
|| !WPACKET_start_sub_packet_u8(pkt)
|| !WPACKET_reserve_bytes(pkt, SSL_COOKIE_LENGTH, &appcookie1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* Generate the application cookie */
if (s->ctx->gen_stateless_cookie_cb(s, appcookie1, &appcookielen) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
return EXT_RETURN_FAIL;
}
if (!WPACKET_allocate_bytes(pkt, appcookielen, &appcookie2)
|| !ossl_assert(appcookie1 == appcookie2)
|| !WPACKET_close(pkt)
|| !WPACKET_get_total_written(pkt, &totcookielen)
|| !WPACKET_reserve_bytes(pkt, SHA256_DIGEST_LENGTH, &hmac)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
hmaclen = SHA256_DIGEST_LENGTH;
totcookielen -= startlen;
if (!ossl_assert(totcookielen <= MAX_COOKIE_SIZE - SHA256_DIGEST_LENGTH)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
/* HMAC the cookie */
hctx = EVP_MD_CTX_create();
pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL,
s->session_ctx->ext.cookie_hmac_key,
sizeof(s->session_ctx->ext
.cookie_hmac_key));
if (hctx == NULL || pkey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_DigestSignInit(hctx, NULL, EVP_sha256(), NULL, pkey) <= 0
|| EVP_DigestSign(hctx, hmac, &hmaclen, cookie,
totcookielen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!ossl_assert(totcookielen + hmaclen <= MAX_COOKIE_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!WPACKET_allocate_bytes(pkt, hmaclen, &hmac2)
|| !ossl_assert(hmac == hmac2)
|| !ossl_assert(cookie == hmac - totcookielen)
|| !WPACKET_close(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_COOKIE,
ERR_R_INTERNAL_ERROR);
goto err;
}
ret = EXT_RETURN_SENT;
err:
EVP_MD_CTX_free(hctx);
EVP_PKEY_free(pkey);
return ret;
#else
return EXT_RETURN_FAIL;
#endif
}
EXT_RETURN tls_construct_stoc_cryptopro_bug(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
const unsigned char cryptopro_ext[36] = {
0xfd, 0xe8, /* 65000 */
0x00, 0x20, /* 32 bytes length */
0x30, 0x1e, 0x30, 0x08, 0x06, 0x06, 0x2a, 0x85,
0x03, 0x02, 0x02, 0x09, 0x30, 0x08, 0x06, 0x06,
0x2a, 0x85, 0x03, 0x02, 0x02, 0x16, 0x30, 0x08,
0x06, 0x06, 0x2a, 0x85, 0x03, 0x02, 0x02, 0x17
};
if (((s->s3->tmp.new_cipher->id & 0xFFFF) != 0x80
&& (s->s3->tmp.new_cipher->id & 0xFFFF) != 0x81)
|| (SSL_get_options(s) & SSL_OP_CRYPTOPRO_TLSEXT_BUG) == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_memcpy(pkt, cryptopro_ext, sizeof(cryptopro_ext))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_CRYPTOPRO_BUG, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_early_data(SSL *s, WPACKET *pkt,
unsigned int context, X509 *x,
size_t chainidx)
{
if (context == SSL_EXT_TLS1_3_NEW_SESSION_TICKET) {
if (s->max_early_data == 0)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_put_bytes_u32(pkt, s->max_early_data)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_early_data)
|| !WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_STOC_EARLY_DATA,
ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
EXT_RETURN tls_construct_stoc_psk(SSL *s, WPACKET *pkt, unsigned int context,
X509 *x, size_t chainidx)
{
if (!s->hit)
return EXT_RETURN_NOT_SENT;
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_psk)
|| !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, s->session->ext.tick_identity)
+ || !WPACKET_put_bytes_u16(pkt, s->ext.tick_identity)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_PSK, ERR_R_INTERNAL_ERROR);
return EXT_RETURN_FAIL;
}
return EXT_RETURN_SENT;
}
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index e56d24dfff60..87800cd8351c 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1,3851 +1,3848 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include <time.h>
#include <assert.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/md5.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/engine.h>
#include <internal/cryptlib.h>
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s, PACKET *pkt);
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt);
static ossl_inline int cert_req_allowed(SSL *s);
static int key_exchange_expected(SSL *s);
static int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk,
WPACKET *pkt);
/*
* Is a CertificateRequest message allowed at the moment or not?
*
* Return values are:
* 1: Yes
* 0: No
*/
static ossl_inline int cert_req_allowed(SSL *s)
{
/* TLS does not like anon-DH with client cert */
if ((s->version > SSL3_VERSION
&& (s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
|| (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aSRP | SSL_aPSK)))
return 0;
return 1;
}
/*
* Should we expect the ServerKeyExchange message or not?
*
* Return values are:
* 1: Yes
* 0: No
*/
static int key_exchange_expected(SSL *s)
{
long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
/*
* Can't skip server key exchange if this is an ephemeral
* ciphersuite or for SRP
*/
if (alg_k & (SSL_kDHE | SSL_kECDHE | SSL_kDHEPSK | SSL_kECDHEPSK
| SSL_kSRP)) {
return 1;
}
return 0;
}
/*
* ossl_statem_client_read_transition() encapsulates the logic for the allowed
* handshake state transitions when a TLS1.3 client is reading messages from the
* server. The message type that the server has sent is provided in |mt|. The
* current state is in |s->statem.hand_state|.
*
* Return values are 1 for success (transition allowed) and 0 on error
* (transition not allowed)
*/
static int ossl_statem_client13_read_transition(SSL *s, int mt)
{
OSSL_STATEM *st = &s->statem;
/*
* Note: There is no case for TLS_ST_CW_CLNT_HELLO, because we haven't
* yet negotiated TLSv1.3 at that point so that is handled by
* ossl_statem_client_read_transition()
*/
switch (st->hand_state) {
default:
break;
case TLS_ST_CW_CLNT_HELLO:
/*
* This must a ClientHello following a HelloRetryRequest, so the only
* thing we can get now is a ServerHello.
*/
if (mt == SSL3_MT_SERVER_HELLO) {
st->hand_state = TLS_ST_CR_SRVR_HELLO;
return 1;
}
break;
case TLS_ST_CR_SRVR_HELLO:
if (mt == SSL3_MT_ENCRYPTED_EXTENSIONS) {
st->hand_state = TLS_ST_CR_ENCRYPTED_EXTENSIONS;
return 1;
}
break;
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
if (s->hit) {
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_CR_FINISHED;
return 1;
}
} else {
if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
st->hand_state = TLS_ST_CR_CERT_REQ;
return 1;
}
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_CR_CERT;
return 1;
}
}
break;
case TLS_ST_CR_CERT_REQ:
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_CR_CERT;
return 1;
}
break;
case TLS_ST_CR_CERT:
if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
st->hand_state = TLS_ST_CR_CERT_VRFY;
return 1;
}
break;
case TLS_ST_CR_CERT_VRFY:
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_CR_FINISHED;
return 1;
}
break;
case TLS_ST_OK:
if (mt == SSL3_MT_NEWSESSION_TICKET) {
st->hand_state = TLS_ST_CR_SESSION_TICKET;
return 1;
}
if (mt == SSL3_MT_KEY_UPDATE) {
st->hand_state = TLS_ST_CR_KEY_UPDATE;
return 1;
}
if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
#if DTLS_MAX_VERSION != DTLS1_2_VERSION
# error TODO(DTLS1.3): Restore digest for PHA before adding message.
#endif
if (!SSL_IS_DTLS(s) && s->post_handshake_auth == SSL_PHA_EXT_SENT) {
s->post_handshake_auth = SSL_PHA_REQUESTED;
/*
* In TLS, this is called before the message is added to the
* digest. In DTLS, this is expected to be called after adding
* to the digest. Either move the digest restore, or add the
* message here after the swap, or do it after the clientFinished?
*/
if (!tls13_restore_handshake_digest_for_pha(s)) {
/* SSLfatal() already called */
return 0;
}
st->hand_state = TLS_ST_CR_CERT_REQ;
return 1;
}
}
break;
}
/* No valid transition found */
return 0;
}
/*
* ossl_statem_client_read_transition() encapsulates the logic for the allowed
* handshake state transitions when the client is reading messages from the
* server. The message type that the server has sent is provided in |mt|. The
* current state is in |s->statem.hand_state|.
*
* Return values are 1 for success (transition allowed) and 0 on error
* (transition not allowed)
*/
int ossl_statem_client_read_transition(SSL *s, int mt)
{
OSSL_STATEM *st = &s->statem;
int ske_expected;
/*
* Note that after writing the first ClientHello we don't know what version
* we are going to negotiate yet, so we don't take this branch until later.
*/
if (SSL_IS_TLS13(s)) {
if (!ossl_statem_client13_read_transition(s, mt))
goto err;
return 1;
}
switch (st->hand_state) {
default:
break;
case TLS_ST_CW_CLNT_HELLO:
if (mt == SSL3_MT_SERVER_HELLO) {
st->hand_state = TLS_ST_CR_SRVR_HELLO;
return 1;
}
if (SSL_IS_DTLS(s)) {
if (mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
return 1;
}
}
break;
case TLS_ST_EARLY_DATA:
/*
* We've not actually selected TLSv1.3 yet, but we have sent early
* data. The only thing allowed now is a ServerHello or a
* HelloRetryRequest.
*/
if (mt == SSL3_MT_SERVER_HELLO) {
st->hand_state = TLS_ST_CR_SRVR_HELLO;
return 1;
}
break;
case TLS_ST_CR_SRVR_HELLO:
if (s->hit) {
if (s->ext.ticket_expected) {
if (mt == SSL3_MT_NEWSESSION_TICKET) {
st->hand_state = TLS_ST_CR_SESSION_TICKET;
return 1;
}
} else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
st->hand_state = TLS_ST_CR_CHANGE;
return 1;
}
} else {
if (SSL_IS_DTLS(s) && mt == DTLS1_MT_HELLO_VERIFY_REQUEST) {
st->hand_state = DTLS_ST_CR_HELLO_VERIFY_REQUEST;
return 1;
} else if (s->version >= TLS1_VERSION
&& s->ext.session_secret_cb != NULL
&& s->session->ext.tick != NULL
&& mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
/*
* Normally, we can tell if the server is resuming the session
* from the session ID. EAP-FAST (RFC 4851), however, relies on
* the next server message after the ServerHello to determine if
* the server is resuming.
*/
s->hit = 1;
st->hand_state = TLS_ST_CR_CHANGE;
return 1;
} else if (!(s->s3->tmp.new_cipher->algorithm_auth
& (SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_CR_CERT;
return 1;
}
} else {
ske_expected = key_exchange_expected(s);
/* SKE is optional for some PSK ciphersuites */
if (ske_expected
|| ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
&& mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
st->hand_state = TLS_ST_CR_KEY_EXCH;
return 1;
}
} else if (mt == SSL3_MT_CERTIFICATE_REQUEST
&& cert_req_allowed(s)) {
st->hand_state = TLS_ST_CR_CERT_REQ;
return 1;
} else if (mt == SSL3_MT_SERVER_DONE) {
st->hand_state = TLS_ST_CR_SRVR_DONE;
return 1;
}
}
}
break;
case TLS_ST_CR_CERT:
/*
* The CertificateStatus message is optional even if
* |ext.status_expected| is set
*/
if (s->ext.status_expected && mt == SSL3_MT_CERTIFICATE_STATUS) {
st->hand_state = TLS_ST_CR_CERT_STATUS;
return 1;
}
/* Fall through */
case TLS_ST_CR_CERT_STATUS:
ske_expected = key_exchange_expected(s);
/* SKE is optional for some PSK ciphersuites */
if (ske_expected || ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)
&& mt == SSL3_MT_SERVER_KEY_EXCHANGE)) {
if (mt == SSL3_MT_SERVER_KEY_EXCHANGE) {
st->hand_state = TLS_ST_CR_KEY_EXCH;
return 1;
}
goto err;
}
/* Fall through */
case TLS_ST_CR_KEY_EXCH:
if (mt == SSL3_MT_CERTIFICATE_REQUEST) {
if (cert_req_allowed(s)) {
st->hand_state = TLS_ST_CR_CERT_REQ;
return 1;
}
goto err;
}
/* Fall through */
case TLS_ST_CR_CERT_REQ:
if (mt == SSL3_MT_SERVER_DONE) {
st->hand_state = TLS_ST_CR_SRVR_DONE;
return 1;
}
break;
case TLS_ST_CW_FINISHED:
if (s->ext.ticket_expected) {
if (mt == SSL3_MT_NEWSESSION_TICKET) {
st->hand_state = TLS_ST_CR_SESSION_TICKET;
return 1;
}
} else if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
st->hand_state = TLS_ST_CR_CHANGE;
return 1;
}
break;
case TLS_ST_CR_SESSION_TICKET:
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
st->hand_state = TLS_ST_CR_CHANGE;
return 1;
}
break;
case TLS_ST_CR_CHANGE:
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_CR_FINISHED;
return 1;
}
break;
case TLS_ST_OK:
if (mt == SSL3_MT_HELLO_REQUEST) {
st->hand_state = TLS_ST_CR_HELLO_REQ;
return 1;
}
break;
}
err:
/* No valid transition found */
if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
BIO *rbio;
/*
* CCS messages don't have a message sequence number so this is probably
* because of an out-of-order CCS. We'll just drop it.
*/
s->init_num = 0;
s->rwstate = SSL_READING;
rbio = SSL_get_rbio(s);
BIO_clear_retry_flags(rbio);
BIO_set_retry_read(rbio);
return 0;
}
SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
SSL_F_OSSL_STATEM_CLIENT_READ_TRANSITION,
SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
/*
* ossl_statem_client13_write_transition() works out what handshake state to
* move to next when the TLSv1.3 client is writing messages to be sent to the
* server.
*/
static WRITE_TRAN ossl_statem_client13_write_transition(SSL *s)
{
OSSL_STATEM *st = &s->statem;
/*
* Note: There are no cases for TLS_ST_BEFORE because we haven't negotiated
* TLSv1.3 yet at that point. They are handled by
* ossl_statem_client_write_transition().
*/
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_CR_CERT_REQ:
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
st->hand_state = TLS_ST_CW_CERT;
return WRITE_TRAN_CONTINUE;
}
/*
* We should only get here if we received a CertificateRequest after
* we already sent close_notify
*/
if (!ossl_assert((s->shutdown & SSL_SENT_SHUTDOWN) != 0)) {
/* Shouldn't happen - same as default case */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_CLIENT13_WRITE_TRANSITION,
ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
}
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CR_FINISHED:
if (s->early_data_state == SSL_EARLY_DATA_WRITE_RETRY
|| s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING)
st->hand_state = TLS_ST_PENDING_EARLY_DATA_END;
else if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
&& s->hello_retry_request == SSL_HRR_NONE)
st->hand_state = TLS_ST_CW_CHANGE;
else
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
: TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_PENDING_EARLY_DATA_END:
if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
st->hand_state = TLS_ST_CW_END_OF_EARLY_DATA;
return WRITE_TRAN_CONTINUE;
}
/* Fall through */
case TLS_ST_CW_END_OF_EARLY_DATA:
case TLS_ST_CW_CHANGE:
st->hand_state = (s->s3->tmp.cert_req != 0) ? TLS_ST_CW_CERT
: TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CW_CERT:
/* If a non-empty Certificate we also send CertificateVerify */
st->hand_state = (s->s3->tmp.cert_req == 1) ? TLS_ST_CW_CERT_VRFY
: TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CW_CERT_VRFY:
st->hand_state = TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CR_KEY_UPDATE:
if (s->key_update != SSL_KEY_UPDATE_NONE) {
st->hand_state = TLS_ST_CW_KEY_UPDATE;
return WRITE_TRAN_CONTINUE;
}
/* Fall through */
case TLS_ST_CW_KEY_UPDATE:
case TLS_ST_CR_SESSION_TICKET:
case TLS_ST_CW_FINISHED:
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_OK:
if (s->key_update != SSL_KEY_UPDATE_NONE) {
st->hand_state = TLS_ST_CW_KEY_UPDATE;
return WRITE_TRAN_CONTINUE;
}
/* Try to read from the server instead */
return WRITE_TRAN_FINISHED;
}
}
/*
* ossl_statem_client_write_transition() works out what handshake state to
* move to next when the client is writing messages to be sent to the server.
*/
WRITE_TRAN ossl_statem_client_write_transition(SSL *s)
{
OSSL_STATEM *st = &s->statem;
/*
* Note that immediately before/after a ClientHello we don't know what
* version we are going to negotiate yet, so we don't take this branch until
* later
*/
if (SSL_IS_TLS13(s))
return ossl_statem_client13_write_transition(s);
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_CLIENT_WRITE_TRANSITION,
ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_OK:
if (!s->renegotiate) {
/*
* We haven't requested a renegotiation ourselves so we must have
* received a message from the server. Better read it.
*/
return WRITE_TRAN_FINISHED;
}
/* Renegotiation */
/* fall thru */
case TLS_ST_BEFORE:
st->hand_state = TLS_ST_CW_CLNT_HELLO;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CW_CLNT_HELLO:
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
/*
* We are assuming this is a TLSv1.3 connection, although we haven't
* actually selected a version yet.
*/
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0)
st->hand_state = TLS_ST_CW_CHANGE;
else
st->hand_state = TLS_ST_EARLY_DATA;
return WRITE_TRAN_CONTINUE;
}
/*
* No transition at the end of writing because we don't know what
* we will be sent
*/
return WRITE_TRAN_FINISHED;
case TLS_ST_CR_SRVR_HELLO:
/*
* We only get here in TLSv1.3. We just received an HRR, so issue a
* CCS unless middlebox compat mode is off, or we already issued one
* because we did early data.
*/
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING)
st->hand_state = TLS_ST_CW_CHANGE;
else
st->hand_state = TLS_ST_CW_CLNT_HELLO;
return WRITE_TRAN_CONTINUE;
case TLS_ST_EARLY_DATA:
return WRITE_TRAN_FINISHED;
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
st->hand_state = TLS_ST_CW_CLNT_HELLO;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CR_SRVR_DONE:
if (s->s3->tmp.cert_req)
st->hand_state = TLS_ST_CW_CERT;
else
st->hand_state = TLS_ST_CW_KEY_EXCH;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CW_CERT:
st->hand_state = TLS_ST_CW_KEY_EXCH;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CW_KEY_EXCH:
/*
* For TLS, cert_req is set to 2, so a cert chain of nothing is
* sent, but no verify packet is sent
*/
/*
* XXX: For now, we do not support client authentication in ECDH
* cipher suites with ECDH (rather than ECDSA) certificates. We
* need to skip the certificate verify message when client's
* ECDH public key is sent inside the client certificate.
*/
if (s->s3->tmp.cert_req == 1) {
st->hand_state = TLS_ST_CW_CERT_VRFY;
} else {
st->hand_state = TLS_ST_CW_CHANGE;
}
if (s->s3->flags & TLS1_FLAGS_SKIP_CERT_VERIFY) {
st->hand_state = TLS_ST_CW_CHANGE;
}
return WRITE_TRAN_CONTINUE;
case TLS_ST_CW_CERT_VRFY:
st->hand_state = TLS_ST_CW_CHANGE;
return WRITE_TRAN_CONTINUE;
case TLS_ST_CW_CHANGE:
if (s->hello_retry_request == SSL_HRR_PENDING) {
st->hand_state = TLS_ST_CW_CLNT_HELLO;
} else if (s->early_data_state == SSL_EARLY_DATA_CONNECTING) {
st->hand_state = TLS_ST_EARLY_DATA;
} else {
#if defined(OPENSSL_NO_NEXTPROTONEG)
st->hand_state = TLS_ST_CW_FINISHED;
#else
if (!SSL_IS_DTLS(s) && s->s3->npn_seen)
st->hand_state = TLS_ST_CW_NEXT_PROTO;
else
st->hand_state = TLS_ST_CW_FINISHED;
#endif
}
return WRITE_TRAN_CONTINUE;
#if !defined(OPENSSL_NO_NEXTPROTONEG)
case TLS_ST_CW_NEXT_PROTO:
st->hand_state = TLS_ST_CW_FINISHED;
return WRITE_TRAN_CONTINUE;
#endif
case TLS_ST_CW_FINISHED:
if (s->hit) {
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
} else {
return WRITE_TRAN_FINISHED;
}
case TLS_ST_CR_FINISHED:
if (s->hit) {
st->hand_state = TLS_ST_CW_CHANGE;
return WRITE_TRAN_CONTINUE;
} else {
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
}
case TLS_ST_CR_HELLO_REQ:
/*
* If we can renegotiate now then do so, otherwise wait for a more
* convenient time.
*/
if (ssl3_renegotiate_check(s, 1)) {
if (!tls_setup_handshake(s)) {
/* SSLfatal() already called */
return WRITE_TRAN_ERROR;
}
st->hand_state = TLS_ST_CW_CLNT_HELLO;
return WRITE_TRAN_CONTINUE;
}
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
}
}
/*
* Perform any pre work that needs to be done prior to sending a message from
* the client to the server.
*/
WORK_STATE ossl_statem_client_pre_work(SSL *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* No pre work to be done */
break;
case TLS_ST_CW_CLNT_HELLO:
s->shutdown = 0;
if (SSL_IS_DTLS(s)) {
/* every DTLS ClientHello resets Finished MAC */
if (!ssl3_init_finished_mac(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
}
break;
case TLS_ST_CW_CHANGE:
if (SSL_IS_DTLS(s)) {
if (s->hit) {
/*
* We're into the last flight so we don't retransmit these
* messages unless we need to.
*/
st->use_timer = 0;
}
#ifndef OPENSSL_NO_SCTP
if (BIO_dgram_is_sctp(SSL_get_wbio(s))) {
/* Calls SSLfatal() as required */
return dtls_wait_for_dry(s);
}
#endif
}
break;
case TLS_ST_PENDING_EARLY_DATA_END:
/*
* If we've been called by SSL_do_handshake()/SSL_write(), or we did not
* attempt to write early data before calling SSL_read() then we press
* on with the handshake. Otherwise we pause here.
*/
if (s->early_data_state == SSL_EARLY_DATA_FINISHED_WRITING
|| s->early_data_state == SSL_EARLY_DATA_NONE)
return WORK_FINISHED_CONTINUE;
/* Fall through */
case TLS_ST_EARLY_DATA:
return tls_finish_handshake(s, wst, 0, 1);
case TLS_ST_OK:
/* Calls SSLfatal() as required */
return tls_finish_handshake(s, wst, 1, 1);
}
return WORK_FINISHED_CONTINUE;
}
/*
* Perform any work that needs to be done after sending a message from the
* client to the server.
*/
WORK_STATE ossl_statem_client_post_work(SSL *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
s->init_num = 0;
switch (st->hand_state) {
default:
/* No post work to be done */
break;
case TLS_ST_CW_CLNT_HELLO:
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
&& s->max_early_data > 0) {
/*
* We haven't selected TLSv1.3 yet so we don't call the change
* cipher state function associated with the SSL_METHOD. Instead
* we call tls13_change_cipher_state() directly.
*/
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0) {
if (!tls13_change_cipher_state(s,
SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
}
/* else we're in compat mode so we delay flushing until after CCS */
} else if (!statem_flush(s)) {
return WORK_MORE_A;
}
if (SSL_IS_DTLS(s)) {
/* Treat the next message as the first packet */
s->first_packet = 1;
}
break;
case TLS_ST_CW_END_OF_EARLY_DATA:
/*
* We set the enc_write_ctx back to NULL because we may end up writing
* in cleartext again if we get a HelloRetryRequest from the server.
*/
EVP_CIPHER_CTX_free(s->enc_write_ctx);
s->enc_write_ctx = NULL;
break;
case TLS_ST_CW_KEY_EXCH:
if (tls_client_key_exchange_post_work(s) == 0) {
/* SSLfatal() already called */
return WORK_ERROR;
}
break;
case TLS_ST_CW_CHANGE:
if (SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING)
break;
if (s->early_data_state == SSL_EARLY_DATA_CONNECTING
&& s->max_early_data > 0) {
/*
* We haven't selected TLSv1.3 yet so we don't call the change
* cipher state function associated with the SSL_METHOD. Instead
* we call tls13_change_cipher_state() directly.
*/
if (!tls13_change_cipher_state(s,
SSL3_CC_EARLY | SSL3_CHANGE_CIPHER_CLIENT_WRITE))
return WORK_ERROR;
break;
}
s->session->cipher = s->s3->tmp.new_cipher;
#ifdef OPENSSL_NO_COMP
s->session->compress_meth = 0;
#else
if (s->s3->tmp.new_compression == NULL)
s->session->compress_meth = 0;
else
s->session->compress_meth = s->s3->tmp.new_compression->id;
#endif
if (!s->method->ssl3_enc->setup_key_block(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
if (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
if (SSL_IS_DTLS(s)) {
#ifndef OPENSSL_NO_SCTP
if (s->hit) {
/*
* Change to new shared key of SCTP-Auth, will be ignored if
* no SCTP used.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
0, NULL);
}
#endif
dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
}
break;
case TLS_ST_CW_FINISHED:
#ifndef OPENSSL_NO_SCTP
if (wst == WORK_MORE_A && SSL_IS_DTLS(s) && s->hit == 0) {
/*
* Change to new shared key of SCTP-Auth, will be ignored if
* no SCTP used.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
0, NULL);
}
#endif
if (statem_flush(s) != 1)
return WORK_MORE_B;
if (SSL_IS_TLS13(s)) {
if (!tls13_save_handshake_digest_for_pha(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
if (s->post_handshake_auth != SSL_PHA_REQUESTED) {
if (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_CLIENT_WRITE)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
}
}
break;
case TLS_ST_CW_KEY_UPDATE:
if (statem_flush(s) != 1)
return WORK_MORE_A;
if (!tls13_update_key(s, 1)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
break;
}
return WORK_FINISHED_CONTINUE;
}
/*
* Get the message construction function and message type for sending from the
* client
*
* Valid return values are:
* 1: Success
* 0: Error
*/
int ossl_statem_client_construct_message(SSL *s, WPACKET *pkt,
confunc_f *confunc, int *mt)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_CLIENT_CONSTRUCT_MESSAGE,
SSL_R_BAD_HANDSHAKE_STATE);
return 0;
case TLS_ST_CW_CHANGE:
if (SSL_IS_DTLS(s))
*confunc = dtls_construct_change_cipher_spec;
else
*confunc = tls_construct_change_cipher_spec;
*mt = SSL3_MT_CHANGE_CIPHER_SPEC;
break;
case TLS_ST_CW_CLNT_HELLO:
*confunc = tls_construct_client_hello;
*mt = SSL3_MT_CLIENT_HELLO;
break;
case TLS_ST_CW_END_OF_EARLY_DATA:
*confunc = tls_construct_end_of_early_data;
*mt = SSL3_MT_END_OF_EARLY_DATA;
break;
case TLS_ST_PENDING_EARLY_DATA_END:
*confunc = NULL;
*mt = SSL3_MT_DUMMY;
break;
case TLS_ST_CW_CERT:
*confunc = tls_construct_client_certificate;
*mt = SSL3_MT_CERTIFICATE;
break;
case TLS_ST_CW_KEY_EXCH:
*confunc = tls_construct_client_key_exchange;
*mt = SSL3_MT_CLIENT_KEY_EXCHANGE;
break;
case TLS_ST_CW_CERT_VRFY:
*confunc = tls_construct_cert_verify;
*mt = SSL3_MT_CERTIFICATE_VERIFY;
break;
#if !defined(OPENSSL_NO_NEXTPROTONEG)
case TLS_ST_CW_NEXT_PROTO:
*confunc = tls_construct_next_proto;
*mt = SSL3_MT_NEXT_PROTO;
break;
#endif
case TLS_ST_CW_FINISHED:
*confunc = tls_construct_finished;
*mt = SSL3_MT_FINISHED;
break;
case TLS_ST_CW_KEY_UPDATE:
*confunc = tls_construct_key_update;
*mt = SSL3_MT_KEY_UPDATE;
break;
}
return 1;
}
/*
* Returns the maximum allowed length for the current message that we are
* reading. Excludes the message header.
*/
size_t ossl_statem_client_max_message_size(SSL *s)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* Shouldn't happen */
return 0;
case TLS_ST_CR_SRVR_HELLO:
return SERVER_HELLO_MAX_LENGTH;
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
return HELLO_VERIFY_REQUEST_MAX_LENGTH;
case TLS_ST_CR_CERT:
return s->max_cert_list;
case TLS_ST_CR_CERT_VRFY:
return SSL3_RT_MAX_PLAIN_LENGTH;
case TLS_ST_CR_CERT_STATUS:
return SSL3_RT_MAX_PLAIN_LENGTH;
case TLS_ST_CR_KEY_EXCH:
return SERVER_KEY_EXCH_MAX_LENGTH;
case TLS_ST_CR_CERT_REQ:
/*
* Set to s->max_cert_list for compatibility with previous releases. In
* practice these messages can get quite long if servers are configured
* to provide a long list of acceptable CAs
*/
return s->max_cert_list;
case TLS_ST_CR_SRVR_DONE:
return SERVER_HELLO_DONE_MAX_LENGTH;
case TLS_ST_CR_CHANGE:
if (s->version == DTLS1_BAD_VER)
return 3;
return CCS_MAX_LENGTH;
case TLS_ST_CR_SESSION_TICKET:
return SSL3_RT_MAX_PLAIN_LENGTH;
case TLS_ST_CR_FINISHED:
return FINISHED_MAX_LENGTH;
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
return ENCRYPTED_EXTENSIONS_MAX_LENGTH;
case TLS_ST_CR_KEY_UPDATE:
return KEY_UPDATE_MAX_LENGTH;
}
}
/*
* Process a message that the client has been received from the server.
*/
MSG_PROCESS_RETURN ossl_statem_client_process_message(SSL *s, PACKET *pkt)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_CLIENT_PROCESS_MESSAGE,
ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
case TLS_ST_CR_SRVR_HELLO:
return tls_process_server_hello(s, pkt);
case DTLS_ST_CR_HELLO_VERIFY_REQUEST:
return dtls_process_hello_verify(s, pkt);
case TLS_ST_CR_CERT:
return tls_process_server_certificate(s, pkt);
case TLS_ST_CR_CERT_VRFY:
return tls_process_cert_verify(s, pkt);
case TLS_ST_CR_CERT_STATUS:
return tls_process_cert_status(s, pkt);
case TLS_ST_CR_KEY_EXCH:
return tls_process_key_exchange(s, pkt);
case TLS_ST_CR_CERT_REQ:
return tls_process_certificate_request(s, pkt);
case TLS_ST_CR_SRVR_DONE:
return tls_process_server_done(s, pkt);
case TLS_ST_CR_CHANGE:
return tls_process_change_cipher_spec(s, pkt);
case TLS_ST_CR_SESSION_TICKET:
return tls_process_new_session_ticket(s, pkt);
case TLS_ST_CR_FINISHED:
return tls_process_finished(s, pkt);
case TLS_ST_CR_HELLO_REQ:
return tls_process_hello_req(s, pkt);
case TLS_ST_CR_ENCRYPTED_EXTENSIONS:
return tls_process_encrypted_extensions(s, pkt);
case TLS_ST_CR_KEY_UPDATE:
return tls_process_key_update(s, pkt);
}
}
/*
* Perform any further processing required following the receipt of a message
* from the server
*/
WORK_STATE ossl_statem_client_post_process_message(SSL *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_CLIENT_POST_PROCESS_MESSAGE,
ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
case TLS_ST_CR_CERT_VRFY:
case TLS_ST_CR_CERT_REQ:
return tls_prepare_client_certificate(s, wst);
}
}
int tls_construct_client_hello(SSL *s, WPACKET *pkt)
{
unsigned char *p;
size_t sess_id_len;
int i, protverr;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp;
#endif
SSL_SESSION *sess = s->session;
unsigned char *session_id;
/* Work out what SSL/TLS/DTLS version to use */
protverr = ssl_set_client_hello_version(s);
if (protverr != 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
protverr);
return 0;
}
if (sess == NULL
|| !ssl_version_supported(s, sess->ssl_version, NULL)
|| !SSL_SESSION_is_resumable(sess)) {
if (s->hello_retry_request == SSL_HRR_NONE
&& !ssl_get_new_session(s, 0)) {
/* SSLfatal() already called */
return 0;
}
}
/* else use the pre-loaded session */
p = s->s3->client_random;
/*
* for DTLS if client_random is initialized, reuse it, we are
* required to use same upon reply to HelloVerify
*/
if (SSL_IS_DTLS(s)) {
size_t idx;
i = 1;
for (idx = 0; idx < sizeof(s->s3->client_random); idx++) {
if (p[idx]) {
i = 0;
break;
}
}
} else {
i = (s->hello_retry_request == SSL_HRR_NONE);
}
if (i && ssl_fill_hello_random(s, 0, p, sizeof(s->s3->client_random),
DOWNGRADE_NONE) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
/*-
* version indicates the negotiated version: for example from
* an SSLv2/v3 compatible client hello). The client_version
* field is the maximum version we permit and it is also
* used in RSA encrypted premaster secrets. Some servers can
* choke if we initially report a higher version then
* renegotiate to a lower one in the premaster secret. This
* didn't happen with TLS 1.0 as most servers supported it
* but it can with TLS 1.1 or later if the server only supports
* 1.0.
*
* Possible scenario with previous logic:
* 1. Client hello indicates TLS 1.2
* 2. Server hello says TLS 1.0
* 3. RSA encrypted premaster secret uses 1.2.
* 4. Handshake proceeds using TLS 1.0.
* 5. Server sends hello request to renegotiate.
* 6. Client hello indicates TLS v1.0 as we now
* know that is maximum server supports.
* 7. Server chokes on RSA encrypted premaster secret
* containing version 1.0.
*
* For interoperability it should be OK to always use the
* maximum version we support in client hello and then rely
* on the checking of version to ensure the servers isn't
* being inconsistent: for example initially negotiating with
* TLS 1.0 and renegotiating with TLS 1.2. We do this by using
* client_version in client hello and not resetting it to
* the negotiated version.
*
* For TLS 1.3 we always set the ClientHello version to 1.2 and rely on the
* supported_versions extension for the real supported versions.
*/
if (!WPACKET_put_bytes_u16(pkt, s->client_version)
|| !WPACKET_memcpy(pkt, s->s3->client_random, SSL3_RANDOM_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* Session ID */
session_id = s->session->session_id;
if (s->new_session || s->session->ssl_version == TLS1_3_VERSION) {
if (s->version == TLS1_3_VERSION
&& (s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0) {
sess_id_len = sizeof(s->tmp_session_id);
s->tmp_session_id_len = sess_id_len;
session_id = s->tmp_session_id;
if (s->hello_retry_request == SSL_HRR_NONE
&& RAND_bytes(s->tmp_session_id, sess_id_len) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
} else {
sess_id_len = 0;
}
} else {
assert(s->session->session_id_length <= sizeof(s->session->session_id));
sess_id_len = s->session->session_id_length;
if (s->version == TLS1_3_VERSION) {
s->tmp_session_id_len = sess_id_len;
memcpy(s->tmp_session_id, s->session->session_id, sess_id_len);
}
}
if (!WPACKET_start_sub_packet_u8(pkt)
|| (sess_id_len != 0 && !WPACKET_memcpy(pkt, session_id,
sess_id_len))
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* cookie stuff for DTLS */
if (SSL_IS_DTLS(s)) {
if (s->d1->cookie_len > sizeof(s->d1->cookie)
|| !WPACKET_sub_memcpy_u8(pkt, s->d1->cookie,
s->d1->cookie_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
/* Ciphers supported */
if (!WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!ssl_cipher_list_to_bytes(s, SSL_get_ciphers(s), pkt)) {
/* SSLfatal() already called */
return 0;
}
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* COMPRESSION */
if (!WPACKET_start_sub_packet_u8(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
#ifndef OPENSSL_NO_COMP
if (ssl_allow_compression(s)
&& s->ctx->comp_methods
&& (SSL_IS_DTLS(s) || s->s3->tmp.max_ver < TLS1_3_VERSION)) {
int compnum = sk_SSL_COMP_num(s->ctx->comp_methods);
for (i = 0; i < compnum; i++) {
comp = sk_SSL_COMP_value(s->ctx->comp_methods, i);
if (!WPACKET_put_bytes_u8(pkt, comp->id)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
}
#endif
/* Add the NULL method */
if (!WPACKET_put_bytes_u8(pkt, 0) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* TLS extensions */
if (!tls_construct_extensions(s, pkt, SSL_EXT_CLIENT_HELLO, NULL, 0)) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
MSG_PROCESS_RETURN dtls_process_hello_verify(SSL *s, PACKET *pkt)
{
size_t cookie_len;
PACKET cookiepkt;
if (!PACKET_forward(pkt, 2)
|| !PACKET_get_length_prefixed_1(pkt, &cookiepkt)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
cookie_len = PACKET_remaining(&cookiepkt);
if (cookie_len > sizeof(s->d1->cookie)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
SSL_R_LENGTH_TOO_LONG);
return MSG_PROCESS_ERROR;
}
if (!PACKET_copy_bytes(&cookiepkt, s->d1->cookie, cookie_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_DTLS_PROCESS_HELLO_VERIFY,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
s->d1->cookie_len = cookie_len;
return MSG_PROCESS_FINISHED_READING;
}
static int set_client_ciphersuite(SSL *s, const unsigned char *cipherchars)
{
STACK_OF(SSL_CIPHER) *sk;
const SSL_CIPHER *c;
int i;
c = ssl_get_cipher_by_char(s, cipherchars, 0);
if (c == NULL) {
/* unknown cipher */
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
SSL_R_UNKNOWN_CIPHER_RETURNED);
return 0;
}
/*
* If it is a disabled cipher we either didn't send it in client hello,
* or it's not allowed for the selected protocol. So we return an error.
*/
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_CHECK, 1)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
SSL_R_WRONG_CIPHER_RETURNED);
return 0;
}
sk = ssl_get_ciphers_by_id(s);
i = sk_SSL_CIPHER_find(sk, c);
if (i < 0) {
/* we did not say we would use this cipher */
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
SSL_R_WRONG_CIPHER_RETURNED);
return 0;
}
if (SSL_IS_TLS13(s) && s->s3->tmp.new_cipher != NULL
&& s->s3->tmp.new_cipher->id != c->id) {
/* ServerHello selected a different ciphersuite to that in the HRR */
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
SSL_R_WRONG_CIPHER_RETURNED);
return 0;
}
/*
* Depending on the session caching (internal/external), the cipher
* and/or cipher_id values may not be set. Make sure that cipher_id is
* set and use it for comparison.
*/
if (s->session->cipher != NULL)
s->session->cipher_id = s->session->cipher->id;
if (s->hit && (s->session->cipher_id != c->id)) {
if (SSL_IS_TLS13(s)) {
/*
* In TLSv1.3 it is valid for the server to select a different
* ciphersuite as long as the hash is the same.
*/
if (ssl_md(c->algorithm2)
!= ssl_md(s->session->cipher->algorithm2)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_SET_CLIENT_CIPHERSUITE,
SSL_R_CIPHERSUITE_DIGEST_HAS_CHANGED);
return 0;
}
} else {
/*
* Prior to TLSv1.3 resuming a session always meant using the same
* ciphersuite.
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_SET_CLIENT_CIPHERSUITE,
SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED);
return 0;
}
}
s->s3->tmp.new_cipher = c;
return 1;
}
MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
{
PACKET session_id, extpkt;
size_t session_id_len;
const unsigned char *cipherchars;
int hrr = 0;
unsigned int compression;
unsigned int sversion;
unsigned int context;
RAW_EXTENSION *extensions = NULL;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp;
#endif
if (!PACKET_get_net_2(pkt, &sversion)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
/* load the server random */
if (s->version == TLS1_3_VERSION
&& sversion == TLS1_2_VERSION
&& PACKET_remaining(pkt) >= SSL3_RANDOM_SIZE
&& memcmp(hrrrandom, PACKET_data(pkt), SSL3_RANDOM_SIZE) == 0) {
s->hello_retry_request = SSL_HRR_PENDING;
hrr = 1;
if (!PACKET_forward(pkt, SSL3_RANDOM_SIZE)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
} else {
if (!PACKET_copy_bytes(pkt, s->s3->server_random, SSL3_RANDOM_SIZE)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
}
/* Get the session-id. */
if (!PACKET_get_length_prefixed_1(pkt, &session_id)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
session_id_len = PACKET_remaining(&session_id);
if (session_id_len > sizeof(s->session->session_id)
|| session_id_len > SSL3_SESSION_ID_SIZE) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_SSL3_SESSION_ID_TOO_LONG);
goto err;
}
if (!PACKET_get_bytes(pkt, &cipherchars, TLS_CIPHER_LEN)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_get_1(pkt, &compression)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
/* TLS extensions */
if (PACKET_remaining(pkt) == 0 && !hrr) {
PACKET_null_init(&extpkt);
} else if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_BAD_LENGTH);
goto err;
}
if (!hrr) {
if (!tls_collect_extensions(s, &extpkt,
SSL_EXT_TLS1_2_SERVER_HELLO
| SSL_EXT_TLS1_3_SERVER_HELLO,
&extensions, NULL, 1)) {
/* SSLfatal() already called */
goto err;
}
if (!ssl_choose_client_version(s, sversion, extensions)) {
/* SSLfatal() already called */
goto err;
}
}
if (SSL_IS_TLS13(s) || hrr) {
if (compression != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto err;
}
if (session_id_len != s->tmp_session_id_len
|| memcmp(PACKET_data(&session_id), s->tmp_session_id,
session_id_len) != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PROCESS_SERVER_HELLO, SSL_R_INVALID_SESSION_ID);
goto err;
}
}
if (hrr) {
if (!set_client_ciphersuite(s, cipherchars)) {
/* SSLfatal() already called */
goto err;
}
return tls_process_as_hello_retry_request(s, &extpkt);
}
/*
* Now we have chosen the version we need to check again that the extensions
* are appropriate for this version.
*/
context = SSL_IS_TLS13(s) ? SSL_EXT_TLS1_3_SERVER_HELLO
: SSL_EXT_TLS1_2_SERVER_HELLO;
if (!tls_validate_all_contexts(s, context, extensions)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_BAD_EXTENSION);
goto err;
}
s->hit = 0;
if (SSL_IS_TLS13(s)) {
/*
* In TLSv1.3 a ServerHello message signals a key change so the end of
* the message must be on a record boundary.
*/
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_NOT_ON_RECORD_BOUNDARY);
goto err;
}
/* This will set s->hit if we are resuming */
if (!tls_parse_extension(s, TLSEXT_IDX_psk,
SSL_EXT_TLS1_3_SERVER_HELLO,
extensions, NULL, 0)) {
/* SSLfatal() already called */
goto err;
}
} else {
/*
* Check if we can resume the session based on external pre-shared
* secret. EAP-FAST (RFC 4851) supports two types of session resumption.
* Resumption based on server-side state works with session IDs.
* Resumption based on pre-shared Protected Access Credentials (PACs)
* works by overriding the SessionTicket extension at the application
* layer, and does not send a session ID. (We do not know whether
* EAP-FAST servers would honour the session ID.) Therefore, the session
* ID alone is not a reliable indicator of session resumption, so we
* first check if we can resume, and later peek at the next handshake
* message to see if the server wants to resume.
*/
if (s->version >= TLS1_VERSION
&& s->ext.session_secret_cb != NULL && s->session->ext.tick) {
const SSL_CIPHER *pref_cipher = NULL;
/*
* s->session->master_key_length is a size_t, but this is an int for
* backwards compat reasons
*/
int master_key_length;
master_key_length = sizeof(s->session->master_key);
if (s->ext.session_secret_cb(s, s->session->master_key,
&master_key_length,
NULL, &pref_cipher,
s->ext.session_secret_cb_arg)
&& master_key_length > 0) {
s->session->master_key_length = master_key_length;
s->session->cipher = pref_cipher ?
pref_cipher : ssl_get_cipher_by_char(s, cipherchars, 0);
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (session_id_len != 0
&& session_id_len == s->session->session_id_length
&& memcmp(PACKET_data(&session_id), s->session->session_id,
session_id_len) == 0)
s->hit = 1;
}
if (s->hit) {
if (s->sid_ctx_length != s->session->sid_ctx_length
|| memcmp(s->session->sid_ctx, s->sid_ctx, s->sid_ctx_length)) {
/* actually a client application bug */
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_ATTEMPT_TO_REUSE_SESSION_IN_DIFFERENT_CONTEXT);
goto err;
}
} else {
/*
* If we were trying for session-id reuse but the server
* didn't resume, make a new SSL_SESSION.
* In the case of EAP-FAST and PAC, we do not send a session ID,
* so the PAC-based session secret is always preserved. It'll be
* overwritten if the server refuses resumption.
*/
- if (s->session->session_id_length > 0
- || (SSL_IS_TLS13(s)
- && s->session->ext.tick_identity
- != TLSEXT_PSK_BAD_IDENTITY)) {
+ if (s->session->session_id_length > 0) {
tsan_counter(&s->session_ctx->stats.sess_miss);
if (!ssl_get_new_session(s, 0)) {
/* SSLfatal() already called */
goto err;
}
}
s->session->ssl_version = s->version;
/*
* In TLSv1.2 and below we save the session id we were sent so we can
* resume it later. In TLSv1.3 the session id we were sent is just an
* echo of what we originally sent in the ClientHello and should not be
* used for resumption.
*/
if (!SSL_IS_TLS13(s)) {
s->session->session_id_length = session_id_len;
/* session_id_len could be 0 */
if (session_id_len > 0)
memcpy(s->session->session_id, PACKET_data(&session_id),
session_id_len);
}
}
/* Session version and negotiated protocol version should match */
if (s->version != s->session->ssl_version) {
SSLfatal(s, SSL_AD_PROTOCOL_VERSION, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_SSL_SESSION_VERSION_MISMATCH);
goto err;
}
/*
* Now that we know the version, update the check to see if it's an allowed
* version.
*/
s->s3->tmp.min_ver = s->version;
s->s3->tmp.max_ver = s->version;
if (!set_client_ciphersuite(s, cipherchars)) {
/* SSLfatal() already called */
goto err;
}
#ifdef OPENSSL_NO_COMP
if (compression != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
goto err;
}
/*
* If compression is disabled we'd better not try to resume a session
* using compression.
*/
if (s->session->compress_meth != 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_INCONSISTENT_COMPRESSION);
goto err;
}
#else
if (s->hit && compression != s->session->compress_meth) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_OLD_SESSION_COMPRESSION_ALGORITHM_NOT_RETURNED);
goto err;
}
if (compression == 0)
comp = NULL;
else if (!ssl_allow_compression(s)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_COMPRESSION_DISABLED);
goto err;
} else {
comp = ssl3_comp_find(s->ctx->comp_methods, compression);
}
if (compression != 0 && comp == NULL) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SERVER_HELLO,
SSL_R_UNSUPPORTED_COMPRESSION_ALGORITHM);
goto err;
} else {
s->s3->tmp.new_compression = comp;
}
#endif
if (!tls_parse_all_extensions(s, context, extensions, NULL, 0, 1)) {
/* SSLfatal() already called */
goto err;
}
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && s->hit) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
size_t labellen;
/*
* Add new shared key for SCTP-Auth, will be ignored if
* no SCTP used.
*/
memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
sizeof(DTLS1_SCTP_AUTH_LABEL));
/* Don't include the terminating zero. */
labellen = sizeof(labelbuffer) - 1;
if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
labellen += 1;
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey),
labelbuffer,
labellen, NULL, 0, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_HELLO,
ERR_R_INTERNAL_ERROR);
goto err;
}
BIO_ctrl(SSL_get_wbio(s),
BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
}
#endif
/*
* In TLSv1.3 we have some post-processing to change cipher state, otherwise
* we're done with this message
*/
if (SSL_IS_TLS13(s)
&& (!s->method->ssl3_enc->setup_key_block(s)
|| !s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_READ))) {
/* SSLfatal() already called */
goto err;
}
OPENSSL_free(extensions);
return MSG_PROCESS_CONTINUE_READING;
err:
OPENSSL_free(extensions);
return MSG_PROCESS_ERROR;
}
static MSG_PROCESS_RETURN tls_process_as_hello_retry_request(SSL *s,
PACKET *extpkt)
{
RAW_EXTENSION *extensions = NULL;
/*
* If we were sending early_data then the enc_write_ctx is now invalid and
* should not be used.
*/
EVP_CIPHER_CTX_free(s->enc_write_ctx);
s->enc_write_ctx = NULL;
if (!tls_collect_extensions(s, extpkt, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
&extensions, NULL, 1)
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST,
extensions, NULL, 0, 1)) {
/* SSLfatal() already called */
goto err;
}
OPENSSL_free(extensions);
extensions = NULL;
if (s->ext.tls13_cookie_len == 0
#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
&& s->s3->tmp.pkey != NULL
#endif
) {
/*
* We didn't receive a cookie or a new key_share so the next
* ClientHello will not change
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PROCESS_AS_HELLO_RETRY_REQUEST,
SSL_R_NO_CHANGE_FOLLOWING_HRR);
goto err;
}
/*
* Re-initialise the Transcript Hash. We're going to prepopulate it with
* a synthetic message_hash in place of ClientHello1.
*/
if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
/* SSLfatal() already called */
goto err;
}
/*
* Add this message to the Transcript Hash. Normally this is done
* automatically prior to the message processing stage. However due to the
* need to create the synthetic message hash, we defer that step until now
* for HRR messages.
*/
if (!ssl3_finish_mac(s, (unsigned char *)s->init_buf->data,
s->init_num + SSL3_HM_HEADER_LENGTH)) {
/* SSLfatal() already called */
goto err;
}
return MSG_PROCESS_FINISHED_READING;
err:
OPENSSL_free(extensions);
return MSG_PROCESS_ERROR;
}
MSG_PROCESS_RETURN tls_process_server_certificate(SSL *s, PACKET *pkt)
{
int i;
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
unsigned long cert_list_len, cert_len;
X509 *x = NULL;
const unsigned char *certstart, *certbytes;
STACK_OF(X509) *sk = NULL;
EVP_PKEY *pkey = NULL;
size_t chainidx, certidx;
unsigned int context = 0;
const SSL_CERT_LOOKUP *clu;
if ((sk = sk_X509_new_null()) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
ERR_R_MALLOC_FAILURE);
goto err;
}
if ((SSL_IS_TLS13(s) && !PACKET_get_1(pkt, &context))
|| context != 0
|| !PACKET_get_net_3(pkt, &cert_list_len)
|| PACKET_remaining(pkt) != cert_list_len
|| PACKET_remaining(pkt) == 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_LENGTH_MISMATCH);
goto err;
}
for (chainidx = 0; PACKET_remaining(pkt); chainidx++) {
if (!PACKET_get_net_3(pkt, &cert_len)
|| !PACKET_get_bytes(pkt, &certbytes, cert_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
certstart = certbytes;
x = d2i_X509(NULL, (const unsigned char **)&certbytes, cert_len);
if (x == NULL) {
SSLfatal(s, SSL_AD_BAD_CERTIFICATE,
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, ERR_R_ASN1_LIB);
goto err;
}
if (certbytes != (certstart + cert_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
if (SSL_IS_TLS13(s)) {
RAW_EXTENSION *rawexts = NULL;
PACKET extensions;
if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_BAD_LENGTH);
goto err;
}
if (!tls_collect_extensions(s, &extensions,
SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
NULL, chainidx == 0)
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
rawexts, x, chainidx,
PACKET_remaining(pkt) == 0)) {
OPENSSL_free(rawexts);
/* SSLfatal already called */
goto err;
}
OPENSSL_free(rawexts);
}
if (!sk_X509_push(sk, x)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
ERR_R_MALLOC_FAILURE);
goto err;
}
x = NULL;
}
i = ssl_verify_cert_chain(s, sk);
/*
* The documented interface is that SSL_VERIFY_PEER should be set in order
* for client side verification of the server certificate to take place.
* However, historically the code has only checked that *any* flag is set
* to cause server verification to take place. Use of the other flags makes
* no sense in client mode. An attempt to clean up the semantics was
* reverted because at least one application *only* set
* SSL_VERIFY_FAIL_IF_NO_PEER_CERT. Prior to the clean up this still caused
* server verification to take place, after the clean up it silently did
* nothing. SSL_CTX_set_verify()/SSL_set_verify() cannot validate the flags
* sent to them because they are void functions. Therefore, we now use the
* (less clean) historic behaviour of performing validation if any flag is
* set. The *documented* interface remains the same.
*/
if (s->verify_mode != SSL_VERIFY_NONE && i <= 0) {
SSLfatal(s, ssl_x509err2alert(s->verify_result),
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_CERTIFICATE_VERIFY_FAILED);
goto err;
}
ERR_clear_error(); /* but we keep s->verify_result */
if (i > 1) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE, i);
goto err;
}
s->session->peer_chain = sk;
/*
* Inconsistency alert: cert_chain does include the peer's certificate,
* which we don't include in statem_srvr.c
*/
x = sk_X509_value(sk, 0);
sk = NULL;
pkey = X509_get0_pubkey(x);
if (pkey == NULL || EVP_PKEY_missing_parameters(pkey)) {
x = NULL;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS);
goto err;
}
if ((clu = ssl_cert_lookup_by_pkey(pkey, &certidx)) == NULL) {
x = NULL;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
goto err;
}
/*
* Check certificate type is consistent with ciphersuite. For TLS 1.3
* skip check since TLS 1.3 ciphersuites can be used with any certificate
* type.
*/
if (!SSL_IS_TLS13(s)) {
if ((clu->amask & s->s3->tmp.new_cipher->algorithm_auth) == 0) {
x = NULL;
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PROCESS_SERVER_CERTIFICATE,
SSL_R_WRONG_CERTIFICATE_TYPE);
goto err;
}
}
s->session->peer_type = certidx;
X509_free(s->session->peer);
X509_up_ref(x);
s->session->peer = x;
s->session->verify_result = s->verify_result;
x = NULL;
/* Save the current hash state for when we receive the CertificateVerify */
if (SSL_IS_TLS13(s)
&& !ssl_handshake_hash(s, s->cert_verify_hash,
sizeof(s->cert_verify_hash),
&s->cert_verify_hash_len)) {
/* SSLfatal() already called */;
goto err;
}
ret = MSG_PROCESS_CONTINUE_READING;
err:
X509_free(x);
sk_X509_pop_free(sk, X509_free);
return ret;
}
static int tls_process_ske_psk_preamble(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_PSK
PACKET psk_identity_hint;
/* PSK ciphersuites are preceded by an identity hint */
if (!PACKET_get_length_prefixed_2(pkt, &psk_identity_hint)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/*
* Store PSK identity hint for later use, hint is used in
* tls_construct_client_key_exchange. Assume that the maximum length of
* a PSK identity hint can be as long as the maximum length of a PSK
* identity.
*/
if (PACKET_remaining(&psk_identity_hint) > PSK_MAX_IDENTITY_LEN) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
if (PACKET_remaining(&psk_identity_hint) == 0) {
OPENSSL_free(s->session->psk_identity_hint);
s->session->psk_identity_hint = NULL;
} else if (!PACKET_strndup(&psk_identity_hint,
&s->session->psk_identity_hint)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_PSK_PREAMBLE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_ske_srp(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
{
#ifndef OPENSSL_NO_SRP
PACKET prime, generator, salt, server_pub;
if (!PACKET_get_length_prefixed_2(pkt, &prime)
|| !PACKET_get_length_prefixed_2(pkt, &generator)
|| !PACKET_get_length_prefixed_1(pkt, &salt)
|| !PACKET_get_length_prefixed_2(pkt, &server_pub)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
SSL_R_LENGTH_MISMATCH);
return 0;
}
/* TODO(size_t): Convert BN_bin2bn() calls */
if ((s->srp_ctx.N =
BN_bin2bn(PACKET_data(&prime),
(int)PACKET_remaining(&prime), NULL)) == NULL
|| (s->srp_ctx.g =
BN_bin2bn(PACKET_data(&generator),
(int)PACKET_remaining(&generator), NULL)) == NULL
|| (s->srp_ctx.s =
BN_bin2bn(PACKET_data(&salt),
(int)PACKET_remaining(&salt), NULL)) == NULL
|| (s->srp_ctx.B =
BN_bin2bn(PACKET_data(&server_pub),
(int)PACKET_remaining(&server_pub), NULL)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
ERR_R_BN_LIB);
return 0;
}
if (!srp_verify_server_param(s)) {
/* SSLfatal() already called */
return 0;
}
/* We must check if there is a certificate */
if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
*pkey = X509_get0_pubkey(s->session->peer);
return 1;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_SRP,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_ske_dhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
{
#ifndef OPENSSL_NO_DH
PACKET prime, generator, pub_key;
EVP_PKEY *peer_tmp = NULL;
DH *dh = NULL;
BIGNUM *p = NULL, *g = NULL, *bnpub_key = NULL;
int check_bits = 0;
if (!PACKET_get_length_prefixed_2(pkt, &prime)
|| !PACKET_get_length_prefixed_2(pkt, &generator)
|| !PACKET_get_length_prefixed_2(pkt, &pub_key)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
peer_tmp = EVP_PKEY_new();
dh = DH_new();
if (peer_tmp == NULL || dh == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
ERR_R_MALLOC_FAILURE);
goto err;
}
/* TODO(size_t): Convert these calls */
p = BN_bin2bn(PACKET_data(&prime), (int)PACKET_remaining(&prime), NULL);
g = BN_bin2bn(PACKET_data(&generator), (int)PACKET_remaining(&generator),
NULL);
bnpub_key = BN_bin2bn(PACKET_data(&pub_key),
(int)PACKET_remaining(&pub_key), NULL);
if (p == NULL || g == NULL || bnpub_key == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
ERR_R_BN_LIB);
goto err;
}
/* test non-zero pubkey */
if (BN_is_zero(bnpub_key)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
SSL_R_BAD_DH_VALUE);
goto err;
}
if (!DH_set0_pqg(dh, p, NULL, g)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
ERR_R_BN_LIB);
goto err;
}
p = g = NULL;
if (DH_check_params(dh, &check_bits) == 0 || check_bits != 0) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_DHE,
SSL_R_BAD_DH_VALUE);
goto err;
}
if (!DH_set0_key(dh, bnpub_key, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
ERR_R_BN_LIB);
goto err;
}
bnpub_key = NULL;
if (!ssl_security(s, SSL_SECOP_TMP_DH, DH_security_bits(dh), 0, dh)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_SKE_DHE,
SSL_R_DH_KEY_TOO_SMALL);
goto err;
}
if (EVP_PKEY_assign_DH(peer_tmp, dh) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
ERR_R_EVP_LIB);
goto err;
}
s->s3->peer_tmp = peer_tmp;
/*
* FIXME: This makes assumptions about which ciphersuites come with
* public keys. We should have a less ad-hoc way of doing this
*/
if (s->s3->tmp.new_cipher->algorithm_auth & (SSL_aRSA | SSL_aDSS))
*pkey = X509_get0_pubkey(s->session->peer);
/* else anonymous DH, so no certificate or pkey. */
return 1;
err:
BN_free(p);
BN_free(g);
BN_free(bnpub_key);
DH_free(dh);
EVP_PKEY_free(peer_tmp);
return 0;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_DHE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_ske_ecdhe(SSL *s, PACKET *pkt, EVP_PKEY **pkey)
{
#ifndef OPENSSL_NO_EC
PACKET encoded_pt;
unsigned int curve_type, curve_id;
/*
* Extract elliptic curve parameters and the server's ephemeral ECDH
* public key. We only support named (not generic) curves and
* ECParameters in this case is just three bytes.
*/
if (!PACKET_get_1(pkt, &curve_type) || !PACKET_get_net_2(pkt, &curve_id)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
SSL_R_LENGTH_TOO_SHORT);
return 0;
}
/*
* Check curve is named curve type and one of our preferences, if not
* server has sent an invalid curve.
*/
if (curve_type != NAMED_CURVE_TYPE
|| !tls1_check_group_id(s, curve_id, 1)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
SSL_R_WRONG_CURVE);
return 0;
}
if ((s->s3->peer_tmp = ssl_generate_param_group(curve_id)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
SSL_R_UNABLE_TO_FIND_ECDH_PARAMETERS);
return 0;
}
if (!PACKET_get_length_prefixed_1(pkt, &encoded_pt)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
if (!EVP_PKEY_set1_tls_encodedpoint(s->s3->peer_tmp,
PACKET_data(&encoded_pt),
PACKET_remaining(&encoded_pt))) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_SKE_ECDHE,
SSL_R_BAD_ECPOINT);
return 0;
}
/*
* The ECC/TLS specification does not mention the use of DSA to sign
* ECParameters in the server key exchange message. We do support RSA
* and ECDSA.
*/
if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aECDSA)
*pkey = X509_get0_pubkey(s->session->peer);
else if (s->s3->tmp.new_cipher->algorithm_auth & SSL_aRSA)
*pkey = X509_get0_pubkey(s->session->peer);
/* else anonymous ECDH, so no certificate or pkey. */
return 1;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SKE_ECDHE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
MSG_PROCESS_RETURN tls_process_key_exchange(SSL *s, PACKET *pkt)
{
long alg_k;
EVP_PKEY *pkey = NULL;
EVP_MD_CTX *md_ctx = NULL;
EVP_PKEY_CTX *pctx = NULL;
PACKET save_param_start, signature;
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
save_param_start = *pkt;
#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DH)
EVP_PKEY_free(s->s3->peer_tmp);
s->s3->peer_tmp = NULL;
#endif
if (alg_k & SSL_PSK) {
if (!tls_process_ske_psk_preamble(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
}
/* Nothing else to do for plain PSK or RSAPSK */
if (alg_k & (SSL_kPSK | SSL_kRSAPSK)) {
} else if (alg_k & SSL_kSRP) {
if (!tls_process_ske_srp(s, pkt, &pkey)) {
/* SSLfatal() already called */
goto err;
}
} else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
if (!tls_process_ske_dhe(s, pkt, &pkey)) {
/* SSLfatal() already called */
goto err;
}
} else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
if (!tls_process_ske_ecdhe(s, pkt, &pkey)) {
/* SSLfatal() already called */
goto err;
}
} else if (alg_k) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
SSL_R_UNEXPECTED_MESSAGE);
goto err;
}
/* if it was signed, check the signature */
if (pkey != NULL) {
PACKET params;
int maxsig;
const EVP_MD *md = NULL;
unsigned char *tbs;
size_t tbslen;
int rv;
/*
* |pkt| now points to the beginning of the signature, so the difference
* equals the length of the parameters.
*/
if (!PACKET_get_sub_packet(&save_param_start, &params,
PACKET_remaining(&save_param_start) -
PACKET_remaining(pkt))) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (SSL_USE_SIGALGS(s)) {
unsigned int sigalg;
if (!PACKET_get_net_2(pkt, &sigalg)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
SSL_R_LENGTH_TOO_SHORT);
goto err;
}
if (tls12_check_peer_sigalg(s, sigalg, pkey) <=0) {
/* SSLfatal() already called */
goto err;
}
} else if (!tls1_set_peer_legacy_sigalg(s, pkey)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (!tls1_lookup_md(s->s3->tmp.peer_sigalg, &md)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
#ifdef SSL_DEBUG
if (SSL_USE_SIGALGS(s))
fprintf(stderr, "USING TLSv1.2 HASH %s\n",
md == NULL ? "n/a" : EVP_MD_name(md));
#endif
if (!PACKET_get_length_prefixed_2(pkt, &signature)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
SSL_R_LENGTH_MISMATCH);
goto err;
}
maxsig = EVP_PKEY_size(pkey);
if (maxsig < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* Check signature length
*/
if (PACKET_remaining(&signature) > (size_t)maxsig) {
/* wrong packet length */
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
SSL_R_WRONG_SIGNATURE_LENGTH);
goto err;
}
md_ctx = EVP_MD_CTX_new();
if (md_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_DigestVerifyInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
ERR_R_EVP_LIB);
goto err;
}
if (SSL_USE_PSS(s)) {
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
RSA_PSS_SALTLEN_DIGEST) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_KEY_EXCHANGE, ERR_R_EVP_LIB);
goto err;
}
}
tbslen = construct_key_exchange_tbs(s, &tbs, PACKET_data(&params),
PACKET_remaining(&params));
if (tbslen == 0) {
/* SSLfatal() already called */
goto err;
}
rv = EVP_DigestVerify(md_ctx, PACKET_data(&signature),
PACKET_remaining(&signature), tbs, tbslen);
OPENSSL_free(tbs);
if (rv <= 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
SSL_R_BAD_SIGNATURE);
goto err;
}
EVP_MD_CTX_free(md_ctx);
md_ctx = NULL;
} else {
/* aNULL, aSRP or PSK do not need public keys */
if (!(s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP))
&& !(alg_k & SSL_PSK)) {
/* Might be wrong key type, check it */
if (ssl3_check_cert_and_algorithm(s)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
SSL_R_BAD_DATA);
}
/* else this shouldn't happen, SSLfatal() already called */
goto err;
}
/* still data left over */
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_KEY_EXCHANGE,
SSL_R_EXTRA_DATA_IN_MESSAGE);
goto err;
}
}
return MSG_PROCESS_CONTINUE_READING;
err:
EVP_MD_CTX_free(md_ctx);
return MSG_PROCESS_ERROR;
}
MSG_PROCESS_RETURN tls_process_certificate_request(SSL *s, PACKET *pkt)
{
size_t i;
/* Clear certificate validity flags */
for (i = 0; i < SSL_PKEY_NUM; i++)
s->s3->tmp.valid_flags[i] = 0;
if (SSL_IS_TLS13(s)) {
PACKET reqctx, extensions;
RAW_EXTENSION *rawexts = NULL;
if ((s->shutdown & SSL_SENT_SHUTDOWN) != 0) {
/*
* We already sent close_notify. This can only happen in TLSv1.3
* post-handshake messages. We can't reasonably respond to this, so
* we just ignore it
*/
return MSG_PROCESS_FINISHED_READING;
}
/* Free and zero certificate types: it is not present in TLS 1.3 */
OPENSSL_free(s->s3->tmp.ctype);
s->s3->tmp.ctype = NULL;
s->s3->tmp.ctype_len = 0;
OPENSSL_free(s->pha_context);
s->pha_context = NULL;
if (!PACKET_get_length_prefixed_1(pkt, &reqctx) ||
!PACKET_memdup(&reqctx, &s->pha_context, &s->pha_context_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (!PACKET_get_length_prefixed_2(pkt, &extensions)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSL_R_BAD_LENGTH);
return MSG_PROCESS_ERROR;
}
if (!tls_collect_extensions(s, &extensions,
SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
&rawexts, NULL, 1)
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE_REQUEST,
rawexts, NULL, 0, 1)) {
/* SSLfatal() already called */
OPENSSL_free(rawexts);
return MSG_PROCESS_ERROR;
}
OPENSSL_free(rawexts);
if (!tls1_process_sigalgs(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSL_R_BAD_LENGTH);
return MSG_PROCESS_ERROR;
}
} else {
PACKET ctypes;
/* get the certificate types */
if (!PACKET_get_length_prefixed_1(pkt, &ctypes)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (!PACKET_memdup(&ctypes, &s->s3->tmp.ctype, &s->s3->tmp.ctype_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
if (SSL_USE_SIGALGS(s)) {
PACKET sigalgs;
if (!PACKET_get_length_prefixed_2(pkt, &sigalgs)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
/*
* Despite this being for certificates, preserve compatibility
* with pre-TLS 1.3 and use the regular sigalgs field.
*/
if (!tls1_save_sigalgs(s, &sigalgs, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSL_R_SIGNATURE_ALGORITHMS_ERROR);
return MSG_PROCESS_ERROR;
}
if (!tls1_process_sigalgs(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
ERR_R_MALLOC_FAILURE);
return MSG_PROCESS_ERROR;
}
}
/* get the CA RDNs */
if (!parse_ca_names(s, pkt)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
}
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CERTIFICATE_REQUEST,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
/* we should setup a certificate to return.... */
s->s3->tmp.cert_req = 1;
/*
* In TLSv1.3 we don't prepare the client certificate yet. We wait until
* after the CertificateVerify message has been received. This is because
* in TLSv1.3 the CertificateRequest arrives before the Certificate message
* but in TLSv1.2 it is the other way around. We want to make sure that
* SSL_get_peer_certificate() returns something sensible in
* client_cert_cb.
*/
if (SSL_IS_TLS13(s) && s->post_handshake_auth != SSL_PHA_REQUESTED)
return MSG_PROCESS_CONTINUE_READING;
return MSG_PROCESS_CONTINUE_PROCESSING;
}
MSG_PROCESS_RETURN tls_process_new_session_ticket(SSL *s, PACKET *pkt)
{
unsigned int ticklen;
unsigned long ticket_lifetime_hint, age_add = 0;
unsigned int sess_len;
RAW_EXTENSION *exts = NULL;
PACKET nonce;
PACKET_null_init(&nonce);
if (!PACKET_get_net_4(pkt, &ticket_lifetime_hint)
|| (SSL_IS_TLS13(s)
&& (!PACKET_get_net_4(pkt, &age_add)
|| !PACKET_get_length_prefixed_1(pkt, &nonce)))
|| !PACKET_get_net_2(pkt, &ticklen)
|| (SSL_IS_TLS13(s) ? (ticklen == 0 || PACKET_remaining(pkt) < ticklen)
: PACKET_remaining(pkt) != ticklen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
SSL_R_LENGTH_MISMATCH);
goto err;
}
/*
* Server is allowed to change its mind (in <=TLSv1.2) and send an empty
* ticket. We already checked this TLSv1.3 case above, so it should never
* be 0 here in that instance
*/
if (ticklen == 0)
return MSG_PROCESS_CONTINUE_READING;
/*
* Sessions must be immutable once they go into the session cache. Otherwise
* we can get multi-thread problems. Therefore we don't "update" sessions,
* we replace them with a duplicate. In TLSv1.3 we need to do this every
* time a NewSessionTicket arrives because those messages arrive
* post-handshake and the session may have already gone into the session
* cache.
*/
if (SSL_IS_TLS13(s) || s->session->session_id_length > 0) {
SSL_SESSION *new_sess;
/*
* We reused an existing session, so we need to replace it with a new
* one
*/
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
ERR_R_MALLOC_FAILURE);
goto err;
}
if ((s->session_ctx->session_cache_mode & SSL_SESS_CACHE_CLIENT) != 0
&& !SSL_IS_TLS13(s)) {
/*
* In TLSv1.2 and below the arrival of a new tickets signals that
* any old ticket we were using is now out of date, so we remove the
* old session from the cache. We carry on if this fails
*/
SSL_CTX_remove_session(s->session_ctx, s->session);
}
SSL_SESSION_free(s->session);
s->session = new_sess;
}
/*
* Technically the cast to long here is not guaranteed by the C standard -
* but we use it elsewhere, so this should be ok.
*/
s->session->time = (long)time(NULL);
OPENSSL_free(s->session->ext.tick);
s->session->ext.tick = NULL;
s->session->ext.ticklen = 0;
s->session->ext.tick = OPENSSL_malloc(ticklen);
if (s->session->ext.tick == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (!PACKET_copy_bytes(pkt, s->session->ext.tick, ticklen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
SSL_R_LENGTH_MISMATCH);
goto err;
}
s->session->ext.tick_lifetime_hint = ticket_lifetime_hint;
s->session->ext.tick_age_add = age_add;
s->session->ext.ticklen = ticklen;
if (SSL_IS_TLS13(s)) {
PACKET extpkt;
if (!PACKET_as_length_prefixed_2(pkt, &extpkt)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!tls_collect_extensions(s, &extpkt,
SSL_EXT_TLS1_3_NEW_SESSION_TICKET, &exts,
NULL, 1)
|| !tls_parse_all_extensions(s,
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
exts, NULL, 0, 1)) {
/* SSLfatal() already called */
goto err;
}
}
/*
* There are two ways to detect a resumed ticket session. One is to set
* an appropriate session ID and then the server must return a match in
* ServerHello. This allows the normal client session ID matching to work
* and we know much earlier that the ticket has been accepted. The
* other way is to set zero length session ID when the ticket is
* presented and rely on the handshake to determine session resumption.
* We choose the former approach because this fits in with assumptions
* elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
* SHA256 is disabled) hash of the ticket.
*/
/*
* TODO(size_t): we use sess_len here because EVP_Digest expects an int
* but s->session->session_id_length is a size_t
*/
if (!EVP_Digest(s->session->ext.tick, ticklen,
s->session->session_id, &sess_len,
EVP_sha256(), NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
ERR_R_EVP_LIB);
goto err;
}
s->session->session_id_length = sess_len;
s->session->not_resumable = 0;
/* This is a standalone message in TLSv1.3, so there is no more to read */
if (SSL_IS_TLS13(s)) {
const EVP_MD *md = ssl_handshake_md(s);
int hashleni = EVP_MD_size(md);
size_t hashlen;
static const unsigned char nonce_label[] = "resumption";
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_NEW_SESSION_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
hashlen = (size_t)hashleni;
if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
nonce_label,
sizeof(nonce_label) - 1,
PACKET_data(&nonce),
PACKET_remaining(&nonce),
s->session->master_key,
hashlen, 1)) {
/* SSLfatal() already called */
goto err;
}
s->session->master_key_length = hashlen;
OPENSSL_free(exts);
ssl_update_cache(s, SSL_SESS_CACHE_CLIENT);
return MSG_PROCESS_FINISHED_READING;
}
return MSG_PROCESS_CONTINUE_READING;
err:
OPENSSL_free(exts);
return MSG_PROCESS_ERROR;
}
/*
* In TLSv1.3 this is called from the extensions code, otherwise it is used to
* parse a separate message. Returns 1 on success or 0 on failure
*/
int tls_process_cert_status_body(SSL *s, PACKET *pkt)
{
size_t resplen;
unsigned int type;
if (!PACKET_get_1(pkt, &type)
|| type != TLSEXT_STATUSTYPE_ocsp) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
SSL_R_UNSUPPORTED_STATUS_TYPE);
return 0;
}
if (!PACKET_get_net_3_len(pkt, &resplen)
|| PACKET_remaining(pkt) != resplen) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
SSL_R_LENGTH_MISMATCH);
return 0;
}
s->ext.ocsp.resp = OPENSSL_malloc(resplen);
if (s->ext.ocsp.resp == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
ERR_R_MALLOC_FAILURE);
return 0;
}
if (!PACKET_copy_bytes(pkt, s->ext.ocsp.resp, resplen)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CERT_STATUS_BODY,
SSL_R_LENGTH_MISMATCH);
return 0;
}
s->ext.ocsp.resp_len = resplen;
return 1;
}
MSG_PROCESS_RETURN tls_process_cert_status(SSL *s, PACKET *pkt)
{
if (!tls_process_cert_status_body(s, pkt)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
return MSG_PROCESS_CONTINUE_READING;
}
/*
* Perform miscellaneous checks and processing after we have received the
* server's initial flight. In TLS1.3 this is after the Server Finished message.
* In <=TLS1.2 this is after the ServerDone message. Returns 1 on success or 0
* on failure.
*/
int tls_process_initial_server_flight(SSL *s)
{
/*
* at this point we check that we have the required stuff from
* the server
*/
if (!ssl3_check_cert_and_algorithm(s)) {
/* SSLfatal() already called */
return 0;
}
/*
* Call the ocsp status callback if needed. The |ext.ocsp.resp| and
* |ext.ocsp.resp_len| values will be set if we actually received a status
* message, or NULL and -1 otherwise
*/
if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing
&& s->ctx->ext.status_cb != NULL) {
int ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
if (ret == 0) {
SSLfatal(s, SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE,
SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
SSL_R_INVALID_STATUS_RESPONSE);
return 0;
}
if (ret < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_INITIAL_SERVER_FLIGHT,
ERR_R_MALLOC_FAILURE);
return 0;
}
}
#ifndef OPENSSL_NO_CT
if (s->ct_validation_callback != NULL) {
/* Note we validate the SCTs whether or not we abort on error */
if (!ssl_validate_ct(s) && (s->verify_mode & SSL_VERIFY_PEER)) {
/* SSLfatal() already called */
return 0;
}
}
#endif
return 1;
}
MSG_PROCESS_RETURN tls_process_server_done(SSL *s, PACKET *pkt)
{
if (PACKET_remaining(pkt) > 0) {
/* should contain no data */
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
#ifndef OPENSSL_NO_SRP
if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
if (SRP_Calc_A_param(s) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_SERVER_DONE,
SSL_R_SRP_A_CALC);
return MSG_PROCESS_ERROR;
}
}
#endif
if (!tls_process_initial_server_flight(s)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
return MSG_PROCESS_FINISHED_READING;
}
static int tls_construct_cke_psk_preamble(SSL *s, WPACKET *pkt)
{
#ifndef OPENSSL_NO_PSK
int ret = 0;
/*
* The callback needs PSK_MAX_IDENTITY_LEN + 1 bytes to return a
* \0-terminated identity. The last byte is for us for simulating
* strnlen.
*/
char identity[PSK_MAX_IDENTITY_LEN + 1];
size_t identitylen = 0;
unsigned char psk[PSK_MAX_PSK_LEN];
unsigned char *tmppsk = NULL;
char *tmpidentity = NULL;
size_t psklen = 0;
if (s->psk_client_callback == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
SSL_R_PSK_NO_CLIENT_CB);
goto err;
}
memset(identity, 0, sizeof(identity));
psklen = s->psk_client_callback(s, s->session->psk_identity_hint,
identity, sizeof(identity) - 1,
psk, sizeof(psk));
if (psklen > PSK_MAX_PSK_LEN) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE, ERR_R_INTERNAL_ERROR);
goto err;
} else if (psklen == 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
SSL_R_PSK_IDENTITY_NOT_FOUND);
goto err;
}
identitylen = strlen(identity);
if (identitylen > PSK_MAX_IDENTITY_LEN) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
ERR_R_INTERNAL_ERROR);
goto err;
}
tmppsk = OPENSSL_memdup(psk, psklen);
tmpidentity = OPENSSL_strdup(identity);
if (tmppsk == NULL || tmpidentity == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_free(s->s3->tmp.psk);
s->s3->tmp.psk = tmppsk;
s->s3->tmp.psklen = psklen;
tmppsk = NULL;
OPENSSL_free(s->session->psk_identity);
s->session->psk_identity = tmpidentity;
tmpidentity = NULL;
if (!WPACKET_sub_memcpy_u16(pkt, identity, identitylen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
ERR_R_INTERNAL_ERROR);
goto err;
}
ret = 1;
err:
OPENSSL_cleanse(psk, psklen);
OPENSSL_cleanse(identity, sizeof(identity));
OPENSSL_clear_free(tmppsk, psklen);
OPENSSL_clear_free(tmpidentity, identitylen);
return ret;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_PSK_PREAMBLE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_construct_cke_rsa(SSL *s, WPACKET *pkt)
{
#ifndef OPENSSL_NO_RSA
unsigned char *encdata = NULL;
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *pctx = NULL;
size_t enclen;
unsigned char *pms = NULL;
size_t pmslen = 0;
if (s->session->peer == NULL) {
/*
* We should always have a server certificate with SSL_kRSA.
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
ERR_R_INTERNAL_ERROR);
return 0;
}
pkey = X509_get0_pubkey(s->session->peer);
if (EVP_PKEY_get0_RSA(pkey) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
ERR_R_INTERNAL_ERROR);
return 0;
}
pmslen = SSL_MAX_MASTER_KEY_LENGTH;
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
ERR_R_MALLOC_FAILURE);
return 0;
}
pms[0] = s->client_version >> 8;
pms[1] = s->client_version & 0xff;
/* TODO(size_t): Convert this function */
if (RAND_bytes(pms + 2, (int)(pmslen - 2)) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
ERR_R_MALLOC_FAILURE);
goto err;
}
/* Fix buf for TLS and beyond */
if (s->version > SSL3_VERSION && !WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
ERR_R_INTERNAL_ERROR);
goto err;
}
pctx = EVP_PKEY_CTX_new(pkey, NULL);
if (pctx == NULL || EVP_PKEY_encrypt_init(pctx) <= 0
|| EVP_PKEY_encrypt(pctx, NULL, &enclen, pms, pmslen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
ERR_R_EVP_LIB);
goto err;
}
if (!WPACKET_allocate_bytes(pkt, enclen, &encdata)
|| EVP_PKEY_encrypt(pctx, encdata, &enclen, pms, pmslen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
SSL_R_BAD_RSA_ENCRYPT);
goto err;
}
EVP_PKEY_CTX_free(pctx);
pctx = NULL;
/* Fix buf for TLS and beyond */
if (s->version > SSL3_VERSION && !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Log the premaster secret, if logging is enabled. */
if (!ssl_log_rsa_client_key_exchange(s, encdata, enclen, pms, pmslen)) {
/* SSLfatal() already called */
goto err;
}
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
return 1;
err:
OPENSSL_clear_free(pms, pmslen);
EVP_PKEY_CTX_free(pctx);
return 0;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_RSA,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_construct_cke_dhe(SSL *s, WPACKET *pkt)
{
#ifndef OPENSSL_NO_DH
DH *dh_clnt = NULL;
const BIGNUM *pub_key;
EVP_PKEY *ckey = NULL, *skey = NULL;
unsigned char *keybytes = NULL;
skey = s->s3->peer_tmp;
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
ERR_R_INTERNAL_ERROR);
goto err;
}
ckey = ssl_generate_pkey(skey);
if (ckey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
ERR_R_INTERNAL_ERROR);
goto err;
}
dh_clnt = EVP_PKEY_get0_DH(ckey);
if (dh_clnt == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (ssl_derive(s, ckey, skey, 0) == 0) {
/* SSLfatal() already called */
goto err;
}
/* send off the data */
DH_get0_key(dh_clnt, &pub_key, NULL);
if (!WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(pub_key),
&keybytes)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
ERR_R_INTERNAL_ERROR);
goto err;
}
BN_bn2bin(pub_key, keybytes);
EVP_PKEY_free(ckey);
return 1;
err:
EVP_PKEY_free(ckey);
return 0;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_DHE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_construct_cke_ecdhe(SSL *s, WPACKET *pkt)
{
#ifndef OPENSSL_NO_EC
unsigned char *encodedPoint = NULL;
size_t encoded_pt_len = 0;
EVP_PKEY *ckey = NULL, *skey = NULL;
int ret = 0;
skey = s->s3->peer_tmp;
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
ERR_R_INTERNAL_ERROR);
return 0;
}
ckey = ssl_generate_pkey(skey);
if (ckey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (ssl_derive(s, ckey, skey, 0) == 0) {
/* SSLfatal() already called */
goto err;
}
/* Generate encoding of client key */
encoded_pt_len = EVP_PKEY_get1_tls_encodedpoint(ckey, &encodedPoint);
if (encoded_pt_len == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
ERR_R_EC_LIB);
goto err;
}
if (!WPACKET_sub_memcpy_u8(pkt, encodedPoint, encoded_pt_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
ERR_R_INTERNAL_ERROR);
goto err;
}
ret = 1;
err:
OPENSSL_free(encodedPoint);
EVP_PKEY_free(ckey);
return ret;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_ECDHE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_construct_cke_gost(SSL *s, WPACKET *pkt)
{
#ifndef OPENSSL_NO_GOST
/* GOST key exchange message creation */
EVP_PKEY_CTX *pkey_ctx = NULL;
X509 *peer_cert;
size_t msglen;
unsigned int md_len;
unsigned char shared_ukm[32], tmp[256];
EVP_MD_CTX *ukm_hash = NULL;
int dgst_nid = NID_id_GostR3411_94;
unsigned char *pms = NULL;
size_t pmslen = 0;
if ((s->s3->tmp.new_cipher->algorithm_auth & SSL_aGOST12) != 0)
dgst_nid = NID_id_GostR3411_2012_256;
/*
* Get server certificate PKEY and create ctx from it
*/
peer_cert = s->session->peer;
if (!peer_cert) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_CONSTRUCT_CKE_GOST,
SSL_R_NO_GOST_CERTIFICATE_SENT_BY_PEER);
return 0;
}
pkey_ctx = EVP_PKEY_CTX_new(X509_get0_pubkey(peer_cert), NULL);
if (pkey_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
ERR_R_MALLOC_FAILURE);
return 0;
}
/*
* If we have send a certificate, and certificate key
* parameters match those of server certificate, use
* certificate key for key exchange
*/
/* Otherwise, generate ephemeral key pair */
pmslen = 32;
pms = OPENSSL_malloc(pmslen);
if (pms == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (EVP_PKEY_encrypt_init(pkey_ctx) <= 0
/* Generate session key
* TODO(size_t): Convert this function
*/
|| RAND_bytes(pms, (int)pmslen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
ERR_R_INTERNAL_ERROR);
goto err;
};
/*
* Compute shared IV and store it in algorithm-specific context
* data
*/
ukm_hash = EVP_MD_CTX_new();
if (ukm_hash == NULL
|| EVP_DigestInit(ukm_hash, EVP_get_digestbynid(dgst_nid)) <= 0
|| EVP_DigestUpdate(ukm_hash, s->s3->client_random,
SSL3_RANDOM_SIZE) <= 0
|| EVP_DigestUpdate(ukm_hash, s->s3->server_random,
SSL3_RANDOM_SIZE) <= 0
|| EVP_DigestFinal_ex(ukm_hash, shared_ukm, &md_len) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_MD_CTX_free(ukm_hash);
ukm_hash = NULL;
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, EVP_PKEY_OP_ENCRYPT,
EVP_PKEY_CTRL_SET_IV, 8, shared_ukm) < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
SSL_R_LIBRARY_BUG);
goto err;
}
/* Make GOST keytransport blob message */
/*
* Encapsulate it into sequence
*/
msglen = 255;
if (EVP_PKEY_encrypt(pkey_ctx, tmp, &msglen, pms, pmslen) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
SSL_R_LIBRARY_BUG);
goto err;
}
if (!WPACKET_put_bytes_u8(pkt, V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)
|| (msglen >= 0x80 && !WPACKET_put_bytes_u8(pkt, 0x81))
|| !WPACKET_sub_memcpy_u8(pkt, tmp, msglen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_PKEY_CTX_free(pkey_ctx);
s->s3->tmp.pms = pms;
s->s3->tmp.pmslen = pmslen;
return 1;
err:
EVP_PKEY_CTX_free(pkey_ctx);
OPENSSL_clear_free(pms, pmslen);
EVP_MD_CTX_free(ukm_hash);
return 0;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_GOST,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_construct_cke_srp(SSL *s, WPACKET *pkt)
{
#ifndef OPENSSL_NO_SRP
unsigned char *abytes = NULL;
if (s->srp_ctx.A == NULL
|| !WPACKET_sub_allocate_bytes_u16(pkt, BN_num_bytes(s->srp_ctx.A),
&abytes)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
ERR_R_INTERNAL_ERROR);
return 0;
}
BN_bn2bin(s->srp_ctx.A, abytes);
OPENSSL_free(s->session->srp_username);
s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
if (s->session->srp_username == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
ERR_R_MALLOC_FAILURE);
return 0;
}
return 1;
#else
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CKE_SRP,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
int tls_construct_client_key_exchange(SSL *s, WPACKET *pkt)
{
unsigned long alg_k;
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
/*
* All of the construct functions below call SSLfatal() if necessary so
* no need to do so here.
*/
if ((alg_k & SSL_PSK)
&& !tls_construct_cke_psk_preamble(s, pkt))
goto err;
if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
if (!tls_construct_cke_rsa(s, pkt))
goto err;
} else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
if (!tls_construct_cke_dhe(s, pkt))
goto err;
} else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
if (!tls_construct_cke_ecdhe(s, pkt))
goto err;
} else if (alg_k & SSL_kGOST) {
if (!tls_construct_cke_gost(s, pkt))
goto err;
} else if (alg_k & SSL_kSRP) {
if (!tls_construct_cke_srp(s, pkt))
goto err;
} else if (!(alg_k & SSL_kPSK)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CLIENT_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
return 1;
err:
OPENSSL_clear_free(s->s3->tmp.pms, s->s3->tmp.pmslen);
s->s3->tmp.pms = NULL;
#ifndef OPENSSL_NO_PSK
OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
s->s3->tmp.psk = NULL;
#endif
return 0;
}
int tls_client_key_exchange_post_work(SSL *s)
{
unsigned char *pms = NULL;
size_t pmslen = 0;
pms = s->s3->tmp.pms;
pmslen = s->s3->tmp.pmslen;
#ifndef OPENSSL_NO_SRP
/* Check for SRP */
if (s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) {
if (!srp_generate_client_master_secret(s)) {
/* SSLfatal() already called */
goto err;
}
return 1;
}
#endif
if (pms == NULL && !(s->s3->tmp.new_cipher->algorithm_mkey & SSL_kPSK)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!ssl_generate_master_secret(s, pms, pmslen, 1)) {
/* SSLfatal() already called */
/* ssl_generate_master_secret frees the pms even on error */
pms = NULL;
pmslen = 0;
goto err;
}
pms = NULL;
pmslen = 0;
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s)) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
size_t labellen;
/*
* Add new shared key for SCTP-Auth, will be ignored if no SCTP
* used.
*/
memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
sizeof(DTLS1_SCTP_AUTH_LABEL));
/* Don't include the terminating zero. */
labellen = sizeof(labelbuffer) - 1;
if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
labellen += 1;
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0, 0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CLIENT_KEY_EXCHANGE_POST_WORK,
ERR_R_INTERNAL_ERROR);
goto err;
}
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
}
#endif
return 1;
err:
OPENSSL_clear_free(pms, pmslen);
s->s3->tmp.pms = NULL;
return 0;
}
/*
* Check a certificate can be used for client authentication. Currently check
* cert exists, if we have a suitable digest for TLS 1.2 if static DH client
* certificates can be used and optionally checks suitability for Suite B.
*/
static int ssl3_check_client_certificate(SSL *s)
{
/* If no suitable signature algorithm can't use certificate */
if (!tls_choose_sigalg(s, 0) || s->s3->tmp.sigalg == NULL)
return 0;
/*
* If strict mode check suitability of chain before using it. This also
* adjusts suite B digest if necessary.
*/
if (s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT &&
!tls1_check_chain(s, NULL, NULL, NULL, -2))
return 0;
return 1;
}
WORK_STATE tls_prepare_client_certificate(SSL *s, WORK_STATE wst)
{
X509 *x509 = NULL;
EVP_PKEY *pkey = NULL;
int i;
if (wst == WORK_MORE_A) {
/* Let cert callback update client certificates if required */
if (s->cert->cert_cb) {
i = s->cert->cert_cb(s, s->cert->cert_cb_arg);
if (i < 0) {
s->rwstate = SSL_X509_LOOKUP;
return WORK_MORE_A;
}
if (i == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
SSL_R_CALLBACK_FAILED);
return WORK_ERROR;
}
s->rwstate = SSL_NOTHING;
}
if (ssl3_check_client_certificate(s)) {
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
return WORK_FINISHED_STOP;
}
return WORK_FINISHED_CONTINUE;
}
/* Fall through to WORK_MORE_B */
wst = WORK_MORE_B;
}
/* We need to get a client cert */
if (wst == WORK_MORE_B) {
/*
* If we get an error, we need to ssl->rwstate=SSL_X509_LOOKUP;
* return(-1); We then get retied later
*/
i = ssl_do_client_cert_cb(s, &x509, &pkey);
if (i < 0) {
s->rwstate = SSL_X509_LOOKUP;
return WORK_MORE_B;
}
s->rwstate = SSL_NOTHING;
if ((i == 1) && (pkey != NULL) && (x509 != NULL)) {
if (!SSL_use_certificate(s, x509) || !SSL_use_PrivateKey(s, pkey))
i = 0;
} else if (i == 1) {
i = 0;
SSLerr(SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
SSL_R_BAD_DATA_RETURNED_BY_CALLBACK);
}
X509_free(x509);
EVP_PKEY_free(pkey);
if (i && !ssl3_check_client_certificate(s))
i = 0;
if (i == 0) {
if (s->version == SSL3_VERSION) {
s->s3->tmp.cert_req = 0;
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_CERTIFICATE);
return WORK_FINISHED_CONTINUE;
} else {
s->s3->tmp.cert_req = 2;
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
}
}
if (s->post_handshake_auth == SSL_PHA_REQUESTED)
return WORK_FINISHED_STOP;
return WORK_FINISHED_CONTINUE;
}
/* Shouldn't ever get here */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PREPARE_CLIENT_CERTIFICATE,
ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
int tls_construct_client_certificate(SSL *s, WPACKET *pkt)
{
if (SSL_IS_TLS13(s)) {
if (s->pha_context == NULL) {
/* no context available, add 0-length context */
if (!WPACKET_put_bytes_u8(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
return 0;
}
} else if (!WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (!ssl3_output_cert_chain(s, pkt,
(s->s3->tmp.cert_req == 2) ? NULL
: s->cert->key)) {
/* SSLfatal() already called */
return 0;
}
if (SSL_IS_TLS13(s)
&& SSL_IS_FIRST_HANDSHAKE(s)
&& (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_CLIENT_WRITE))) {
/*
* This is a fatal error, which leaves enc_write_ctx in an inconsistent
* state and thus ssl3_send_alert may crash.
*/
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_TLS_CONSTRUCT_CLIENT_CERTIFICATE,
SSL_R_CANNOT_CHANGE_CIPHER);
return 0;
}
return 1;
}
int ssl3_check_cert_and_algorithm(SSL *s)
{
const SSL_CERT_LOOKUP *clu;
size_t idx;
long alg_k, alg_a;
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
/* we don't have a certificate */
if (!(alg_a & SSL_aCERT))
return 1;
/* This is the passed certificate */
clu = ssl_cert_lookup_by_pkey(X509_get0_pubkey(s->session->peer), &idx);
/* Check certificate is recognised and suitable for cipher */
if (clu == NULL || (alg_a & clu->amask) == 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_SIGNING_CERT);
return 0;
}
#ifndef OPENSSL_NO_EC
if (clu->amask & SSL_aECDSA) {
if (ssl_check_srvr_ecc_cert_and_alg(s->session->peer, s))
return 1;
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_BAD_ECC_CERT);
return 0;
}
#endif
#ifndef OPENSSL_NO_RSA
if (alg_k & (SSL_kRSA | SSL_kRSAPSK) && idx != SSL_PKEY_RSA) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
SSL_R_MISSING_RSA_ENCRYPTING_CERT);
return 0;
}
#endif
#ifndef OPENSSL_NO_DH
if ((alg_k & SSL_kDHE) && (s->s3->peer_tmp == NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM,
ERR_R_INTERNAL_ERROR);
return 0;
}
#endif
return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
int tls_construct_next_proto(SSL *s, WPACKET *pkt)
{
size_t len, padding_len;
unsigned char *padding = NULL;
len = s->ext.npn_len;
padding_len = 32 - ((len + 2) % 32);
if (!WPACKET_sub_memcpy_u8(pkt, s->ext.npn, len)
|| !WPACKET_sub_allocate_bytes_u8(pkt, padding_len, &padding)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_NEXT_PROTO,
ERR_R_INTERNAL_ERROR);
return 0;
}
memset(padding, 0, padding_len);
return 1;
}
#endif
MSG_PROCESS_RETURN tls_process_hello_req(SSL *s, PACKET *pkt)
{
if (PACKET_remaining(pkt) > 0) {
/* should contain no data */
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_HELLO_REQ,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if ((s->options & SSL_OP_NO_RENEGOTIATION)) {
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
return MSG_PROCESS_FINISHED_READING;
}
/*
* This is a historical discrepancy (not in the RFC) maintained for
* compatibility reasons. If a TLS client receives a HelloRequest it will
* attempt an abbreviated handshake. However if a DTLS client receives a
* HelloRequest it will do a full handshake. Either behaviour is reasonable
* but doing one for TLS and another for DTLS is odd.
*/
if (SSL_IS_DTLS(s))
SSL_renegotiate(s);
else
SSL_renegotiate_abbreviated(s);
return MSG_PROCESS_FINISHED_READING;
}
static MSG_PROCESS_RETURN tls_process_encrypted_extensions(SSL *s, PACKET *pkt)
{
PACKET extensions;
RAW_EXTENSION *rawexts = NULL;
if (!PACKET_as_length_prefixed_2(pkt, &extensions)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_ENCRYPTED_EXTENSIONS,
SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!tls_collect_extensions(s, &extensions,
SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS, &rawexts,
NULL, 1)
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
rawexts, NULL, 0, 1)) {
/* SSLfatal() already called */
goto err;
}
OPENSSL_free(rawexts);
return MSG_PROCESS_CONTINUE_READING;
err:
OPENSSL_free(rawexts);
return MSG_PROCESS_ERROR;
}
int ssl_do_client_cert_cb(SSL *s, X509 **px509, EVP_PKEY **ppkey)
{
int i = 0;
#ifndef OPENSSL_NO_ENGINE
if (s->ctx->client_cert_engine) {
i = ENGINE_load_ssl_client_cert(s->ctx->client_cert_engine, s,
SSL_get_client_CA_list(s),
px509, ppkey, NULL, NULL, NULL);
if (i != 0)
return i;
}
#endif
if (s->ctx->client_cert_cb)
i = s->ctx->client_cert_cb(s, px509, ppkey);
return i;
}
int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *sk, WPACKET *pkt)
{
int i;
size_t totlen = 0, len, maxlen, maxverok = 0;
int empty_reneg_info_scsv = !s->renegotiate;
/* Set disabled masks for this session */
if (!ssl_set_client_disabled(s)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
SSL_R_NO_PROTOCOLS_AVAILABLE);
return 0;
}
if (sk == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
ERR_R_INTERNAL_ERROR);
return 0;
}
#ifdef OPENSSL_MAX_TLS1_2_CIPHER_LENGTH
# if OPENSSL_MAX_TLS1_2_CIPHER_LENGTH < 6
# error Max cipher length too short
# endif
/*
* Some servers hang if client hello > 256 bytes as hack workaround
* chop number of supported ciphers to keep it well below this if we
* use TLS v1.2
*/
if (TLS1_get_version(s) >= TLS1_2_VERSION)
maxlen = OPENSSL_MAX_TLS1_2_CIPHER_LENGTH & ~1;
else
#endif
/* Maximum length that can be stored in 2 bytes. Length must be even */
maxlen = 0xfffe;
if (empty_reneg_info_scsv)
maxlen -= 2;
if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV)
maxlen -= 2;
for (i = 0; i < sk_SSL_CIPHER_num(sk) && totlen < maxlen; i++) {
const SSL_CIPHER *c;
c = sk_SSL_CIPHER_value(sk, i);
/* Skip disabled ciphers */
if (ssl_cipher_disabled(s, c, SSL_SECOP_CIPHER_SUPPORTED, 0))
continue;
if (!s->method->put_cipher_by_char(c, pkt, &len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* Sanity check that the maximum version we offer has ciphers enabled */
if (!maxverok) {
if (SSL_IS_DTLS(s)) {
if (DTLS_VERSION_GE(c->max_dtls, s->s3->tmp.max_ver)
&& DTLS_VERSION_LE(c->min_dtls, s->s3->tmp.max_ver))
maxverok = 1;
} else {
if (c->max_tls >= s->s3->tmp.max_ver
&& c->min_tls <= s->s3->tmp.max_ver)
maxverok = 1;
}
}
totlen += len;
}
if (totlen == 0 || !maxverok) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_SSL_CIPHER_LIST_TO_BYTES,
SSL_R_NO_CIPHERS_AVAILABLE);
if (!maxverok)
ERR_add_error_data(1, "No ciphers enabled for max supported "
"SSL/TLS version");
return 0;
}
if (totlen != 0) {
if (empty_reneg_info_scsv) {
static SSL_CIPHER scsv = {
0, NULL, NULL, SSL3_CK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (s->mode & SSL_MODE_SEND_FALLBACK_SCSV) {
static SSL_CIPHER scsv = {
0, NULL, NULL, SSL3_CK_FALLBACK_SCSV, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
if (!s->method->put_cipher_by_char(&scsv, pkt, &len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_SSL_CIPHER_LIST_TO_BYTES, ERR_R_INTERNAL_ERROR);
return 0;
}
}
}
return 1;
}
int tls_construct_end_of_early_data(SSL *s, WPACKET *pkt)
{
if (s->early_data_state != SSL_EARLY_DATA_WRITE_RETRY
&& s->early_data_state != SSL_EARLY_DATA_FINISHED_WRITING) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_END_OF_EARLY_DATA,
ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
return 0;
}
s->early_data_state = SSL_EARLY_DATA_FINISHED_WRITING;
return 1;
}
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 6b8aae62ccd8..d454326a9971 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1,4272 +1,4276 @@
/*
* Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
* Copyright 2005 Nokia. All rights reserved.
*
* Licensed under the OpenSSL license (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
* in the file LICENSE in the source distribution or at
* https://www.openssl.org/source/license.html
*/
#include <stdio.h>
#include "../ssl_locl.h"
#include "statem_locl.h"
#include "internal/constant_time_locl.h"
#include "internal/cryptlib.h"
#include <openssl/buffer.h>
#include <openssl/rand.h>
#include <openssl/objects.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/x509.h>
#include <openssl/dh.h>
#include <openssl/bn.h>
#include <openssl/md5.h>
#define TICKET_NONCE_SIZE 8
static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt);
/*
* ossl_statem_server13_read_transition() encapsulates the logic for the allowed
* handshake state transitions when a TLSv1.3 server is reading messages from
* the client. The message type that the client has sent is provided in |mt|.
* The current state is in |s->statem.hand_state|.
*
* Return values are 1 for success (transition allowed) and 0 on error
* (transition not allowed)
*/
static int ossl_statem_server13_read_transition(SSL *s, int mt)
{
OSSL_STATEM *st = &s->statem;
/*
* Note: There is no case for TLS_ST_BEFORE because at that stage we have
* not negotiated TLSv1.3 yet, so that case is handled by
* ossl_statem_server_read_transition()
*/
switch (st->hand_state) {
default:
break;
case TLS_ST_EARLY_DATA:
if (s->hello_retry_request == SSL_HRR_PENDING) {
if (mt == SSL3_MT_CLIENT_HELLO) {
st->hand_state = TLS_ST_SR_CLNT_HELLO;
return 1;
}
break;
} else if (s->ext.early_data == SSL_EARLY_DATA_ACCEPTED) {
if (mt == SSL3_MT_END_OF_EARLY_DATA) {
st->hand_state = TLS_ST_SR_END_OF_EARLY_DATA;
return 1;
}
break;
}
/* Fall through */
case TLS_ST_SR_END_OF_EARLY_DATA:
case TLS_ST_SW_FINISHED:
if (s->s3->tmp.cert_request) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_SR_CERT;
return 1;
}
} else {
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
}
break;
case TLS_ST_SR_CERT:
if (s->session->peer == NULL) {
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
} else {
if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
st->hand_state = TLS_ST_SR_CERT_VRFY;
return 1;
}
}
break;
case TLS_ST_SR_CERT_VRFY:
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
break;
case TLS_ST_OK:
/*
* Its never ok to start processing handshake messages in the middle of
* early data (i.e. before we've received the end of early data alert)
*/
if (s->early_data_state == SSL_EARLY_DATA_READING)
break;
if (mt == SSL3_MT_CERTIFICATE
&& s->post_handshake_auth == SSL_PHA_REQUESTED) {
st->hand_state = TLS_ST_SR_CERT;
return 1;
}
if (mt == SSL3_MT_KEY_UPDATE) {
st->hand_state = TLS_ST_SR_KEY_UPDATE;
return 1;
}
break;
}
/* No valid transition found */
return 0;
}
/*
* ossl_statem_server_read_transition() encapsulates the logic for the allowed
* handshake state transitions when the server is reading messages from the
* client. The message type that the client has sent is provided in |mt|. The
* current state is in |s->statem.hand_state|.
*
* Return values are 1 for success (transition allowed) and 0 on error
* (transition not allowed)
*/
int ossl_statem_server_read_transition(SSL *s, int mt)
{
OSSL_STATEM *st = &s->statem;
if (SSL_IS_TLS13(s)) {
if (!ossl_statem_server13_read_transition(s, mt))
goto err;
return 1;
}
switch (st->hand_state) {
default:
break;
case TLS_ST_BEFORE:
case TLS_ST_OK:
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
if (mt == SSL3_MT_CLIENT_HELLO) {
st->hand_state = TLS_ST_SR_CLNT_HELLO;
return 1;
}
break;
case TLS_ST_SW_SRVR_DONE:
/*
* If we get a CKE message after a ServerDone then either
* 1) We didn't request a Certificate
* OR
* 2) If we did request one then
* a) We allow no Certificate to be returned
* AND
* b) We are running SSL3 (in TLS1.0+ the client must return a 0
* list if we requested a certificate)
*/
if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
if (s->s3->tmp.cert_request) {
if (s->version == SSL3_VERSION) {
if ((s->verify_mode & SSL_VERIFY_PEER)
&& (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
/*
* This isn't an unexpected message as such - we're just
* not going to accept it because we require a client
* cert.
*/
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
return 0;
}
st->hand_state = TLS_ST_SR_KEY_EXCH;
return 1;
}
} else {
st->hand_state = TLS_ST_SR_KEY_EXCH;
return 1;
}
} else if (s->s3->tmp.cert_request) {
if (mt == SSL3_MT_CERTIFICATE) {
st->hand_state = TLS_ST_SR_CERT;
return 1;
}
}
break;
case TLS_ST_SR_CERT:
if (mt == SSL3_MT_CLIENT_KEY_EXCHANGE) {
st->hand_state = TLS_ST_SR_KEY_EXCH;
return 1;
}
break;
case TLS_ST_SR_KEY_EXCH:
/*
* We should only process a CertificateVerify message if we have
* received a Certificate from the client. If so then |s->session->peer|
* will be non NULL. In some instances a CertificateVerify message is
* not required even if the peer has sent a Certificate (e.g. such as in
* the case of static DH). In that case |st->no_cert_verify| should be
* set.
*/
if (s->session->peer == NULL || st->no_cert_verify) {
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
/*
* For the ECDH ciphersuites when the client sends its ECDH
* pub key in a certificate, the CertificateVerify message is
* not sent. Also for GOST ciphersuites when the client uses
* its key from the certificate for key exchange.
*/
st->hand_state = TLS_ST_SR_CHANGE;
return 1;
}
} else {
if (mt == SSL3_MT_CERTIFICATE_VERIFY) {
st->hand_state = TLS_ST_SR_CERT_VRFY;
return 1;
}
}
break;
case TLS_ST_SR_CERT_VRFY:
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
st->hand_state = TLS_ST_SR_CHANGE;
return 1;
}
break;
case TLS_ST_SR_CHANGE:
#ifndef OPENSSL_NO_NEXTPROTONEG
if (s->s3->npn_seen) {
if (mt == SSL3_MT_NEXT_PROTO) {
st->hand_state = TLS_ST_SR_NEXT_PROTO;
return 1;
}
} else {
#endif
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
}
#endif
break;
#ifndef OPENSSL_NO_NEXTPROTONEG
case TLS_ST_SR_NEXT_PROTO:
if (mt == SSL3_MT_FINISHED) {
st->hand_state = TLS_ST_SR_FINISHED;
return 1;
}
break;
#endif
case TLS_ST_SW_FINISHED:
if (mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
st->hand_state = TLS_ST_SR_CHANGE;
return 1;
}
break;
}
err:
/* No valid transition found */
if (SSL_IS_DTLS(s) && mt == SSL3_MT_CHANGE_CIPHER_SPEC) {
BIO *rbio;
/*
* CCS messages don't have a message sequence number so this is probably
* because of an out-of-order CCS. We'll just drop it.
*/
s->init_num = 0;
s->rwstate = SSL_READING;
rbio = SSL_get_rbio(s);
BIO_clear_retry_flags(rbio);
BIO_set_retry_read(rbio);
return 0;
}
SSLfatal(s, SSL3_AD_UNEXPECTED_MESSAGE,
SSL_F_OSSL_STATEM_SERVER_READ_TRANSITION,
SSL_R_UNEXPECTED_MESSAGE);
return 0;
}
/*
* Should we send a ServerKeyExchange message?
*
* Valid return values are:
* 1: Yes
* 0: No
*/
static int send_server_key_exchange(SSL *s)
{
unsigned long alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
/*
* only send a ServerKeyExchange if DH or fortezza but we have a
* sign only certificate PSK: may send PSK identity hints For
* ECC ciphersuites, we send a serverKeyExchange message only if
* the cipher suite is either ECDH-anon or ECDHE. In other cases,
* the server certificate contains the server's public key for
* key exchange.
*/
if (alg_k & (SSL_kDHE | SSL_kECDHE)
/*
* PSK: send ServerKeyExchange if PSK identity hint if
* provided
*/
#ifndef OPENSSL_NO_PSK
/* Only send SKE if we have identity hint for plain PSK */
|| ((alg_k & (SSL_kPSK | SSL_kRSAPSK))
&& s->cert->psk_identity_hint)
/* For other PSK always send SKE */
|| (alg_k & (SSL_PSK & (SSL_kDHEPSK | SSL_kECDHEPSK)))
#endif
#ifndef OPENSSL_NO_SRP
/* SRP: send ServerKeyExchange */
|| (alg_k & SSL_kSRP)
#endif
) {
return 1;
}
return 0;
}
/*
* Should we send a CertificateRequest message?
*
* Valid return values are:
* 1: Yes
* 0: No
*/
int send_certificate_request(SSL *s)
{
if (
/* don't request cert unless asked for it: */
s->verify_mode & SSL_VERIFY_PEER
/*
* don't request if post-handshake-only unless doing
* post-handshake in TLSv1.3:
*/
&& (!SSL_IS_TLS13(s) || !(s->verify_mode & SSL_VERIFY_POST_HANDSHAKE)
|| s->post_handshake_auth == SSL_PHA_REQUEST_PENDING)
/*
* if SSL_VERIFY_CLIENT_ONCE is set, don't request cert
* a second time:
*/
&& (s->certreqs_sent < 1 ||
!(s->verify_mode & SSL_VERIFY_CLIENT_ONCE))
/*
* never request cert in anonymous ciphersuites (see
* section "Certificate request" in SSL 3 drafts and in
* RFC 2246):
*/
&& (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL)
/*
* ... except when the application insists on
* verification (against the specs, but statem_clnt.c accepts
* this for SSL 3)
*/
|| (s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT))
/* don't request certificate for SRP auth */
&& !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aSRP)
/*
* With normal PSK Certificates and Certificate Requests
* are omitted
*/
&& !(s->s3->tmp.new_cipher->algorithm_auth & SSL_aPSK)) {
return 1;
}
return 0;
}
/*
* ossl_statem_server13_write_transition() works out what handshake state to
* move to next when a TLSv1.3 server is writing messages to be sent to the
* client.
*/
static WRITE_TRAN ossl_statem_server13_write_transition(SSL *s)
{
OSSL_STATEM *st = &s->statem;
/*
* No case for TLS_ST_BEFORE, because at that stage we have not negotiated
* TLSv1.3 yet, so that is handled by ossl_statem_server_write_transition()
*/
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_SERVER13_WRITE_TRANSITION,
ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_OK:
if (s->key_update != SSL_KEY_UPDATE_NONE) {
st->hand_state = TLS_ST_SW_KEY_UPDATE;
return WRITE_TRAN_CONTINUE;
}
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
st->hand_state = TLS_ST_SW_CERT_REQ;
return WRITE_TRAN_CONTINUE;
}
/* Try to read from the client instead */
return WRITE_TRAN_FINISHED;
case TLS_ST_SR_CLNT_HELLO:
st->hand_state = TLS_ST_SW_SRVR_HELLO;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SRVR_HELLO:
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
&& s->hello_retry_request != SSL_HRR_COMPLETE)
st->hand_state = TLS_ST_SW_CHANGE;
else if (s->hello_retry_request == SSL_HRR_PENDING)
st->hand_state = TLS_ST_EARLY_DATA;
else
st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CHANGE:
if (s->hello_retry_request == SSL_HRR_PENDING)
st->hand_state = TLS_ST_EARLY_DATA;
else
st->hand_state = TLS_ST_SW_ENCRYPTED_EXTENSIONS;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
if (s->hit)
st->hand_state = TLS_ST_SW_FINISHED;
else if (send_certificate_request(s))
st->hand_state = TLS_ST_SW_CERT_REQ;
else
st->hand_state = TLS_ST_SW_CERT;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CERT_REQ:
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
s->post_handshake_auth = SSL_PHA_REQUESTED;
st->hand_state = TLS_ST_OK;
} else {
st->hand_state = TLS_ST_SW_CERT;
}
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CERT:
st->hand_state = TLS_ST_SW_CERT_VRFY;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CERT_VRFY:
st->hand_state = TLS_ST_SW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_FINISHED:
st->hand_state = TLS_ST_EARLY_DATA;
return WRITE_TRAN_CONTINUE;
case TLS_ST_EARLY_DATA:
return WRITE_TRAN_FINISHED;
case TLS_ST_SR_FINISHED:
/*
* Technically we have finished the handshake at this point, but we're
* going to remain "in_init" for now and write out any session tickets
* immediately.
*/
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
s->post_handshake_auth = SSL_PHA_EXT_RECEIVED;
} else if (!s->ext.ticket_expected) {
/*
* If we're not going to renew the ticket then we just finish the
* handshake at this point.
*/
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
}
if (s->num_tickets > s->sent_tickets)
st->hand_state = TLS_ST_SW_SESSION_TICKET;
else
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SR_KEY_UPDATE:
if (s->key_update != SSL_KEY_UPDATE_NONE) {
st->hand_state = TLS_ST_SW_KEY_UPDATE;
return WRITE_TRAN_CONTINUE;
}
/* Fall through */
case TLS_ST_SW_KEY_UPDATE:
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SESSION_TICKET:
/* In a resumption we only ever send a maximum of one new ticket.
* Following an initial handshake we send the number of tickets we have
* been configured for.
*/
if (s->hit || s->num_tickets <= s->sent_tickets) {
/* We've written enough tickets out. */
st->hand_state = TLS_ST_OK;
}
return WRITE_TRAN_CONTINUE;
}
}
/*
* ossl_statem_server_write_transition() works out what handshake state to move
* to next when the server is writing messages to be sent to the client.
*/
WRITE_TRAN ossl_statem_server_write_transition(SSL *s)
{
OSSL_STATEM *st = &s->statem;
/*
* Note that before the ClientHello we don't know what version we are going
* to negotiate yet, so we don't take this branch until later
*/
if (SSL_IS_TLS13(s))
return ossl_statem_server13_write_transition(s);
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_SERVER_WRITE_TRANSITION,
ERR_R_INTERNAL_ERROR);
return WRITE_TRAN_ERROR;
case TLS_ST_OK:
if (st->request_state == TLS_ST_SW_HELLO_REQ) {
/* We must be trying to renegotiate */
st->hand_state = TLS_ST_SW_HELLO_REQ;
st->request_state = TLS_ST_BEFORE;
return WRITE_TRAN_CONTINUE;
}
/* Must be an incoming ClientHello */
if (!tls_setup_handshake(s)) {
/* SSLfatal() already called */
return WRITE_TRAN_ERROR;
}
/* Fall through */
case TLS_ST_BEFORE:
/* Just go straight to trying to read from the client */
return WRITE_TRAN_FINISHED;
case TLS_ST_SW_HELLO_REQ:
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SR_CLNT_HELLO:
if (SSL_IS_DTLS(s) && !s->d1->cookie_verified
&& (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE)) {
st->hand_state = DTLS_ST_SW_HELLO_VERIFY_REQUEST;
} else if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
/* We must have rejected the renegotiation */
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
} else {
st->hand_state = TLS_ST_SW_SRVR_HELLO;
}
return WRITE_TRAN_CONTINUE;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
return WRITE_TRAN_FINISHED;
case TLS_ST_SW_SRVR_HELLO:
if (s->hit) {
if (s->ext.ticket_expected)
st->hand_state = TLS_ST_SW_SESSION_TICKET;
else
st->hand_state = TLS_ST_SW_CHANGE;
} else {
/* Check if it is anon DH or anon ECDH, */
/* normal PSK or SRP */
if (!(s->s3->tmp.new_cipher->algorithm_auth &
(SSL_aNULL | SSL_aSRP | SSL_aPSK))) {
st->hand_state = TLS_ST_SW_CERT;
} else if (send_server_key_exchange(s)) {
st->hand_state = TLS_ST_SW_KEY_EXCH;
} else if (send_certificate_request(s)) {
st->hand_state = TLS_ST_SW_CERT_REQ;
} else {
st->hand_state = TLS_ST_SW_SRVR_DONE;
}
}
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CERT:
if (s->ext.status_expected) {
st->hand_state = TLS_ST_SW_CERT_STATUS;
return WRITE_TRAN_CONTINUE;
}
/* Fall through */
case TLS_ST_SW_CERT_STATUS:
if (send_server_key_exchange(s)) {
st->hand_state = TLS_ST_SW_KEY_EXCH;
return WRITE_TRAN_CONTINUE;
}
/* Fall through */
case TLS_ST_SW_KEY_EXCH:
if (send_certificate_request(s)) {
st->hand_state = TLS_ST_SW_CERT_REQ;
return WRITE_TRAN_CONTINUE;
}
/* Fall through */
case TLS_ST_SW_CERT_REQ:
st->hand_state = TLS_ST_SW_SRVR_DONE;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SRVR_DONE:
return WRITE_TRAN_FINISHED;
case TLS_ST_SR_FINISHED:
if (s->hit) {
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
} else if (s->ext.ticket_expected) {
st->hand_state = TLS_ST_SW_SESSION_TICKET;
} else {
st->hand_state = TLS_ST_SW_CHANGE;
}
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_SESSION_TICKET:
st->hand_state = TLS_ST_SW_CHANGE;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_CHANGE:
st->hand_state = TLS_ST_SW_FINISHED;
return WRITE_TRAN_CONTINUE;
case TLS_ST_SW_FINISHED:
if (s->hit) {
return WRITE_TRAN_FINISHED;
}
st->hand_state = TLS_ST_OK;
return WRITE_TRAN_CONTINUE;
}
}
/*
* Perform any pre work that needs to be done prior to sending a message from
* the server to the client.
*/
WORK_STATE ossl_statem_server_pre_work(SSL *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* No pre work to be done */
break;
case TLS_ST_SW_HELLO_REQ:
s->shutdown = 0;
if (SSL_IS_DTLS(s))
dtls1_clear_sent_buffer(s);
break;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
s->shutdown = 0;
if (SSL_IS_DTLS(s)) {
dtls1_clear_sent_buffer(s);
/* We don't buffer this message so don't use the timer */
st->use_timer = 0;
}
break;
case TLS_ST_SW_SRVR_HELLO:
if (SSL_IS_DTLS(s)) {
/*
* Messages we write from now on should be buffered and
* retransmitted if necessary, so we need to use the timer now
*/
st->use_timer = 1;
}
break;
case TLS_ST_SW_SRVR_DONE:
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && BIO_dgram_is_sctp(SSL_get_wbio(s))) {
/* Calls SSLfatal() as required */
return dtls_wait_for_dry(s);
}
#endif
return WORK_FINISHED_CONTINUE;
case TLS_ST_SW_SESSION_TICKET:
if (SSL_IS_TLS13(s) && s->sent_tickets == 0) {
/*
* Actually this is the end of the handshake, but we're going
* straight into writing the session ticket out. So we finish off
* the handshake, but keep the various buffers active.
*
* Calls SSLfatal as required.
*/
return tls_finish_handshake(s, wst, 0, 0);
} if (SSL_IS_DTLS(s)) {
/*
* We're into the last flight. We don't retransmit the last flight
* unless we need to, so we don't use the timer
*/
st->use_timer = 0;
}
break;
case TLS_ST_SW_CHANGE:
if (SSL_IS_TLS13(s))
break;
s->session->cipher = s->s3->tmp.new_cipher;
if (!s->method->ssl3_enc->setup_key_block(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
if (SSL_IS_DTLS(s)) {
/*
* We're into the last flight. We don't retransmit the last flight
* unless we need to, so we don't use the timer. This might have
* already been set to 0 if we sent a NewSessionTicket message,
* but we'll set it again here in case we didn't.
*/
st->use_timer = 0;
}
return WORK_FINISHED_CONTINUE;
case TLS_ST_EARLY_DATA:
if (s->early_data_state != SSL_EARLY_DATA_ACCEPTING
&& (s->s3->flags & TLS1_FLAGS_STATELESS) == 0)
return WORK_FINISHED_CONTINUE;
/* Fall through */
case TLS_ST_OK:
/* Calls SSLfatal() as required */
return tls_finish_handshake(s, wst, 1, 1);
}
return WORK_FINISHED_CONTINUE;
}
static ossl_inline int conn_is_closed(void)
{
switch (get_last_sys_error()) {
#if defined(EPIPE)
case EPIPE:
return 1;
#endif
#if defined(ECONNRESET)
case ECONNRESET:
return 1;
+#endif
+#if defined(WSAECONNRESET)
+ case WSAECONNRESET:
+ return 1;
#endif
default:
return 0;
}
}
/*
* Perform any work that needs to be done after sending a message from the
* server to the client.
*/
WORK_STATE ossl_statem_server_post_work(SSL *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
s->init_num = 0;
switch (st->hand_state) {
default:
/* No post work to be done */
break;
case TLS_ST_SW_HELLO_REQ:
if (statem_flush(s) != 1)
return WORK_MORE_A;
if (!ssl3_init_finished_mac(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
break;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
if (statem_flush(s) != 1)
return WORK_MORE_A;
/* HelloVerifyRequest resets Finished MAC */
if (s->version != DTLS1_BAD_VER && !ssl3_init_finished_mac(s)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
/*
* The next message should be another ClientHello which we need to
* treat like it was the first packet
*/
s->first_packet = 1;
break;
case TLS_ST_SW_SRVR_HELLO:
if (SSL_IS_TLS13(s) && s->hello_retry_request == SSL_HRR_PENDING) {
if ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) == 0
&& statem_flush(s) != 1)
return WORK_MORE_A;
break;
}
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && s->hit) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
size_t labellen;
/*
* Add new shared key for SCTP-Auth, will be ignored if no
* SCTP used.
*/
memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
sizeof(DTLS1_SCTP_AUTH_LABEL));
/* Don't include the terminating zero. */
labellen = sizeof(labelbuffer) - 1;
if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
labellen += 1;
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0,
0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_SERVER_POST_WORK,
ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
}
#endif
if (!SSL_IS_TLS13(s)
|| ((s->options & SSL_OP_ENABLE_MIDDLEBOX_COMPAT) != 0
&& s->hello_retry_request != SSL_HRR_COMPLETE))
break;
/* Fall through */
case TLS_ST_SW_CHANGE:
if (s->hello_retry_request == SSL_HRR_PENDING) {
if (!statem_flush(s))
return WORK_MORE_A;
break;
}
if (SSL_IS_TLS13(s)) {
if (!s->method->ssl3_enc->setup_key_block(s)
|| !s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_WRITE)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
if (s->ext.early_data != SSL_EARLY_DATA_ACCEPTED
&& !s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE |SSL3_CHANGE_CIPHER_SERVER_READ)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
/*
* We don't yet know whether the next record we are going to receive
* is an unencrypted alert, an encrypted alert, or an encrypted
* handshake message. We temporarily tolerate unencrypted alerts.
*/
s->statem.enc_read_state = ENC_READ_STATE_ALLOW_PLAIN_ALERTS;
break;
}
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && !s->hit) {
/*
* Change to new shared key of SCTP-Auth, will be ignored if
* no SCTP used.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
0, NULL);
}
#endif
if (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CHANGE_CIPHER_SERVER_WRITE))
{
/* SSLfatal() already called */
return WORK_ERROR;
}
if (SSL_IS_DTLS(s))
dtls1_reset_seq_numbers(s, SSL3_CC_WRITE);
break;
case TLS_ST_SW_SRVR_DONE:
if (statem_flush(s) != 1)
return WORK_MORE_A;
break;
case TLS_ST_SW_FINISHED:
if (statem_flush(s) != 1)
return WORK_MORE_A;
#ifndef OPENSSL_NO_SCTP
if (SSL_IS_DTLS(s) && s->hit) {
/*
* Change to new shared key of SCTP-Auth, will be ignored if
* no SCTP used.
*/
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_NEXT_AUTH_KEY,
0, NULL);
}
#endif
if (SSL_IS_TLS13(s)) {
if (!s->method->ssl3_enc->generate_master_secret(s,
s->master_secret, s->handshake_secret, 0,
&s->session->master_key_length)
|| !s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_APPLICATION | SSL3_CHANGE_CIPHER_SERVER_WRITE))
/* SSLfatal() already called */
return WORK_ERROR;
}
break;
case TLS_ST_SW_CERT_REQ:
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
if (statem_flush(s) != 1)
return WORK_MORE_A;
}
break;
case TLS_ST_SW_KEY_UPDATE:
if (statem_flush(s) != 1)
return WORK_MORE_A;
if (!tls13_update_key(s, 1)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
break;
case TLS_ST_SW_SESSION_TICKET:
clear_sys_error();
if (SSL_IS_TLS13(s) && statem_flush(s) != 1) {
if (SSL_get_error(s, 0) == SSL_ERROR_SYSCALL
&& conn_is_closed()) {
/*
* We ignore connection closed errors in TLSv1.3 when sending a
* NewSessionTicket and behave as if we were successful. This is
* so that we are still able to read data sent to us by a client
* that closes soon after the end of the handshake without
* waiting to read our post-handshake NewSessionTickets.
*/
s->rwstate = SSL_NOTHING;
break;
}
return WORK_MORE_A;
}
break;
}
return WORK_FINISHED_CONTINUE;
}
/*
* Get the message construction function and message type for sending from the
* server
*
* Valid return values are:
* 1: Success
* 0: Error
*/
int ossl_statem_server_construct_message(SSL *s, WPACKET *pkt,
confunc_f *confunc, int *mt)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_SERVER_CONSTRUCT_MESSAGE,
SSL_R_BAD_HANDSHAKE_STATE);
return 0;
case TLS_ST_SW_CHANGE:
if (SSL_IS_DTLS(s))
*confunc = dtls_construct_change_cipher_spec;
else
*confunc = tls_construct_change_cipher_spec;
*mt = SSL3_MT_CHANGE_CIPHER_SPEC;
break;
case DTLS_ST_SW_HELLO_VERIFY_REQUEST:
*confunc = dtls_construct_hello_verify_request;
*mt = DTLS1_MT_HELLO_VERIFY_REQUEST;
break;
case TLS_ST_SW_HELLO_REQ:
/* No construction function needed */
*confunc = NULL;
*mt = SSL3_MT_HELLO_REQUEST;
break;
case TLS_ST_SW_SRVR_HELLO:
*confunc = tls_construct_server_hello;
*mt = SSL3_MT_SERVER_HELLO;
break;
case TLS_ST_SW_CERT:
*confunc = tls_construct_server_certificate;
*mt = SSL3_MT_CERTIFICATE;
break;
case TLS_ST_SW_CERT_VRFY:
*confunc = tls_construct_cert_verify;
*mt = SSL3_MT_CERTIFICATE_VERIFY;
break;
case TLS_ST_SW_KEY_EXCH:
*confunc = tls_construct_server_key_exchange;
*mt = SSL3_MT_SERVER_KEY_EXCHANGE;
break;
case TLS_ST_SW_CERT_REQ:
*confunc = tls_construct_certificate_request;
*mt = SSL3_MT_CERTIFICATE_REQUEST;
break;
case TLS_ST_SW_SRVR_DONE:
*confunc = tls_construct_server_done;
*mt = SSL3_MT_SERVER_DONE;
break;
case TLS_ST_SW_SESSION_TICKET:
*confunc = tls_construct_new_session_ticket;
*mt = SSL3_MT_NEWSESSION_TICKET;
break;
case TLS_ST_SW_CERT_STATUS:
*confunc = tls_construct_cert_status;
*mt = SSL3_MT_CERTIFICATE_STATUS;
break;
case TLS_ST_SW_FINISHED:
*confunc = tls_construct_finished;
*mt = SSL3_MT_FINISHED;
break;
case TLS_ST_EARLY_DATA:
*confunc = NULL;
*mt = SSL3_MT_DUMMY;
break;
case TLS_ST_SW_ENCRYPTED_EXTENSIONS:
*confunc = tls_construct_encrypted_extensions;
*mt = SSL3_MT_ENCRYPTED_EXTENSIONS;
break;
case TLS_ST_SW_KEY_UPDATE:
*confunc = tls_construct_key_update;
*mt = SSL3_MT_KEY_UPDATE;
break;
}
return 1;
}
/*
* Maximum size (excluding the Handshake header) of a ClientHello message,
* calculated as follows:
*
* 2 + # client_version
* 32 + # only valid length for random
* 1 + # length of session_id
* 32 + # maximum size for session_id
* 2 + # length of cipher suites
* 2^16-2 + # maximum length of cipher suites array
* 1 + # length of compression_methods
* 2^8-1 + # maximum length of compression methods
* 2 + # length of extensions
* 2^16-1 # maximum length of extensions
*/
#define CLIENT_HELLO_MAX_LENGTH 131396
#define CLIENT_KEY_EXCH_MAX_LENGTH 2048
#define NEXT_PROTO_MAX_LENGTH 514
/*
* Returns the maximum allowed length for the current message that we are
* reading. Excludes the message header.
*/
size_t ossl_statem_server_max_message_size(SSL *s)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* Shouldn't happen */
return 0;
case TLS_ST_SR_CLNT_HELLO:
return CLIENT_HELLO_MAX_LENGTH;
case TLS_ST_SR_END_OF_EARLY_DATA:
return END_OF_EARLY_DATA_MAX_LENGTH;
case TLS_ST_SR_CERT:
return s->max_cert_list;
case TLS_ST_SR_KEY_EXCH:
return CLIENT_KEY_EXCH_MAX_LENGTH;
case TLS_ST_SR_CERT_VRFY:
return SSL3_RT_MAX_PLAIN_LENGTH;
#ifndef OPENSSL_NO_NEXTPROTONEG
case TLS_ST_SR_NEXT_PROTO:
return NEXT_PROTO_MAX_LENGTH;
#endif
case TLS_ST_SR_CHANGE:
return CCS_MAX_LENGTH;
case TLS_ST_SR_FINISHED:
return FINISHED_MAX_LENGTH;
case TLS_ST_SR_KEY_UPDATE:
return KEY_UPDATE_MAX_LENGTH;
}
}
/*
* Process a message that the server has received from the client.
*/
MSG_PROCESS_RETURN ossl_statem_server_process_message(SSL *s, PACKET *pkt)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_SERVER_PROCESS_MESSAGE,
ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
case TLS_ST_SR_CLNT_HELLO:
return tls_process_client_hello(s, pkt);
case TLS_ST_SR_END_OF_EARLY_DATA:
return tls_process_end_of_early_data(s, pkt);
case TLS_ST_SR_CERT:
return tls_process_client_certificate(s, pkt);
case TLS_ST_SR_KEY_EXCH:
return tls_process_client_key_exchange(s, pkt);
case TLS_ST_SR_CERT_VRFY:
return tls_process_cert_verify(s, pkt);
#ifndef OPENSSL_NO_NEXTPROTONEG
case TLS_ST_SR_NEXT_PROTO:
return tls_process_next_proto(s, pkt);
#endif
case TLS_ST_SR_CHANGE:
return tls_process_change_cipher_spec(s, pkt);
case TLS_ST_SR_FINISHED:
return tls_process_finished(s, pkt);
case TLS_ST_SR_KEY_UPDATE:
return tls_process_key_update(s, pkt);
}
}
/*
* Perform any further processing required following the receipt of a message
* from the client
*/
WORK_STATE ossl_statem_server_post_process_message(SSL *s, WORK_STATE wst)
{
OSSL_STATEM *st = &s->statem;
switch (st->hand_state) {
default:
/* Shouldn't happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_OSSL_STATEM_SERVER_POST_PROCESS_MESSAGE,
ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
case TLS_ST_SR_CLNT_HELLO:
return tls_post_process_client_hello(s, wst);
case TLS_ST_SR_KEY_EXCH:
return tls_post_process_client_key_exchange(s, wst);
}
}
#ifndef OPENSSL_NO_SRP
/* Returns 1 on success, 0 for retryable error, -1 for fatal error */
static int ssl_check_srp_ext_ClientHello(SSL *s)
{
int ret;
int al = SSL_AD_UNRECOGNIZED_NAME;
if ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_kSRP) &&
(s->srp_ctx.TLS_ext_srp_username_callback != NULL)) {
if (s->srp_ctx.login == NULL) {
/*
* RFC 5054 says SHOULD reject, we do so if There is no srp
* login name
*/
SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
SSL_R_PSK_IDENTITY_NOT_FOUND);
return -1;
} else {
ret = SSL_srp_server_param_with_username(s, &al);
if (ret < 0)
return 0;
if (ret == SSL3_AL_FATAL) {
SSLfatal(s, al, SSL_F_SSL_CHECK_SRP_EXT_CLIENTHELLO,
al == SSL_AD_UNKNOWN_PSK_IDENTITY
? SSL_R_PSK_IDENTITY_NOT_FOUND
: SSL_R_CLIENTHELLO_TLSEXT);
return -1;
}
}
}
return 1;
}
#endif
int dtls_raw_hello_verify_request(WPACKET *pkt, unsigned char *cookie,
size_t cookie_len)
{
/* Always use DTLS 1.0 version: see RFC 6347 */
if (!WPACKET_put_bytes_u16(pkt, DTLS1_VERSION)
|| !WPACKET_sub_memcpy_u8(pkt, cookie, cookie_len))
return 0;
return 1;
}
int dtls_construct_hello_verify_request(SSL *s, WPACKET *pkt)
{
unsigned int cookie_leni;
if (s->ctx->app_gen_cookie_cb == NULL ||
s->ctx->app_gen_cookie_cb(s, s->d1->cookie,
&cookie_leni) == 0 ||
cookie_leni > 255) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
SSL_R_COOKIE_GEN_CALLBACK_FAILURE);
return 0;
}
s->d1->cookie_len = cookie_leni;
if (!dtls_raw_hello_verify_request(pkt, s->d1->cookie,
s->d1->cookie_len)) {
SSLfatal(s, SSL_AD_NO_ALERT, SSL_F_DTLS_CONSTRUCT_HELLO_VERIFY_REQUEST,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_EC
/*-
* ssl_check_for_safari attempts to fingerprint Safari using OS X
* SecureTransport using the TLS extension block in |hello|.
* Safari, since 10.6, sends exactly these extensions, in this order:
* SNI,
* elliptic_curves
* ec_point_formats
* signature_algorithms (for TLSv1.2 only)
*
* We wish to fingerprint Safari because they broke ECDHE-ECDSA support in 10.8,
* but they advertise support. So enabling ECDHE-ECDSA ciphers breaks them.
* Sadly we cannot differentiate 10.6, 10.7 and 10.8.4 (which work), from
* 10.8..10.8.3 (which don't work).
*/
static void ssl_check_for_safari(SSL *s, const CLIENTHELLO_MSG *hello)
{
static const unsigned char kSafariExtensionsBlock[] = {
0x00, 0x0a, /* elliptic_curves extension */
0x00, 0x08, /* 8 bytes */
0x00, 0x06, /* 6 bytes of curve ids */
0x00, 0x17, /* P-256 */
0x00, 0x18, /* P-384 */
0x00, 0x19, /* P-521 */
0x00, 0x0b, /* ec_point_formats */
0x00, 0x02, /* 2 bytes */
0x01, /* 1 point format */
0x00, /* uncompressed */
/* The following is only present in TLS 1.2 */
0x00, 0x0d, /* signature_algorithms */
0x00, 0x0c, /* 12 bytes */
0x00, 0x0a, /* 10 bytes */
0x05, 0x01, /* SHA-384/RSA */
0x04, 0x01, /* SHA-256/RSA */
0x02, 0x01, /* SHA-1/RSA */
0x04, 0x03, /* SHA-256/ECDSA */
0x02, 0x03, /* SHA-1/ECDSA */
};
/* Length of the common prefix (first two extensions). */
static const size_t kSafariCommonExtensionsLength = 18;
unsigned int type;
PACKET sni, tmppkt;
size_t ext_len;
tmppkt = hello->extensions;
if (!PACKET_forward(&tmppkt, 2)
|| !PACKET_get_net_2(&tmppkt, &type)
|| !PACKET_get_length_prefixed_2(&tmppkt, &sni)) {
return;
}
if (type != TLSEXT_TYPE_server_name)
return;
ext_len = TLS1_get_client_version(s) >= TLS1_2_VERSION ?
sizeof(kSafariExtensionsBlock) : kSafariCommonExtensionsLength;
s->s3->is_probably_safari = PACKET_equal(&tmppkt, kSafariExtensionsBlock,
ext_len);
}
#endif /* !OPENSSL_NO_EC */
MSG_PROCESS_RETURN tls_process_client_hello(SSL *s, PACKET *pkt)
{
/* |cookie| will only be initialized for DTLS. */
PACKET session_id, compression, extensions, cookie;
static const unsigned char null_compression = 0;
CLIENTHELLO_MSG *clienthello = NULL;
/* Check if this is actually an unexpected renegotiation ClientHello */
if (s->renegotiate == 0 && !SSL_IS_FIRST_HANDSHAKE(s)) {
if (!ossl_assert(!SSL_IS_TLS13(s))) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
goto err;
}
if ((s->options & SSL_OP_NO_RENEGOTIATION) != 0
|| (!s->s3->send_connection_binding
&& (s->options
& SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION) == 0)) {
ssl3_send_alert(s, SSL3_AL_WARNING, SSL_AD_NO_RENEGOTIATION);
return MSG_PROCESS_FINISHED_READING;
}
s->renegotiate = 1;
s->new_session = 1;
}
clienthello = OPENSSL_zalloc(sizeof(*clienthello));
if (clienthello == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* First, parse the raw ClientHello data into the CLIENTHELLO_MSG structure.
*/
clienthello->isv2 = RECORD_LAYER_is_sslv2_record(&s->rlayer);
PACKET_null_init(&cookie);
if (clienthello->isv2) {
unsigned int mt;
if (!SSL_IS_FIRST_HANDSHAKE(s)
|| s->hello_retry_request != SSL_HRR_NONE) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_UNEXPECTED_MESSAGE);
goto err;
}
/*-
* An SSLv3/TLSv1 backwards-compatible CLIENT-HELLO in an SSLv2
* header is sent directly on the wire, not wrapped as a TLS
* record. Our record layer just processes the message length and passes
* the rest right through. Its format is:
* Byte Content
* 0-1 msg_length - decoded by the record layer
* 2 msg_type - s->init_msg points here
* 3-4 version
* 5-6 cipher_spec_length
* 7-8 session_id_length
* 9-10 challenge_length
* ... ...
*/
if (!PACKET_get_1(pkt, &mt)
|| mt != SSL2_MT_CLIENT_HELLO) {
/*
* Should never happen. We should have tested this in the record
* layer in order to have determined that this is a SSLv2 record
* in the first place
*/
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (!PACKET_get_net_2(pkt, &clienthello->legacy_version)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_LENGTH_TOO_SHORT);
goto err;
}
/* Parse the message and load client random. */
if (clienthello->isv2) {
/*
* Handle an SSLv2 backwards compatible ClientHello
* Note, this is only for SSLv3+ using the backward compatible format.
* Real SSLv2 is not supported, and is rejected below.
*/
unsigned int ciphersuite_len, session_id_len, challenge_len;
PACKET challenge;
if (!PACKET_get_net_2(pkt, &ciphersuite_len)
|| !PACKET_get_net_2(pkt, &session_id_len)
|| !PACKET_get_net_2(pkt, &challenge_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_RECORD_LENGTH_MISMATCH);
goto err;
}
if (session_id_len > SSL_MAX_SSL_SESSION_ID_LENGTH) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_PROCESS_CLIENT_HELLO, SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_get_sub_packet(pkt, &clienthello->ciphersuites,
ciphersuite_len)
|| !PACKET_copy_bytes(pkt, clienthello->session_id, session_id_len)
|| !PACKET_get_sub_packet(pkt, &challenge, challenge_len)
/* No extensions. */
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_RECORD_LENGTH_MISMATCH);
goto err;
}
clienthello->session_id_len = session_id_len;
/* Load the client random and compression list. We use SSL3_RANDOM_SIZE
* here rather than sizeof(clienthello->random) because that is the limit
* for SSLv3 and it is fixed. It won't change even if
* sizeof(clienthello->random) does.
*/
challenge_len = challenge_len > SSL3_RANDOM_SIZE
? SSL3_RANDOM_SIZE : challenge_len;
memset(clienthello->random, 0, SSL3_RANDOM_SIZE);
if (!PACKET_copy_bytes(&challenge,
clienthello->random + SSL3_RANDOM_SIZE -
challenge_len, challenge_len)
/* Advertise only null compression. */
|| !PACKET_buf_init(&compression, &null_compression, 1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
goto err;
}
PACKET_null_init(&clienthello->extensions);
} else {
/* Regular ClientHello. */
if (!PACKET_copy_bytes(pkt, clienthello->random, SSL3_RANDOM_SIZE)
|| !PACKET_get_length_prefixed_1(pkt, &session_id)
|| !PACKET_copy_all(&session_id, clienthello->session_id,
SSL_MAX_SSL_SESSION_ID_LENGTH,
&clienthello->session_id_len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
if (SSL_IS_DTLS(s)) {
if (!PACKET_get_length_prefixed_1(pkt, &cookie)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_copy_all(&cookie, clienthello->dtls_cookie,
DTLS1_COOKIE_LENGTH,
&clienthello->dtls_cookie_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CLIENT_HELLO, ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* If we require cookies and this ClientHello doesn't contain one,
* just return since we do not want to allocate any memory yet.
* So check cookie length...
*/
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
if (clienthello->dtls_cookie_len == 0) {
OPENSSL_free(clienthello);
return MSG_PROCESS_FINISHED_READING;
}
}
}
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->ciphersuites)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
if (!PACKET_get_length_prefixed_1(pkt, &compression)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
/* Could be empty. */
if (PACKET_remaining(pkt) == 0) {
PACKET_null_init(&clienthello->extensions);
} else {
if (!PACKET_get_length_prefixed_2(pkt, &clienthello->extensions)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
SSL_R_LENGTH_MISMATCH);
goto err;
}
}
}
if (!PACKET_copy_all(&compression, clienthello->compressions,
MAX_COMPRESSIONS_SIZE,
&clienthello->compressions_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Preserve the raw extensions PACKET for later use */
extensions = clienthello->extensions;
if (!tls_collect_extensions(s, &extensions, SSL_EXT_CLIENT_HELLO,
&clienthello->pre_proc_exts,
&clienthello->pre_proc_exts_len, 1)) {
/* SSLfatal already been called */
goto err;
}
s->clienthello = clienthello;
return MSG_PROCESS_CONTINUE_PROCESSING;
err:
if (clienthello != NULL)
OPENSSL_free(clienthello->pre_proc_exts);
OPENSSL_free(clienthello);
return MSG_PROCESS_ERROR;
}
static int tls_early_post_process_client_hello(SSL *s)
{
unsigned int j;
int i, al = SSL_AD_INTERNAL_ERROR;
int protverr;
size_t loop;
unsigned long id;
#ifndef OPENSSL_NO_COMP
SSL_COMP *comp = NULL;
#endif
const SSL_CIPHER *c;
STACK_OF(SSL_CIPHER) *ciphers = NULL;
STACK_OF(SSL_CIPHER) *scsvs = NULL;
CLIENTHELLO_MSG *clienthello = s->clienthello;
DOWNGRADE dgrd = DOWNGRADE_NONE;
/* Finished parsing the ClientHello, now we can start processing it */
/* Give the ClientHello callback a crack at things */
if (s->ctx->client_hello_cb != NULL) {
/* A failure in the ClientHello callback terminates the connection. */
switch (s->ctx->client_hello_cb(s, &al, s->ctx->client_hello_cb_arg)) {
case SSL_CLIENT_HELLO_SUCCESS:
break;
case SSL_CLIENT_HELLO_RETRY:
s->rwstate = SSL_CLIENT_HELLO_CB;
return -1;
case SSL_CLIENT_HELLO_ERROR:
default:
SSLfatal(s, al,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_CALLBACK_FAILED);
goto err;
}
}
/* Set up the client_random */
memcpy(s->s3->client_random, clienthello->random, SSL3_RANDOM_SIZE);
/* Choose the version */
if (clienthello->isv2) {
if (clienthello->legacy_version == SSL2_VERSION
|| (clienthello->legacy_version & 0xff00)
!= (SSL3_VERSION_MAJOR << 8)) {
/*
* This is real SSLv2 or something completely unknown. We don't
* support it.
*/
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_UNKNOWN_PROTOCOL);
goto err;
}
/* SSLv3/TLS */
s->client_version = clienthello->legacy_version;
}
/*
* Do SSL/TLS version negotiation if applicable. For DTLS we just check
* versions are potentially compatible. Version negotiation comes later.
*/
if (!SSL_IS_DTLS(s)) {
protverr = ssl_choose_server_version(s, clienthello, &dgrd);
} else if (s->method->version != DTLS_ANY_VERSION &&
DTLS_VERSION_LT((int)clienthello->legacy_version, s->version)) {
protverr = SSL_R_VERSION_TOO_LOW;
} else {
protverr = 0;
}
if (protverr) {
if (SSL_IS_FIRST_HANDSHAKE(s)) {
/* like ssl3_get_record, send alert using remote version number */
s->version = s->client_version = clienthello->legacy_version;
}
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
goto err;
}
/* TLSv1.3 specifies that a ClientHello must end on a record boundary */
if (SSL_IS_TLS13(s) && RECORD_LAYER_processed_read_pending(&s->rlayer)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_NOT_ON_RECORD_BOUNDARY);
goto err;
}
if (SSL_IS_DTLS(s)) {
/* Empty cookie was already handled above by returning early. */
if (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) {
if (s->ctx->app_verify_cookie_cb != NULL) {
if (s->ctx->app_verify_cookie_cb(s, clienthello->dtls_cookie,
clienthello->dtls_cookie_len) == 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_COOKIE_MISMATCH);
goto err;
/* else cookie verification succeeded */
}
/* default verification */
} else if (s->d1->cookie_len != clienthello->dtls_cookie_len
|| memcmp(clienthello->dtls_cookie, s->d1->cookie,
s->d1->cookie_len) != 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_COOKIE_MISMATCH);
goto err;
}
s->d1->cookie_verified = 1;
}
if (s->method->version == DTLS_ANY_VERSION) {
protverr = ssl_choose_server_version(s, clienthello, &dgrd);
if (protverr != 0) {
s->version = s->client_version;
SSLfatal(s, SSL_AD_PROTOCOL_VERSION,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, protverr);
goto err;
}
}
}
s->hit = 0;
if (!ssl_cache_cipherlist(s, &clienthello->ciphersuites,
clienthello->isv2) ||
!bytes_to_cipher_list(s, &clienthello->ciphersuites, &ciphers, &scsvs,
clienthello->isv2, 1)) {
/* SSLfatal() already called */
goto err;
}
s->s3->send_connection_binding = 0;
/* Check what signalling cipher-suite values were received. */
if (scsvs != NULL) {
for(i = 0; i < sk_SSL_CIPHER_num(scsvs); i++) {
c = sk_SSL_CIPHER_value(scsvs, i);
if (SSL_CIPHER_get_id(c) == SSL3_CK_SCSV) {
if (s->renegotiate) {
/* SCSV is fatal if renegotiating */
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_SCSV_RECEIVED_WHEN_RENEGOTIATING);
goto err;
}
s->s3->send_connection_binding = 1;
} else if (SSL_CIPHER_get_id(c) == SSL3_CK_FALLBACK_SCSV &&
!ssl_check_version_downgrade(s)) {
/*
* This SCSV indicates that the client previously tried
* a higher version. We should fail if the current version
* is an unexpected downgrade, as that indicates that the first
* connection may have been tampered with in order to trigger
* an insecure downgrade.
*/
SSLfatal(s, SSL_AD_INAPPROPRIATE_FALLBACK,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INAPPROPRIATE_FALLBACK);
goto err;
}
}
}
/* For TLSv1.3 we must select the ciphersuite *before* session resumption */
if (SSL_IS_TLS13(s)) {
const SSL_CIPHER *cipher =
ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s));
if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_NO_SHARED_CIPHER);
goto err;
}
if (s->hello_retry_request == SSL_HRR_PENDING
&& (s->s3->tmp.new_cipher == NULL
|| s->s3->tmp.new_cipher->id != cipher->id)) {
/*
* A previous HRR picked a different ciphersuite to the one we
* just selected. Something must have changed.
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_BAD_CIPHER);
goto err;
}
s->s3->tmp.new_cipher = cipher;
}
/* We need to do this before getting the session */
if (!tls_parse_extension(s, TLSEXT_IDX_extended_master_secret,
SSL_EXT_CLIENT_HELLO,
clienthello->pre_proc_exts, NULL, 0)) {
/* SSLfatal() already called */
goto err;
}
/*
* We don't allow resumption in a backwards compatible ClientHello.
* TODO(openssl-team): in TLS1.1+, session_id MUST be empty.
*
* Versions before 0.9.7 always allow clients to resume sessions in
* renegotiation. 0.9.7 and later allow this by default, but optionally
* ignore resumption requests with flag
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION (it's a new flag rather
* than a change to default behavior so that applications relying on
* this for security won't even compile against older library versions).
* 1.0.1 and later also have a function SSL_renegotiate_abbreviated() to
* request renegotiation but not a new session (s->new_session remains
* unset): for servers, this essentially just means that the
* SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION setting will be
* ignored.
*/
if (clienthello->isv2 ||
(s->new_session &&
(s->options & SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION))) {
if (!ssl_get_new_session(s, 1)) {
/* SSLfatal() already called */
goto err;
}
} else {
i = ssl_get_prev_session(s, clienthello);
if (i == 1) {
/* previous session */
s->hit = 1;
} else if (i == -1) {
/* SSLfatal() already called */
goto err;
} else {
/* i == 0 */
if (!ssl_get_new_session(s, 1)) {
/* SSLfatal() already called */
goto err;
}
}
}
if (SSL_IS_TLS13(s)) {
memcpy(s->tmp_session_id, s->clienthello->session_id,
s->clienthello->session_id_len);
s->tmp_session_id_len = s->clienthello->session_id_len;
}
/*
* If it is a hit, check that the cipher is in the list. In TLSv1.3 we check
* ciphersuite compatibility with the session as part of resumption.
*/
if (!SSL_IS_TLS13(s) && s->hit) {
j = 0;
id = s->session->cipher->id;
#ifdef CIPHER_DEBUG
fprintf(stderr, "client sent %d ciphers\n", sk_SSL_CIPHER_num(ciphers));
#endif
for (i = 0; i < sk_SSL_CIPHER_num(ciphers); i++) {
c = sk_SSL_CIPHER_value(ciphers, i);
#ifdef CIPHER_DEBUG
fprintf(stderr, "client [%2d of %2d]:%s\n",
i, sk_SSL_CIPHER_num(ciphers), SSL_CIPHER_get_name(c));
#endif
if (c->id == id) {
j = 1;
break;
}
}
if (j == 0) {
/*
* we need to have the cipher in the cipher list if we are asked
* to reuse it
*/
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_REQUIRED_CIPHER_MISSING);
goto err;
}
}
for (loop = 0; loop < clienthello->compressions_len; loop++) {
if (clienthello->compressions[loop] == 0)
break;
}
if (loop >= clienthello->compressions_len) {
/* no compress */
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_NO_COMPRESSION_SPECIFIED);
goto err;
}
#ifndef OPENSSL_NO_EC
if (s->options & SSL_OP_SAFARI_ECDHE_ECDSA_BUG)
ssl_check_for_safari(s, clienthello);
#endif /* !OPENSSL_NO_EC */
/* TLS extensions */
if (!tls_parse_all_extensions(s, SSL_EXT_CLIENT_HELLO,
clienthello->pre_proc_exts, NULL, 0, 1)) {
/* SSLfatal() already called */
goto err;
}
/*
* Check if we want to use external pre-shared secret for this handshake
* for not reused session only. We need to generate server_random before
* calling tls_session_secret_cb in order to allow SessionTicket
* processing to use it in key derivation.
*/
{
unsigned char *pos;
pos = s->s3->server_random;
if (ssl_fill_hello_random(s, 1, pos, SSL3_RANDOM_SIZE, dgrd) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
goto err;
}
}
if (!s->hit
&& s->version >= TLS1_VERSION
&& !SSL_IS_TLS13(s)
&& !SSL_IS_DTLS(s)
&& s->ext.session_secret_cb) {
const SSL_CIPHER *pref_cipher = NULL;
/*
* s->session->master_key_length is a size_t, but this is an int for
* backwards compat reasons
*/
int master_key_length;
master_key_length = sizeof(s->session->master_key);
if (s->ext.session_secret_cb(s, s->session->master_key,
&master_key_length, ciphers,
&pref_cipher,
s->ext.session_secret_cb_arg)
&& master_key_length > 0) {
s->session->master_key_length = master_key_length;
s->hit = 1;
s->session->ciphers = ciphers;
s->session->verify_result = X509_V_OK;
ciphers = NULL;
/* check if some cipher was preferred by call back */
if (pref_cipher == NULL)
pref_cipher = ssl3_choose_cipher(s, s->session->ciphers,
SSL_get_ciphers(s));
if (pref_cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_NO_SHARED_CIPHER);
goto err;
}
s->session->cipher = pref_cipher;
sk_SSL_CIPHER_free(s->cipher_list);
s->cipher_list = sk_SSL_CIPHER_dup(s->session->ciphers);
sk_SSL_CIPHER_free(s->cipher_list_by_id);
s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
}
}
/*
* Worst case, we will use the NULL compression, but if we have other
* options, we will now look for them. We have complen-1 compression
* algorithms from the client, starting at q.
*/
s->s3->tmp.new_compression = NULL;
if (SSL_IS_TLS13(s)) {
/*
* We already checked above that the NULL compression method appears in
* the list. Now we check there aren't any others (which is illegal in
* a TLSv1.3 ClientHello.
*/
if (clienthello->compressions_len != 1) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto err;
}
}
#ifndef OPENSSL_NO_COMP
/* This only happens if we have a cache hit */
else if (s->session->compress_meth != 0) {
int m, comp_id = s->session->compress_meth;
unsigned int k;
/* Perform sanity checks on resumed compression algorithm */
/* Can't disable compression */
if (!ssl_allow_compression(s)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INCONSISTENT_COMPRESSION);
goto err;
}
/* Look for resumed compression method */
for (m = 0; m < sk_SSL_COMP_num(s->ctx->comp_methods); m++) {
comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
if (comp_id == comp->id) {
s->s3->tmp.new_compression = comp;
break;
}
}
if (s->s3->tmp.new_compression == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INVALID_COMPRESSION_ALGORITHM);
goto err;
}
/* Look for resumed method in compression list */
for (k = 0; k < clienthello->compressions_len; k++) {
if (clienthello->compressions[k] == comp_id)
break;
}
if (k >= clienthello->compressions_len) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_REQUIRED_COMPRESSION_ALGORITHM_MISSING);
goto err;
}
} else if (s->hit) {
comp = NULL;
} else if (ssl_allow_compression(s) && s->ctx->comp_methods) {
/* See if we have a match */
int m, nn, v, done = 0;
unsigned int o;
nn = sk_SSL_COMP_num(s->ctx->comp_methods);
for (m = 0; m < nn; m++) {
comp = sk_SSL_COMP_value(s->ctx->comp_methods, m);
v = comp->id;
for (o = 0; o < clienthello->compressions_len; o++) {
if (v == clienthello->compressions[o]) {
done = 1;
break;
}
}
if (done)
break;
}
if (done)
s->s3->tmp.new_compression = comp;
else
comp = NULL;
}
#else
/*
* If compression is disabled we'd better not try to resume a session
* using compression.
*/
if (s->session->compress_meth != 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
SSL_R_INCONSISTENT_COMPRESSION);
goto err;
}
#endif
/*
* Given s->session->ciphers and SSL_get_ciphers, we must pick a cipher
*/
if (!s->hit || SSL_IS_TLS13(s)) {
sk_SSL_CIPHER_free(s->session->ciphers);
s->session->ciphers = ciphers;
if (ciphers == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
ERR_R_INTERNAL_ERROR);
goto err;
}
ciphers = NULL;
}
if (!s->hit) {
#ifdef OPENSSL_NO_COMP
s->session->compress_meth = 0;
#else
s->session->compress_meth = (comp == NULL) ? 0 : comp->id;
#endif
}
sk_SSL_CIPHER_free(ciphers);
sk_SSL_CIPHER_free(scsvs);
OPENSSL_free(clienthello->pre_proc_exts);
OPENSSL_free(s->clienthello);
s->clienthello = NULL;
return 1;
err:
sk_SSL_CIPHER_free(ciphers);
sk_SSL_CIPHER_free(scsvs);
OPENSSL_free(clienthello->pre_proc_exts);
OPENSSL_free(s->clienthello);
s->clienthello = NULL;
return 0;
}
/*
* Call the status request callback if needed. Upon success, returns 1.
* Upon failure, returns 0.
*/
static int tls_handle_status_request(SSL *s)
{
s->ext.status_expected = 0;
/*
* If status request then ask callback what to do. Note: this must be
* called after servername callbacks in case the certificate has changed,
* and must be called after the cipher has been chosen because this may
* influence which certificate is sent
*/
if (s->ext.status_type != TLSEXT_STATUSTYPE_nothing && s->ctx != NULL
&& s->ctx->ext.status_cb != NULL) {
int ret;
/* If no certificate can't return certificate status */
if (s->s3->tmp.cert != NULL) {
/*
* Set current certificate to one we will use so SSL_get_certificate
* et al can pick it up.
*/
s->cert->key = s->s3->tmp.cert;
ret = s->ctx->ext.status_cb(s, s->ctx->ext.status_arg);
switch (ret) {
/* We don't want to send a status request response */
case SSL_TLSEXT_ERR_NOACK:
s->ext.status_expected = 0;
break;
/* status request response should be sent */
case SSL_TLSEXT_ERR_OK:
if (s->ext.ocsp.resp)
s->ext.status_expected = 1;
break;
/* something bad happened */
case SSL_TLSEXT_ERR_ALERT_FATAL:
default:
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_HANDLE_STATUS_REQUEST,
SSL_R_CLIENTHELLO_TLSEXT);
return 0;
}
}
}
return 1;
}
/*
* Call the alpn_select callback if needed. Upon success, returns 1.
* Upon failure, returns 0.
*/
int tls_handle_alpn(SSL *s)
{
const unsigned char *selected = NULL;
unsigned char selected_len = 0;
if (s->ctx->ext.alpn_select_cb != NULL && s->s3->alpn_proposed != NULL) {
int r = s->ctx->ext.alpn_select_cb(s, &selected, &selected_len,
s->s3->alpn_proposed,
(unsigned int)s->s3->alpn_proposed_len,
s->ctx->ext.alpn_select_cb_arg);
if (r == SSL_TLSEXT_ERR_OK) {
OPENSSL_free(s->s3->alpn_selected);
s->s3->alpn_selected = OPENSSL_memdup(selected, selected_len);
if (s->s3->alpn_selected == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_HANDLE_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->s3->alpn_selected_len = selected_len;
#ifndef OPENSSL_NO_NEXTPROTONEG
/* ALPN takes precedence over NPN. */
s->s3->npn_seen = 0;
#endif
/* Check ALPN is consistent with session */
if (s->session->ext.alpn_selected == NULL
|| selected_len != s->session->ext.alpn_selected_len
|| memcmp(selected, s->session->ext.alpn_selected,
selected_len) != 0) {
/* Not consistent so can't be used for early_data */
s->ext.early_data_ok = 0;
if (!s->hit) {
/*
* This is a new session and so alpn_selected should have
* been initialised to NULL. We should update it with the
* selected ALPN.
*/
if (!ossl_assert(s->session->ext.alpn_selected == NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_HANDLE_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.alpn_selected = OPENSSL_memdup(selected,
selected_len);
if (s->session->ext.alpn_selected == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_HANDLE_ALPN,
ERR_R_INTERNAL_ERROR);
return 0;
}
s->session->ext.alpn_selected_len = selected_len;
}
}
return 1;
} else if (r != SSL_TLSEXT_ERR_NOACK) {
SSLfatal(s, SSL_AD_NO_APPLICATION_PROTOCOL, SSL_F_TLS_HANDLE_ALPN,
SSL_R_NO_APPLICATION_PROTOCOL);
return 0;
}
/*
* If r == SSL_TLSEXT_ERR_NOACK then behave as if no callback was
* present.
*/
}
/* Check ALPN is consistent with session */
if (s->session->ext.alpn_selected != NULL) {
/* Not consistent so can't be used for early_data */
s->ext.early_data_ok = 0;
}
return 1;
}
WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
{
const SSL_CIPHER *cipher;
if (wst == WORK_MORE_A) {
int rv = tls_early_post_process_client_hello(s);
if (rv == 0) {
/* SSLfatal() was already called */
goto err;
}
if (rv < 0)
return WORK_MORE_A;
wst = WORK_MORE_B;
}
if (wst == WORK_MORE_B) {
if (!s->hit || SSL_IS_TLS13(s)) {
/* Let cert callback update server certificates if required */
if (!s->hit) {
if (s->cert->cert_cb != NULL) {
int rv = s->cert->cert_cb(s, s->cert->cert_cb_arg);
if (rv == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
SSL_R_CERT_CB_ERROR);
goto err;
}
if (rv < 0) {
s->rwstate = SSL_X509_LOOKUP;
return WORK_MORE_B;
}
s->rwstate = SSL_NOTHING;
}
if (!tls1_set_server_sigalgs(s)) {
/* SSLfatal already called */
goto err;
}
}
/* In TLSv1.3 we selected the ciphersuite before resumption */
if (!SSL_IS_TLS13(s)) {
cipher =
ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_POST_PROCESS_CLIENT_HELLO,
SSL_R_NO_SHARED_CIPHER);
goto err;
}
s->s3->tmp.new_cipher = cipher;
}
if (!s->hit) {
if (!tls_choose_sigalg(s, 1)) {
/* SSLfatal already called */
goto err;
}
/* check whether we should disable session resumption */
if (s->not_resumable_session_cb != NULL)
s->session->not_resumable =
s->not_resumable_session_cb(s,
((s->s3->tmp.new_cipher->algorithm_mkey
& (SSL_kDHE | SSL_kECDHE)) != 0));
if (s->session->not_resumable)
/* do not send a session ticket */
s->ext.ticket_expected = 0;
}
} else {
/* Session-id reuse */
s->s3->tmp.new_cipher = s->session->cipher;
}
/*-
* we now have the following setup.
* client_random
* cipher_list - our preferred list of ciphers
* ciphers - the clients preferred list of ciphers
* compression - basically ignored right now
* ssl version is set - sslv3
* s->session - The ssl session has been setup.
* s->hit - session reuse flag
* s->s3->tmp.new_cipher- the new cipher to use.
*/
/*
* Call status_request callback if needed. Has to be done after the
* certificate callbacks etc above.
*/
if (!tls_handle_status_request(s)) {
/* SSLfatal() already called */
goto err;
}
/*
* Call alpn_select callback if needed. Has to be done after SNI and
* cipher negotiation (HTTP/2 restricts permitted ciphers). In TLSv1.3
* we already did this because cipher negotiation happens earlier, and
* we must handle ALPN before we decide whether to accept early_data.
*/
if (!SSL_IS_TLS13(s) && !tls_handle_alpn(s)) {
/* SSLfatal() already called */
goto err;
}
wst = WORK_MORE_C;
}
#ifndef OPENSSL_NO_SRP
if (wst == WORK_MORE_C) {
int ret;
if ((ret = ssl_check_srp_ext_ClientHello(s)) == 0) {
/*
* callback indicates further work to be done
*/
s->rwstate = SSL_X509_LOOKUP;
return WORK_MORE_C;
}
if (ret < 0) {
/* SSLfatal() already called */
goto err;
}
}
#endif
return WORK_FINISHED_STOP;
err:
return WORK_ERROR;
}
int tls_construct_server_hello(SSL *s, WPACKET *pkt)
{
int compm;
size_t sl, len;
int version;
unsigned char *session_id;
int usetls13 = SSL_IS_TLS13(s) || s->hello_retry_request == SSL_HRR_PENDING;
version = usetls13 ? TLS1_2_VERSION : s->version;
if (!WPACKET_put_bytes_u16(pkt, version)
/*
* Random stuff. Filling of the server_random takes place in
* tls_process_client_hello()
*/
|| !WPACKET_memcpy(pkt,
s->hello_retry_request == SSL_HRR_PENDING
? hrrrandom : s->s3->server_random,
SSL3_RANDOM_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
/*-
* There are several cases for the session ID to send
* back in the server hello:
* - For session reuse from the session cache,
* we send back the old session ID.
* - If stateless session reuse (using a session ticket)
* is successful, we send back the client's "session ID"
* (which doesn't actually identify the session).
* - If it is a new session, we send back the new
* session ID.
* - However, if we want the new session to be single-use,
* we send back a 0-length session ID.
* - In TLSv1.3 we echo back the session id sent to us by the client
* regardless
* s->hit is non-zero in either case of session reuse,
* so the following won't overwrite an ID that we're supposed
* to send back.
*/
if (s->session->not_resumable ||
(!(s->ctx->session_cache_mode & SSL_SESS_CACHE_SERVER)
&& !s->hit))
s->session->session_id_length = 0;
if (usetls13) {
sl = s->tmp_session_id_len;
session_id = s->tmp_session_id;
} else {
sl = s->session->session_id_length;
session_id = s->session->session_id;
}
if (sl > sizeof(s->session->session_id)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* set up the compression method */
#ifdef OPENSSL_NO_COMP
compm = 0;
#else
if (usetls13 || s->s3->tmp.new_compression == NULL)
compm = 0;
else
compm = s->s3->tmp.new_compression->id;
#endif
if (!WPACKET_sub_memcpy_u8(pkt, session_id, sl)
|| !s->method->put_cipher_by_char(s->s3->tmp.new_cipher, pkt, &len)
|| !WPACKET_put_bytes_u8(pkt, compm)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_SERVER_HELLO,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (!tls_construct_extensions(s, pkt,
s->hello_retry_request == SSL_HRR_PENDING
? SSL_EXT_TLS1_3_HELLO_RETRY_REQUEST
: (SSL_IS_TLS13(s)
? SSL_EXT_TLS1_3_SERVER_HELLO
: SSL_EXT_TLS1_2_SERVER_HELLO),
NULL, 0)) {
/* SSLfatal() already called */
return 0;
}
if (s->hello_retry_request == SSL_HRR_PENDING) {
/* Ditch the session. We'll create a new one next time around */
SSL_SESSION_free(s->session);
s->session = NULL;
s->hit = 0;
/*
* Re-initialise the Transcript Hash. We're going to prepopulate it with
* a synthetic message_hash in place of ClientHello1.
*/
if (!create_synthetic_message_hash(s, NULL, 0, NULL, 0)) {
/* SSLfatal() already called */
return 0;
}
} else if (!(s->verify_mode & SSL_VERIFY_PEER)
&& !ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */;
return 0;
}
return 1;
}
int tls_construct_server_done(SSL *s, WPACKET *pkt)
{
if (!s->s3->tmp.cert_request) {
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
return 0;
}
}
return 1;
}
int tls_construct_server_key_exchange(SSL *s, WPACKET *pkt)
{
#ifndef OPENSSL_NO_DH
EVP_PKEY *pkdh = NULL;
#endif
#ifndef OPENSSL_NO_EC
unsigned char *encodedPoint = NULL;
size_t encodedlen = 0;
int curve_id = 0;
#endif
const SIGALG_LOOKUP *lu = s->s3->tmp.sigalg;
int i;
unsigned long type;
const BIGNUM *r[4];
EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
EVP_PKEY_CTX *pctx = NULL;
size_t paramlen, paramoffset;
if (!WPACKET_get_total_written(pkt, &paramoffset)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
if (md_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
goto err;
}
type = s->s3->tmp.new_cipher->algorithm_mkey;
r[0] = r[1] = r[2] = r[3] = NULL;
#ifndef OPENSSL_NO_PSK
/* Plain PSK or RSAPSK nothing to do */
if (type & (SSL_kPSK | SSL_kRSAPSK)) {
} else
#endif /* !OPENSSL_NO_PSK */
#ifndef OPENSSL_NO_DH
if (type & (SSL_kDHE | SSL_kDHEPSK)) {
CERT *cert = s->cert;
EVP_PKEY *pkdhp = NULL;
DH *dh;
if (s->cert->dh_tmp_auto) {
DH *dhp = ssl_get_auto_dh(s);
pkdh = EVP_PKEY_new();
if (pkdh == NULL || dhp == NULL) {
DH_free(dhp);
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_PKEY_assign_DH(pkdh, dhp);
pkdhp = pkdh;
} else {
pkdhp = cert->dh_tmp;
}
if ((pkdhp == NULL) && (s->cert->dh_tmp_cb != NULL)) {
DH *dhp = s->cert->dh_tmp_cb(s, 0, 1024);
pkdh = ssl_dh_to_pkey(dhp);
if (pkdh == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
pkdhp = pkdh;
}
if (pkdhp == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (!ssl_security(s, SSL_SECOP_TMP_DH,
EVP_PKEY_security_bits(pkdhp), 0, pkdhp)) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
SSL_R_DH_KEY_TOO_SMALL);
goto err;
}
if (s->s3->tmp.pkey != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
s->s3->tmp.pkey = ssl_generate_pkey(pkdhp);
if (s->s3->tmp.pkey == NULL) {
/* SSLfatal() already called */
goto err;
}
dh = EVP_PKEY_get0_DH(s->s3->tmp.pkey);
if (dh == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
EVP_PKEY_free(pkdh);
pkdh = NULL;
DH_get0_pqg(dh, &r[0], NULL, &r[1]);
DH_get0_key(dh, &r[2], NULL);
} else
#endif
#ifndef OPENSSL_NO_EC
if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
if (s->s3->tmp.pkey != NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Get NID of appropriate shared curve */
curve_id = tls1_shared_group(s, -2);
if (curve_id == 0) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
SSL_R_UNSUPPORTED_ELLIPTIC_CURVE);
goto err;
}
s->s3->tmp.pkey = ssl_generate_pkey_group(s, curve_id);
/* Generate a new key for this curve */
if (s->s3->tmp.pkey == NULL) {
/* SSLfatal() already called */
goto err;
}
/* Encode the public key. */
encodedlen = EVP_PKEY_get1_tls_encodedpoint(s->s3->tmp.pkey,
&encodedPoint);
if (encodedlen == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_EC_LIB);
goto err;
}
/*
* We'll generate the serverKeyExchange message explicitly so we
* can set these to NULLs
*/
r[0] = NULL;
r[1] = NULL;
r[2] = NULL;
r[3] = NULL;
} else
#endif /* !OPENSSL_NO_EC */
#ifndef OPENSSL_NO_SRP
if (type & SSL_kSRP) {
if ((s->srp_ctx.N == NULL) ||
(s->srp_ctx.g == NULL) ||
(s->srp_ctx.s == NULL) || (s->srp_ctx.B == NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
SSL_R_MISSING_SRP_PARAM);
goto err;
}
r[0] = s->srp_ctx.N;
r[1] = s->srp_ctx.g;
r[2] = s->srp_ctx.s;
r[3] = s->srp_ctx.B;
} else
#endif
{
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE);
goto err;
}
if (((s->s3->tmp.new_cipher->algorithm_auth & (SSL_aNULL | SSL_aSRP)) != 0)
|| ((s->s3->tmp.new_cipher->algorithm_mkey & SSL_PSK)) != 0) {
lu = NULL;
} else if (lu == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE, ERR_R_INTERNAL_ERROR);
goto err;
}
#ifndef OPENSSL_NO_PSK
if (type & SSL_PSK) {
size_t len = (s->cert->psk_identity_hint == NULL)
? 0 : strlen(s->cert->psk_identity_hint);
/*
* It should not happen that len > PSK_MAX_IDENTITY_LEN - we already
* checked this when we set the identity hint - but just in case
*/
if (len > PSK_MAX_IDENTITY_LEN
|| !WPACKET_sub_memcpy_u16(pkt, s->cert->psk_identity_hint,
len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
}
#endif
for (i = 0; i < 4 && r[i] != NULL; i++) {
unsigned char *binval;
int res;
#ifndef OPENSSL_NO_SRP
if ((i == 2) && (type & SSL_kSRP)) {
res = WPACKET_start_sub_packet_u8(pkt);
} else
#endif
res = WPACKET_start_sub_packet_u16(pkt);
if (!res) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
#ifndef OPENSSL_NO_DH
/*-
* for interoperability with some versions of the Microsoft TLS
* stack, we need to zero pad the DHE pub key to the same length
* as the prime
*/
if ((i == 2) && (type & (SSL_kDHE | SSL_kDHEPSK))) {
size_t len = BN_num_bytes(r[0]) - BN_num_bytes(r[2]);
if (len > 0) {
if (!WPACKET_allocate_bytes(pkt, len, &binval)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
memset(binval, 0, len);
}
}
#endif
if (!WPACKET_allocate_bytes(pkt, BN_num_bytes(r[i]), &binval)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
BN_bn2bin(r[i], binval);
}
#ifndef OPENSSL_NO_EC
if (type & (SSL_kECDHE | SSL_kECDHEPSK)) {
/*
* We only support named (not generic) curves. In this situation, the
* ServerKeyExchange message has: [1 byte CurveType], [2 byte CurveName]
* [1 byte length of encoded point], followed by the actual encoded
* point itself
*/
if (!WPACKET_put_bytes_u8(pkt, NAMED_CURVE_TYPE)
|| !WPACKET_put_bytes_u8(pkt, 0)
|| !WPACKET_put_bytes_u8(pkt, curve_id)
|| !WPACKET_sub_memcpy_u8(pkt, encodedPoint, encodedlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(encodedPoint);
encodedPoint = NULL;
}
#endif
/* not anonymous */
if (lu != NULL) {
EVP_PKEY *pkey = s->s3->tmp.cert->privatekey;
const EVP_MD *md;
unsigned char *sigbytes1, *sigbytes2, *tbs;
size_t siglen, tbslen;
int rv;
if (pkey == NULL || !tls1_lookup_md(lu, &md)) {
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Get length of the parameters we have written above */
if (!WPACKET_get_length(pkt, &paramlen)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* send signature algorithm */
if (SSL_USE_SIGALGS(s) && !WPACKET_put_bytes_u16(pkt, lu->sigalg)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* Create the signature. We don't know the actual length of the sig
* until after we've created it, so we reserve enough bytes for it
* up front, and then properly allocate them in the WPACKET
* afterwards.
*/
siglen = EVP_PKEY_size(pkey);
if (!WPACKET_sub_reserve_bytes_u16(pkt, siglen, &sigbytes1)
|| EVP_DigestSignInit(md_ctx, &pctx, md, NULL, pkey) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
if (lu->sig == EVP_PKEY_RSA_PSS) {
if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0
|| EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, RSA_PSS_SALTLEN_DIGEST) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_EVP_LIB);
goto err;
}
}
tbslen = construct_key_exchange_tbs(s, &tbs,
s->init_buf->data + paramoffset,
paramlen);
if (tbslen == 0) {
/* SSLfatal() already called */
goto err;
}
rv = EVP_DigestSign(md_ctx, sigbytes1, &siglen, tbs, tbslen);
OPENSSL_free(tbs);
if (rv <= 0 || !WPACKET_sub_allocate_bytes_u16(pkt, siglen, &sigbytes2)
|| sigbytes1 != sigbytes2) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
goto err;
}
}
EVP_MD_CTX_free(md_ctx);
return 1;
err:
#ifndef OPENSSL_NO_DH
EVP_PKEY_free(pkdh);
#endif
#ifndef OPENSSL_NO_EC
OPENSSL_free(encodedPoint);
#endif
EVP_MD_CTX_free(md_ctx);
return 0;
}
int tls_construct_certificate_request(SSL *s, WPACKET *pkt)
{
if (SSL_IS_TLS13(s)) {
/* Send random context when doing post-handshake auth */
if (s->post_handshake_auth == SSL_PHA_REQUEST_PENDING) {
OPENSSL_free(s->pha_context);
s->pha_context_len = 32;
if ((s->pha_context = OPENSSL_malloc(s->pha_context_len)) == NULL
|| RAND_bytes(s->pha_context, s->pha_context_len) <= 0
|| !WPACKET_sub_memcpy_u8(pkt, s->pha_context, s->pha_context_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
ERR_R_INTERNAL_ERROR);
return 0;
}
/* reset the handshake hash back to just after the ClientFinished */
if (!tls13_restore_handshake_digest_for_pha(s)) {
/* SSLfatal() already called */
return 0;
}
} else {
if (!WPACKET_put_bytes_u8(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (!tls_construct_extensions(s, pkt,
SSL_EXT_TLS1_3_CERTIFICATE_REQUEST, NULL,
0)) {
/* SSLfatal() already called */
return 0;
}
goto done;
}
/* get the list of acceptable cert types */
if (!WPACKET_start_sub_packet_u8(pkt)
|| !ssl3_get_req_cert_type(s, pkt) || !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST, ERR_R_INTERNAL_ERROR);
return 0;
}
if (SSL_USE_SIGALGS(s)) {
const uint16_t *psigs;
size_t nl = tls12_get_psigalgs(s, 1, &psigs);
if (!WPACKET_start_sub_packet_u16(pkt)
|| !WPACKET_set_flags(pkt, WPACKET_FLAGS_NON_ZERO_LENGTH)
|| !tls12_copy_sigalgs(s, pkt, psigs, nl)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CERTIFICATE_REQUEST,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
if (!construct_ca_names(s, get_ca_names(s), pkt)) {
/* SSLfatal() already called */
return 0;
}
done:
s->certreqs_sent++;
s->s3->tmp.cert_request = 1;
return 1;
}
static int tls_process_cke_psk_preamble(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_PSK
unsigned char psk[PSK_MAX_PSK_LEN];
size_t psklen;
PACKET psk_identity;
if (!PACKET_get_length_prefixed_2(pkt, &psk_identity)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
SSL_R_LENGTH_MISMATCH);
return 0;
}
if (PACKET_remaining(&psk_identity) > PSK_MAX_IDENTITY_LEN) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
SSL_R_DATA_LENGTH_TOO_LONG);
return 0;
}
if (s->psk_server_callback == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
SSL_R_PSK_NO_SERVER_CB);
return 0;
}
if (!PACKET_strndup(&psk_identity, &s->session->psk_identity)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
ERR_R_INTERNAL_ERROR);
return 0;
}
psklen = s->psk_server_callback(s, s->session->psk_identity,
psk, sizeof(psk));
if (psklen > PSK_MAX_PSK_LEN) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
ERR_R_INTERNAL_ERROR);
return 0;
} else if (psklen == 0) {
/*
* PSK related to the given identity not found
*/
SSLfatal(s, SSL_AD_UNKNOWN_PSK_IDENTITY,
SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
SSL_R_PSK_IDENTITY_NOT_FOUND);
return 0;
}
OPENSSL_free(s->s3->tmp.psk);
s->s3->tmp.psk = OPENSSL_memdup(psk, psklen);
OPENSSL_cleanse(psk, psklen);
if (s->s3->tmp.psk == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE, ERR_R_MALLOC_FAILURE);
return 0;
}
s->s3->tmp.psklen = psklen;
return 1;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_PSK_PREAMBLE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_rsa(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_RSA
unsigned char rand_premaster_secret[SSL_MAX_MASTER_KEY_LENGTH];
int decrypt_len;
unsigned char decrypt_good, version_good;
size_t j, padding_len;
PACKET enc_premaster;
RSA *rsa = NULL;
unsigned char *rsa_decrypt = NULL;
int ret = 0;
rsa = EVP_PKEY_get0_RSA(s->cert->pkeys[SSL_PKEY_RSA].privatekey);
if (rsa == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
SSL_R_MISSING_RSA_CERTIFICATE);
return 0;
}
/* SSLv3 and pre-standard DTLS omit the length bytes. */
if (s->version == SSL3_VERSION || s->version == DTLS1_BAD_VER) {
enc_premaster = *pkt;
} else {
if (!PACKET_get_length_prefixed_2(pkt, &enc_premaster)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
SSL_R_LENGTH_MISMATCH);
return 0;
}
}
/*
* We want to be sure that the plaintext buffer size makes it safe to
* iterate over the entire size of a premaster secret
* (SSL_MAX_MASTER_KEY_LENGTH). Reject overly short RSA keys because
* their ciphertext cannot accommodate a premaster secret anyway.
*/
if (RSA_size(rsa) < SSL_MAX_MASTER_KEY_LENGTH) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
RSA_R_KEY_SIZE_TOO_SMALL);
return 0;
}
rsa_decrypt = OPENSSL_malloc(RSA_size(rsa));
if (rsa_decrypt == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
ERR_R_MALLOC_FAILURE);
return 0;
}
/*
* We must not leak whether a decryption failure occurs because of
* Bleichenbacher's attack on PKCS #1 v1.5 RSA padding (see RFC 2246,
* section 7.4.7.1). The code follows that advice of the TLS RFC and
* generates a random premaster secret for the case that the decrypt
* fails. See https://tools.ietf.org/html/rfc5246#section-7.4.7.1
*/
if (RAND_priv_bytes(rand_premaster_secret,
sizeof(rand_premaster_secret)) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* Decrypt with no padding. PKCS#1 padding will be removed as part of
* the timing-sensitive code below.
*/
/* TODO(size_t): Convert this function */
decrypt_len = (int)RSA_private_decrypt((int)PACKET_remaining(&enc_premaster),
PACKET_data(&enc_premaster),
rsa_decrypt, rsa, RSA_NO_PADDING);
if (decrypt_len < 0) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
ERR_R_INTERNAL_ERROR);
goto err;
}
/* Check the padding. See RFC 3447, section 7.2.2. */
/*
* The smallest padded premaster is 11 bytes of overhead. Small keys
* are publicly invalid, so this may return immediately. This ensures
* PS is at least 8 bytes.
*/
if (decrypt_len < 11 + SSL_MAX_MASTER_KEY_LENGTH) {
SSLfatal(s, SSL_AD_DECRYPT_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
SSL_R_DECRYPTION_FAILED);
goto err;
}
padding_len = decrypt_len - SSL_MAX_MASTER_KEY_LENGTH;
decrypt_good = constant_time_eq_int_8(rsa_decrypt[0], 0) &
constant_time_eq_int_8(rsa_decrypt[1], 2);
for (j = 2; j < padding_len - 1; j++) {
decrypt_good &= ~constant_time_is_zero_8(rsa_decrypt[j]);
}
decrypt_good &= constant_time_is_zero_8(rsa_decrypt[padding_len - 1]);
/*
* If the version in the decrypted pre-master secret is correct then
* version_good will be 0xff, otherwise it'll be zero. The
* Klima-Pokorny-Rosa extension of Bleichenbacher's attack
* (http://eprint.iacr.org/2003/052/) exploits the version number
* check as a "bad version oracle". Thus version checks are done in
* constant time and are treated like any other decryption error.
*/
version_good =
constant_time_eq_8(rsa_decrypt[padding_len],
(unsigned)(s->client_version >> 8));
version_good &=
constant_time_eq_8(rsa_decrypt[padding_len + 1],
(unsigned)(s->client_version & 0xff));
/*
* The premaster secret must contain the same version number as the
* ClientHello to detect version rollback attacks (strangely, the
* protocol does not offer such protection for DH ciphersuites).
* However, buggy clients exist that send the negotiated protocol
* version instead if the server does not support the requested
* protocol version. If SSL_OP_TLS_ROLLBACK_BUG is set, tolerate such
* clients.
*/
if (s->options & SSL_OP_TLS_ROLLBACK_BUG) {
unsigned char workaround_good;
workaround_good = constant_time_eq_8(rsa_decrypt[padding_len],
(unsigned)(s->version >> 8));
workaround_good &=
constant_time_eq_8(rsa_decrypt[padding_len + 1],
(unsigned)(s->version & 0xff));
version_good |= workaround_good;
}
/*
* Both decryption and version must be good for decrypt_good to
* remain non-zero (0xff).
*/
decrypt_good &= version_good;
/*
* Now copy rand_premaster_secret over from p using
* decrypt_good_mask. If decryption failed, then p does not
* contain valid plaintext, however, a check above guarantees
* it is still sufficiently large to read from.
*/
for (j = 0; j < sizeof(rand_premaster_secret); j++) {
rsa_decrypt[padding_len + j] =
constant_time_select_8(decrypt_good,
rsa_decrypt[padding_len + j],
rand_premaster_secret[j]);
}
if (!ssl_generate_master_secret(s, rsa_decrypt + padding_len,
sizeof(rand_premaster_secret), 0)) {
/* SSLfatal() already called */
goto err;
}
ret = 1;
err:
OPENSSL_free(rsa_decrypt);
return ret;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_RSA,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_dhe(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_DH
EVP_PKEY *skey = NULL;
DH *cdh;
unsigned int i;
BIGNUM *pub_key;
const unsigned char *data;
EVP_PKEY *ckey = NULL;
int ret = 0;
if (!PACKET_get_net_2(pkt, &i) || PACKET_remaining(pkt) != i) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG);
goto err;
}
skey = s->s3->tmp.pkey;
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (PACKET_remaining(pkt) == 0L) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
SSL_R_MISSING_TMP_DH_KEY);
goto err;
}
if (!PACKET_get_bytes(pkt, &data, i)) {
/* We already checked we have enough data */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
ERR_R_INTERNAL_ERROR);
goto err;
}
ckey = EVP_PKEY_new();
if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
SSL_R_BN_LIB);
goto err;
}
cdh = EVP_PKEY_get0_DH(ckey);
pub_key = BN_bin2bn(data, i, NULL);
if (pub_key == NULL || cdh == NULL || !DH_set0_key(cdh, pub_key, NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
ERR_R_INTERNAL_ERROR);
BN_free(pub_key);
goto err;
}
if (ssl_derive(s, skey, ckey, 1) == 0) {
/* SSLfatal() already called */
goto err;
}
ret = 1;
EVP_PKEY_free(s->s3->tmp.pkey);
s->s3->tmp.pkey = NULL;
err:
EVP_PKEY_free(ckey);
return ret;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_DHE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_ecdhe(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_EC
EVP_PKEY *skey = s->s3->tmp.pkey;
EVP_PKEY *ckey = NULL;
int ret = 0;
if (PACKET_remaining(pkt) == 0L) {
/* We don't support ECDH client auth */
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_F_TLS_PROCESS_CKE_ECDHE,
SSL_R_MISSING_TMP_ECDH_KEY);
goto err;
} else {
unsigned int i;
const unsigned char *data;
/*
* Get client's public key from encoded point in the
* ClientKeyExchange message.
*/
/* Get encoded point length */
if (!PACKET_get_1(pkt, &i) || !PACKET_get_bytes(pkt, &data, i)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
SSL_R_LENGTH_MISMATCH);
goto err;
}
if (skey == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
SSL_R_MISSING_TMP_ECDH_KEY);
goto err;
}
ckey = EVP_PKEY_new();
if (ckey == NULL || EVP_PKEY_copy_parameters(ckey, skey) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
ERR_R_EVP_LIB);
goto err;
}
if (EVP_PKEY_set1_tls_encodedpoint(ckey, data, i) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
ERR_R_EC_LIB);
goto err;
}
}
if (ssl_derive(s, skey, ckey, 1) == 0) {
/* SSLfatal() already called */
goto err;
}
ret = 1;
EVP_PKEY_free(s->s3->tmp.pkey);
s->s3->tmp.pkey = NULL;
err:
EVP_PKEY_free(ckey);
return ret;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_ECDHE,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_srp(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_SRP
unsigned int i;
const unsigned char *data;
if (!PACKET_get_net_2(pkt, &i)
|| !PACKET_get_bytes(pkt, &data, i)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
SSL_R_BAD_SRP_A_LENGTH);
return 0;
}
if ((s->srp_ctx.A = BN_bin2bn(data, i, NULL)) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
ERR_R_BN_LIB);
return 0;
}
if (BN_ucmp(s->srp_ctx.A, s->srp_ctx.N) >= 0 || BN_is_zero(s->srp_ctx.A)) {
SSLfatal(s, SSL_AD_ILLEGAL_PARAMETER, SSL_F_TLS_PROCESS_CKE_SRP,
SSL_R_BAD_SRP_PARAMETERS);
return 0;
}
OPENSSL_free(s->session->srp_username);
s->session->srp_username = OPENSSL_strdup(s->srp_ctx.login);
if (s->session->srp_username == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
ERR_R_MALLOC_FAILURE);
return 0;
}
if (!srp_generate_server_master_secret(s)) {
/* SSLfatal() already called */
return 0;
}
return 1;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_SRP,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
static int tls_process_cke_gost(SSL *s, PACKET *pkt)
{
#ifndef OPENSSL_NO_GOST
EVP_PKEY_CTX *pkey_ctx;
EVP_PKEY *client_pub_pkey = NULL, *pk = NULL;
unsigned char premaster_secret[32];
const unsigned char *start;
size_t outlen = 32, inlen;
unsigned long alg_a;
unsigned int asn1id, asn1len;
int ret = 0;
PACKET encdata;
/* Get our certificate private key */
alg_a = s->s3->tmp.new_cipher->algorithm_auth;
if (alg_a & SSL_aGOST12) {
/*
* New GOST ciphersuites have SSL_aGOST01 bit too
*/
pk = s->cert->pkeys[SSL_PKEY_GOST12_512].privatekey;
if (pk == NULL) {
pk = s->cert->pkeys[SSL_PKEY_GOST12_256].privatekey;
}
if (pk == NULL) {
pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
}
} else if (alg_a & SSL_aGOST01) {
pk = s->cert->pkeys[SSL_PKEY_GOST01].privatekey;
}
pkey_ctx = EVP_PKEY_CTX_new(pk, NULL);
if (pkey_ctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
ERR_R_MALLOC_FAILURE);
return 0;
}
if (EVP_PKEY_decrypt_init(pkey_ctx) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* If client certificate is present and is of the same type, maybe
* use it for key exchange. Don't mind errors from
* EVP_PKEY_derive_set_peer, because it is completely valid to use a
* client certificate for authorization only.
*/
client_pub_pkey = X509_get0_pubkey(s->session->peer);
if (client_pub_pkey) {
if (EVP_PKEY_derive_set_peer(pkey_ctx, client_pub_pkey) <= 0)
ERR_clear_error();
}
/* Decrypt session key */
if (!PACKET_get_1(pkt, &asn1id)
|| asn1id != (V_ASN1_SEQUENCE | V_ASN1_CONSTRUCTED)
|| !PACKET_peek_1(pkt, &asn1len)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
SSL_R_DECRYPTION_FAILED);
goto err;
}
if (asn1len == 0x81) {
/*
* Long form length. Should only be one byte of length. Anything else
* isn't supported.
* We did a successful peek before so this shouldn't fail
*/
if (!PACKET_forward(pkt, 1)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
SSL_R_DECRYPTION_FAILED);
goto err;
}
} else if (asn1len >= 0x80) {
/*
* Indefinite length, or more than one long form length bytes. We don't
* support it
*/
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
SSL_R_DECRYPTION_FAILED);
goto err;
} /* else short form length */
if (!PACKET_as_length_prefixed_1(pkt, &encdata)) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
SSL_R_DECRYPTION_FAILED);
goto err;
}
inlen = PACKET_remaining(&encdata);
start = PACKET_data(&encdata);
if (EVP_PKEY_decrypt(pkey_ctx, premaster_secret, &outlen, start,
inlen) <= 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
SSL_R_DECRYPTION_FAILED);
goto err;
}
/* Generate master secret */
if (!ssl_generate_master_secret(s, premaster_secret,
sizeof(premaster_secret), 0)) {
/* SSLfatal() already called */
goto err;
}
/* Check if pubkey from client certificate was used */
if (EVP_PKEY_CTX_ctrl(pkey_ctx, -1, -1, EVP_PKEY_CTRL_PEER_KEY, 2,
NULL) > 0)
s->statem.no_cert_verify = 1;
ret = 1;
err:
EVP_PKEY_CTX_free(pkey_ctx);
return ret;
#else
/* Should never happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CKE_GOST,
ERR_R_INTERNAL_ERROR);
return 0;
#endif
}
MSG_PROCESS_RETURN tls_process_client_key_exchange(SSL *s, PACKET *pkt)
{
unsigned long alg_k;
alg_k = s->s3->tmp.new_cipher->algorithm_mkey;
/* For PSK parse and retrieve identity, obtain PSK key */
if ((alg_k & SSL_PSK) && !tls_process_cke_psk_preamble(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
if (alg_k & SSL_kPSK) {
/* Identity extracted earlier: should be nothing left */
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
SSL_R_LENGTH_MISMATCH);
goto err;
}
/* PSK handled by ssl_generate_master_secret */
if (!ssl_generate_master_secret(s, NULL, 0, 0)) {
/* SSLfatal() already called */
goto err;
}
} else if (alg_k & (SSL_kRSA | SSL_kRSAPSK)) {
if (!tls_process_cke_rsa(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
} else if (alg_k & (SSL_kDHE | SSL_kDHEPSK)) {
if (!tls_process_cke_dhe(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
} else if (alg_k & (SSL_kECDHE | SSL_kECDHEPSK)) {
if (!tls_process_cke_ecdhe(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
} else if (alg_k & SSL_kSRP) {
if (!tls_process_cke_srp(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
} else if (alg_k & SSL_kGOST) {
if (!tls_process_cke_gost(s, pkt)) {
/* SSLfatal() already called */
goto err;
}
} else {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CLIENT_KEY_EXCHANGE,
SSL_R_UNKNOWN_CIPHER_TYPE);
goto err;
}
return MSG_PROCESS_CONTINUE_PROCESSING;
err:
#ifndef OPENSSL_NO_PSK
OPENSSL_clear_free(s->s3->tmp.psk, s->s3->tmp.psklen);
s->s3->tmp.psk = NULL;
#endif
return MSG_PROCESS_ERROR;
}
WORK_STATE tls_post_process_client_key_exchange(SSL *s, WORK_STATE wst)
{
#ifndef OPENSSL_NO_SCTP
if (wst == WORK_MORE_A) {
if (SSL_IS_DTLS(s)) {
unsigned char sctpauthkey[64];
char labelbuffer[sizeof(DTLS1_SCTP_AUTH_LABEL)];
size_t labellen;
/*
* Add new shared key for SCTP-Auth, will be ignored if no SCTP
* used.
*/
memcpy(labelbuffer, DTLS1_SCTP_AUTH_LABEL,
sizeof(DTLS1_SCTP_AUTH_LABEL));
/* Don't include the terminating zero. */
labellen = sizeof(labelbuffer) - 1;
if (s->mode & SSL_MODE_DTLS_SCTP_LABEL_LENGTH_BUG)
labellen += 1;
if (SSL_export_keying_material(s, sctpauthkey,
sizeof(sctpauthkey), labelbuffer,
labellen, NULL, 0,
0) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
BIO_ctrl(SSL_get_wbio(s), BIO_CTRL_DGRAM_SCTP_ADD_AUTH_KEY,
sizeof(sctpauthkey), sctpauthkey);
}
}
#endif
if (s->statem.no_cert_verify || !s->session->peer) {
/*
* No certificate verify or no peer certificate so we no longer need
* the handshake_buffer
*/
if (!ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
return WORK_FINISHED_CONTINUE;
} else {
if (!s->s3->handshake_buffer) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_POST_PROCESS_CLIENT_KEY_EXCHANGE,
ERR_R_INTERNAL_ERROR);
return WORK_ERROR;
}
/*
* For sigalgs freeze the handshake buffer. If we support
* extms we've done this already so this is a no-op
*/
if (!ssl3_digest_cached_records(s, 1)) {
/* SSLfatal() already called */
return WORK_ERROR;
}
}
return WORK_FINISHED_CONTINUE;
}
MSG_PROCESS_RETURN tls_process_client_certificate(SSL *s, PACKET *pkt)
{
int i;
MSG_PROCESS_RETURN ret = MSG_PROCESS_ERROR;
X509 *x = NULL;
unsigned long l;
const unsigned char *certstart, *certbytes;
STACK_OF(X509) *sk = NULL;
PACKET spkt, context;
size_t chainidx;
SSL_SESSION *new_sess = NULL;
/*
* To get this far we must have read encrypted data from the client. We no
* longer tolerate unencrypted alerts. This value is ignored if less than
* TLSv1.3
*/
s->statem.enc_read_state = ENC_READ_STATE_VALID;
if ((sk = sk_X509_new_null()) == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
ERR_R_MALLOC_FAILURE);
goto err;
}
if (SSL_IS_TLS13(s) && (!PACKET_get_length_prefixed_1(pkt, &context)
|| (s->pha_context == NULL && PACKET_remaining(&context) != 0)
|| (s->pha_context != NULL &&
!PACKET_equal(&context, s->pha_context, s->pha_context_len)))) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_INVALID_CONTEXT);
goto err;
}
if (!PACKET_get_length_prefixed_3(pkt, &spkt)
|| PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_LENGTH_MISMATCH);
goto err;
}
for (chainidx = 0; PACKET_remaining(&spkt) > 0; chainidx++) {
if (!PACKET_get_net_3(&spkt, &l)
|| !PACKET_get_bytes(&spkt, &certbytes, l)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
certstart = certbytes;
x = d2i_X509(NULL, (const unsigned char **)&certbytes, l);
if (x == NULL) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, ERR_R_ASN1_LIB);
goto err;
}
if (certbytes != (certstart + l)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_CERT_LENGTH_MISMATCH);
goto err;
}
if (SSL_IS_TLS13(s)) {
RAW_EXTENSION *rawexts = NULL;
PACKET extensions;
if (!PACKET_get_length_prefixed_2(&spkt, &extensions)) {
SSLfatal(s, SSL_AD_DECODE_ERROR,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_BAD_LENGTH);
goto err;
}
if (!tls_collect_extensions(s, &extensions,
SSL_EXT_TLS1_3_CERTIFICATE, &rawexts,
NULL, chainidx == 0)
|| !tls_parse_all_extensions(s, SSL_EXT_TLS1_3_CERTIFICATE,
rawexts, x, chainidx,
PACKET_remaining(&spkt) == 0)) {
OPENSSL_free(rawexts);
goto err;
}
OPENSSL_free(rawexts);
}
if (!sk_X509_push(sk, x)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
ERR_R_MALLOC_FAILURE);
goto err;
}
x = NULL;
}
if (sk_X509_num(sk) <= 0) {
/* TLS does not mind 0 certs returned */
if (s->version == SSL3_VERSION) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_NO_CERTIFICATES_RETURNED);
goto err;
}
/* Fail for TLS only if we required a certificate */
else if ((s->verify_mode & SSL_VERIFY_PEER) &&
(s->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)) {
SSLfatal(s, SSL_AD_CERTIFICATE_REQUIRED,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE);
goto err;
}
/* No client certificate so digest cached records */
if (s->s3->handshake_buffer && !ssl3_digest_cached_records(s, 0)) {
/* SSLfatal() already called */
goto err;
}
} else {
EVP_PKEY *pkey;
i = ssl_verify_cert_chain(s, sk);
if (i <= 0) {
SSLfatal(s, ssl_x509err2alert(s->verify_result),
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_CERTIFICATE_VERIFY_FAILED);
goto err;
}
if (i > 1) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE, i);
goto err;
}
pkey = X509_get0_pubkey(sk_X509_value(sk, 0));
if (pkey == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
SSL_R_UNKNOWN_CERTIFICATE_TYPE);
goto err;
}
}
/*
* Sessions must be immutable once they go into the session cache. Otherwise
* we can get multi-thread problems. Therefore we don't "update" sessions,
* we replace them with a duplicate. Here, we need to do this every time
* a new certificate is received via post-handshake authentication, as the
* session may have already gone into the session cache.
*/
if (s->post_handshake_auth == SSL_PHA_REQUESTED) {
if ((new_sess = ssl_session_dup(s->session, 0)) == 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_PROCESS_CLIENT_CERTIFICATE,
ERR_R_MALLOC_FAILURE);
goto err;
}
SSL_SESSION_free(s->session);
s->session = new_sess;
}
X509_free(s->session->peer);
s->session->peer = sk_X509_shift(sk);
s->session->verify_result = s->verify_result;
sk_X509_pop_free(s->session->peer_chain, X509_free);
s->session->peer_chain = sk;
/*
* Freeze the handshake buffer. For <TLS1.3 we do this after the CKE
* message
*/
if (SSL_IS_TLS13(s) && !ssl3_digest_cached_records(s, 1)) {
/* SSLfatal() already called */
goto err;
}
/*
* Inconsistency alert: cert_chain does *not* include the peer's own
* certificate, while we do include it in statem_clnt.c
*/
sk = NULL;
/* Save the current hash state for when we receive the CertificateVerify */
if (SSL_IS_TLS13(s)) {
if (!ssl_handshake_hash(s, s->cert_verify_hash,
sizeof(s->cert_verify_hash),
&s->cert_verify_hash_len)) {
/* SSLfatal() already called */
goto err;
}
/* Resend session tickets */
s->sent_tickets = 0;
}
ret = MSG_PROCESS_CONTINUE_READING;
err:
X509_free(x);
sk_X509_pop_free(sk, X509_free);
return ret;
}
int tls_construct_server_certificate(SSL *s, WPACKET *pkt)
{
CERT_PKEY *cpk = s->s3->tmp.cert;
if (cpk == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
return 0;
}
/*
* In TLSv1.3 the certificate chain is always preceded by a 0 length context
* for the server Certificate message
*/
if (SSL_IS_TLS13(s) && !WPACKET_put_bytes_u8(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_SERVER_CERTIFICATE, ERR_R_INTERNAL_ERROR);
return 0;
}
if (!ssl3_output_cert_chain(s, pkt, cpk)) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
static int create_ticket_prequel(SSL *s, WPACKET *pkt, uint32_t age_add,
unsigned char *tick_nonce)
{
/*
* Ticket lifetime hint: For TLSv1.2 this is advisory only and we leave this
* unspecified for resumed session (for simplicity).
* In TLSv1.3 we reset the "time" field above, and always specify the
* timeout.
*/
if (!WPACKET_put_bytes_u32(pkt,
(s->hit && !SSL_IS_TLS13(s))
? 0 : s->session->timeout)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
ERR_R_INTERNAL_ERROR);
return 0;
}
if (SSL_IS_TLS13(s)) {
if (!WPACKET_put_bytes_u32(pkt, age_add)
|| !WPACKET_sub_memcpy_u8(pkt, tick_nonce, TICKET_NONCE_SIZE)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
ERR_R_INTERNAL_ERROR);
return 0;
}
}
/* Start the sub-packet for the actual ticket data */
if (!WPACKET_start_sub_packet_u16(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CREATE_TICKET_PREQUEL,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
static int construct_stateless_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
unsigned char *tick_nonce)
{
unsigned char *senc = NULL;
EVP_CIPHER_CTX *ctx = NULL;
HMAC_CTX *hctx = NULL;
unsigned char *p, *encdata1, *encdata2, *macdata1, *macdata2;
const unsigned char *const_p;
int len, slen_full, slen, lenfinal;
SSL_SESSION *sess;
unsigned int hlen;
SSL_CTX *tctx = s->session_ctx;
unsigned char iv[EVP_MAX_IV_LENGTH];
unsigned char key_name[TLSEXT_KEYNAME_LENGTH];
int iv_len, ok = 0;
size_t macoffset, macendoffset;
/* get session encoding length */
slen_full = i2d_SSL_SESSION(s->session, NULL);
/*
* Some length values are 16 bits, so forget it if session is too
* long
*/
if (slen_full == 0 || slen_full > 0xFF00) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
senc = OPENSSL_malloc(slen_full);
if (senc == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_MALLOC_FAILURE);
goto err;
}
ctx = EVP_CIPHER_CTX_new();
hctx = HMAC_CTX_new();
if (ctx == NULL || hctx == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_MALLOC_FAILURE);
goto err;
}
p = senc;
if (!i2d_SSL_SESSION(s->session, &p)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
/*
* create a fresh copy (not shared with other threads) to clean up
*/
const_p = senc;
sess = d2i_SSL_SESSION(NULL, &const_p, slen_full);
if (sess == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
slen = i2d_SSL_SESSION(sess, NULL);
if (slen == 0 || slen > slen_full) {
/* shouldn't ever happen */
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(sess);
goto err;
}
p = senc;
if (!i2d_SSL_SESSION(sess, &p)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_INTERNAL_ERROR);
SSL_SESSION_free(sess);
goto err;
}
SSL_SESSION_free(sess);
/*
* Initialize HMAC and cipher contexts. If callback present it does
* all the work otherwise use generated values from parent ctx.
*/
if (tctx->ext.ticket_key_cb) {
/* if 0 is returned, write an empty ticket */
int ret = tctx->ext.ticket_key_cb(s, key_name, iv, ctx,
hctx, 1);
if (ret == 0) {
/* Put timeout and length */
if (!WPACKET_put_bytes_u32(pkt, 0)
|| !WPACKET_put_bytes_u16(pkt, 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
HMAC_CTX_free(hctx);
return 1;
}
if (ret < 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
SSL_R_CALLBACK_FAILED);
goto err;
}
iv_len = EVP_CIPHER_CTX_iv_length(ctx);
} else {
const EVP_CIPHER *cipher = EVP_aes_256_cbc();
iv_len = EVP_CIPHER_iv_length(cipher);
if (RAND_bytes(iv, iv_len) <= 0
|| !EVP_EncryptInit_ex(ctx, cipher, NULL,
tctx->ext.secure->tick_aes_key, iv)
|| !HMAC_Init_ex(hctx, tctx->ext.secure->tick_hmac_key,
sizeof(tctx->ext.secure->tick_hmac_key),
EVP_sha256(), NULL)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
memcpy(key_name, tctx->ext.tick_key_name,
sizeof(tctx->ext.tick_key_name));
}
if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
/* SSLfatal() already called */
goto err;
}
if (!WPACKET_get_total_written(pkt, &macoffset)
/* Output key name */
|| !WPACKET_memcpy(pkt, key_name, sizeof(key_name))
/* output IV */
|| !WPACKET_memcpy(pkt, iv, iv_len)
|| !WPACKET_reserve_bytes(pkt, slen + EVP_MAX_BLOCK_LENGTH,
&encdata1)
/* Encrypt session data */
|| !EVP_EncryptUpdate(ctx, encdata1, &len, senc, slen)
|| !WPACKET_allocate_bytes(pkt, len, &encdata2)
|| encdata1 != encdata2
|| !EVP_EncryptFinal(ctx, encdata1 + len, &lenfinal)
|| !WPACKET_allocate_bytes(pkt, lenfinal, &encdata2)
|| encdata1 + len != encdata2
|| len + lenfinal > slen + EVP_MAX_BLOCK_LENGTH
|| !WPACKET_get_total_written(pkt, &macendoffset)
|| !HMAC_Update(hctx,
(unsigned char *)s->init_buf->data + macoffset,
macendoffset - macoffset)
|| !WPACKET_reserve_bytes(pkt, EVP_MAX_MD_SIZE, &macdata1)
|| !HMAC_Final(hctx, macdata1, &hlen)
|| hlen > EVP_MAX_MD_SIZE
|| !WPACKET_allocate_bytes(pkt, hlen, &macdata2)
|| macdata1 != macdata2) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_CONSTRUCT_STATELESS_TICKET, ERR_R_INTERNAL_ERROR);
goto err;
}
/* Close the sub-packet created by create_ticket_prequel() */
if (!WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATELESS_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
ok = 1;
err:
OPENSSL_free(senc);
EVP_CIPHER_CTX_free(ctx);
HMAC_CTX_free(hctx);
return ok;
}
static int construct_stateful_ticket(SSL *s, WPACKET *pkt, uint32_t age_add,
unsigned char *tick_nonce)
{
if (!create_ticket_prequel(s, pkt, age_add, tick_nonce)) {
/* SSLfatal() already called */
return 0;
}
if (!WPACKET_memcpy(pkt, s->session->session_id,
s->session->session_id_length)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_CONSTRUCT_STATEFUL_TICKET,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int tls_construct_new_session_ticket(SSL *s, WPACKET *pkt)
{
SSL_CTX *tctx = s->session_ctx;
unsigned char tick_nonce[TICKET_NONCE_SIZE];
union {
unsigned char age_add_c[sizeof(uint32_t)];
uint32_t age_add;
} age_add_u;
age_add_u.age_add = 0;
if (SSL_IS_TLS13(s)) {
size_t i, hashlen;
uint64_t nonce;
static const unsigned char nonce_label[] = "resumption";
const EVP_MD *md = ssl_handshake_md(s);
int hashleni = EVP_MD_size(md);
/* Ensure cast to size_t is safe */
if (!ossl_assert(hashleni >= 0)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
hashlen = (size_t)hashleni;
/*
* If we already sent one NewSessionTicket, or we resumed then
* s->session may already be in a cache and so we must not modify it.
* Instead we need to take a copy of it and modify that.
*/
if (s->sent_tickets != 0 || s->hit) {
SSL_SESSION *new_sess = ssl_session_dup(s->session, 0);
if (new_sess == NULL) {
/* SSLfatal already called */
goto err;
}
SSL_SESSION_free(s->session);
s->session = new_sess;
}
if (!ssl_generate_session_id(s, s->session)) {
/* SSLfatal() already called */
goto err;
}
if (RAND_bytes(age_add_u.age_add_c, sizeof(age_add_u)) <= 0) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
ERR_R_INTERNAL_ERROR);
goto err;
}
s->session->ext.tick_age_add = age_add_u.age_add;
nonce = s->next_ticket_nonce;
for (i = TICKET_NONCE_SIZE; i > 0; i--) {
tick_nonce[i - 1] = (unsigned char)(nonce & 0xff);
nonce >>= 8;
}
if (!tls13_hkdf_expand(s, md, s->resumption_master_secret,
nonce_label,
sizeof(nonce_label) - 1,
tick_nonce,
TICKET_NONCE_SIZE,
s->session->master_key,
hashlen, 1)) {
/* SSLfatal() already called */
goto err;
}
s->session->master_key_length = hashlen;
s->session->time = (long)time(NULL);
if (s->s3->alpn_selected != NULL) {
OPENSSL_free(s->session->ext.alpn_selected);
s->session->ext.alpn_selected =
OPENSSL_memdup(s->s3->alpn_selected, s->s3->alpn_selected_len);
if (s->session->ext.alpn_selected == NULL) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_NEW_SESSION_TICKET,
ERR_R_MALLOC_FAILURE);
goto err;
}
s->session->ext.alpn_selected_len = s->s3->alpn_selected_len;
}
s->session->ext.max_early_data = s->max_early_data;
}
if (tctx->generate_ticket_cb != NULL &&
tctx->generate_ticket_cb(s, tctx->ticket_cb_data) == 0)
goto err;
/*
* If we are using anti-replay protection then we behave as if
* SSL_OP_NO_TICKET is set - we are caching tickets anyway so there
* is no point in using full stateless tickets.
*/
if (SSL_IS_TLS13(s)
&& ((s->options & SSL_OP_NO_TICKET) != 0
|| (s->max_early_data > 0
&& (s->options & SSL_OP_NO_ANTI_REPLAY) == 0))) {
if (!construct_stateful_ticket(s, pkt, age_add_u.age_add, tick_nonce)) {
/* SSLfatal() already called */
goto err;
}
} else if (!construct_stateless_ticket(s, pkt, age_add_u.age_add,
tick_nonce)) {
/* SSLfatal() already called */
goto err;
}
if (SSL_IS_TLS13(s)) {
if (!tls_construct_extensions(s, pkt,
SSL_EXT_TLS1_3_NEW_SESSION_TICKET,
NULL, 0)) {
/* SSLfatal() already called */
goto err;
}
/*
* Increment both |sent_tickets| and |next_ticket_nonce|. |sent_tickets|
* gets reset to 0 if we send more tickets following a post-handshake
* auth, but |next_ticket_nonce| does not.
*/
s->sent_tickets++;
s->next_ticket_nonce++;
ssl_update_cache(s, SSL_SESS_CACHE_SERVER);
}
return 1;
err:
return 0;
}
/*
* In TLSv1.3 this is called from the extensions code, otherwise it is used to
* create a separate message. Returns 1 on success or 0 on failure.
*/
int tls_construct_cert_status_body(SSL *s, WPACKET *pkt)
{
if (!WPACKET_put_bytes_u8(pkt, s->ext.status_type)
|| !WPACKET_sub_memcpy_u24(pkt, s->ext.ocsp.resp,
s->ext.ocsp.resp_len)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_CONSTRUCT_CERT_STATUS_BODY,
ERR_R_INTERNAL_ERROR);
return 0;
}
return 1;
}
int tls_construct_cert_status(SSL *s, WPACKET *pkt)
{
if (!tls_construct_cert_status_body(s, pkt)) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
#ifndef OPENSSL_NO_NEXTPROTONEG
/*
* tls_process_next_proto reads a Next Protocol Negotiation handshake message.
* It sets the next_proto member in s if found
*/
MSG_PROCESS_RETURN tls_process_next_proto(SSL *s, PACKET *pkt)
{
PACKET next_proto, padding;
size_t next_proto_len;
/*-
* The payload looks like:
* uint8 proto_len;
* uint8 proto[proto_len];
* uint8 padding_len;
* uint8 padding[padding_len];
*/
if (!PACKET_get_length_prefixed_1(pkt, &next_proto)
|| !PACKET_get_length_prefixed_1(pkt, &padding)
|| PACKET_remaining(pkt) > 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (!PACKET_memdup(&next_proto, &s->ext.npn, &next_proto_len)) {
s->ext.npn_len = 0;
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_NEXT_PROTO,
ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
s->ext.npn_len = (unsigned char)next_proto_len;
return MSG_PROCESS_CONTINUE_READING;
}
#endif
static int tls_construct_encrypted_extensions(SSL *s, WPACKET *pkt)
{
if (!tls_construct_extensions(s, pkt, SSL_EXT_TLS1_3_ENCRYPTED_EXTENSIONS,
NULL, 0)) {
/* SSLfatal() already called */
return 0;
}
return 1;
}
MSG_PROCESS_RETURN tls_process_end_of_early_data(SSL *s, PACKET *pkt)
{
if (PACKET_remaining(pkt) != 0) {
SSLfatal(s, SSL_AD_DECODE_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
SSL_R_LENGTH_MISMATCH);
return MSG_PROCESS_ERROR;
}
if (s->early_data_state != SSL_EARLY_DATA_READING
&& s->early_data_state != SSL_EARLY_DATA_READ_RETRY) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
ERR_R_INTERNAL_ERROR);
return MSG_PROCESS_ERROR;
}
/*
* EndOfEarlyData signals a key change so the end of the message must be on
* a record boundary.
*/
if (RECORD_LAYER_processed_read_pending(&s->rlayer)) {
SSLfatal(s, SSL_AD_UNEXPECTED_MESSAGE,
SSL_F_TLS_PROCESS_END_OF_EARLY_DATA,
SSL_R_NOT_ON_RECORD_BOUNDARY);
return MSG_PROCESS_ERROR;
}
s->early_data_state = SSL_EARLY_DATA_FINISHED_READING;
if (!s->method->ssl3_enc->change_cipher_state(s,
SSL3_CC_HANDSHAKE | SSL3_CHANGE_CIPHER_SERVER_READ)) {
/* SSLfatal() already called */
return MSG_PROCESS_ERROR;
}
return MSG_PROCESS_CONTINUE_READING;
}

File Metadata

Mime Type
application/octet-stream
Expires
Tue, Jul 9, 11:01 AM (2 d)
Storage Engine
chunks
Storage Format
Chunks
Storage Handle
HnHeG8.63T1T
Default Alt Text
(5 MB)

Event Timeline